mirror of
https://git.vectorsigma.ru/public/atlantis.git
synced 2026-08-03 22:28:49 +00:00
Add BoltDB interface and some relevant tests
With BoltDB interface we are able to mock/stub and improve test coverage. Some other refactoring was required to make code aware and compatible with the new interface
This commit is contained in:
@@ -97,7 +97,7 @@ type DefaultCommandRunner struct {
|
||||
GlobalAutomerge bool
|
||||
PendingPlanFinder PendingPlanFinder
|
||||
WorkingDir WorkingDir
|
||||
DB *db.BoltDB
|
||||
DB db.BoltDB
|
||||
}
|
||||
|
||||
// RunAutoplanCommand runs plan when a pull request is opened or updated.
|
||||
|
||||
@@ -24,6 +24,8 @@ import (
|
||||
"github.com/google/go-github/v28/github"
|
||||
. "github.com/petergtz/pegomock"
|
||||
"github.com/runatlantis/atlantis/server/events"
|
||||
dbmocks "github.com/runatlantis/atlantis/server/events/db/mocks"
|
||||
dbmatchers "github.com/runatlantis/atlantis/server/events/db/mocks/matchers"
|
||||
"github.com/runatlantis/atlantis/server/events/mocks"
|
||||
"github.com/runatlantis/atlantis/server/events/mocks/matchers"
|
||||
"github.com/runatlantis/atlantis/server/events/models"
|
||||
@@ -43,6 +45,7 @@ var ch events.DefaultCommandRunner
|
||||
var pullLogger *logging.SimpleLogger
|
||||
var workingDir events.WorkingDir
|
||||
var pendingPlanFinder *mocks.MockPendingPlanFinder
|
||||
var boltDB *dbmocks.MockBoltDB
|
||||
|
||||
func setup(t *testing.T) *vcsmocks.MockClient {
|
||||
RegisterMockTestingT(t)
|
||||
@@ -57,6 +60,7 @@ func setup(t *testing.T) *vcsmocks.MockClient {
|
||||
projectCommandRunner = mocks.NewMockProjectCommandRunner()
|
||||
workingDir = mocks.NewMockWorkingDir()
|
||||
pendingPlanFinder = mocks.NewMockPendingPlanFinder()
|
||||
boltDB = dbmocks.NewMockBoltDB()
|
||||
When(logger.GetLevel()).ThenReturn(logging.Info)
|
||||
When(logger.NewLogger("runatlantis/atlantis#1", true, logging.Info)).
|
||||
ThenReturn(pullLogger)
|
||||
@@ -76,6 +80,7 @@ func setup(t *testing.T) *vcsmocks.MockClient {
|
||||
PendingPlanFinder: pendingPlanFinder,
|
||||
WorkingDir: workingDir,
|
||||
DisableApplyAll: false,
|
||||
DB: boltDB,
|
||||
}
|
||||
return vcsClient
|
||||
}
|
||||
@@ -234,3 +239,53 @@ func TestRunAutoplanCommand_DeletePlans(t *testing.T) {
|
||||
ch.RunAutoplanCommand(fixtures.GithubRepo, fixtures.GithubRepo, fixtures.Pull, fixtures.User)
|
||||
pendingPlanFinder.VerifyWasCalledOnce().DeletePlans(tmp)
|
||||
}
|
||||
|
||||
func TestApplyWithAutoMerge_VSCMerge(t *testing.T) {
|
||||
t.Log("if \"atlantis apply\" is run with automerge and at least one project" +
|
||||
" has a discarded plan, automerge should not take place")
|
||||
|
||||
vcsClient := setup(t)
|
||||
pull := &github.PullRequest{
|
||||
State: github.String("open"),
|
||||
}
|
||||
modelPull := models.PullRequest{State: models.OpenPullState}
|
||||
When(githubGetter.GetPullRequest(fixtures.GithubRepo, fixtures.Pull.Num)).ThenReturn(pull, nil)
|
||||
When(eventParsing.ParseGithubPull(pull)).ThenReturn(modelPull, modelPull.BaseRepo, fixtures.GithubRepo, nil)
|
||||
ch.GlobalAutomerge = true
|
||||
|
||||
ch.RunCommentCommand(fixtures.GithubRepo, &fixtures.GithubRepo, nil, fixtures.User, fixtures.Pull.Num, &events.CommentCommand{Name: models.ApplyCommand})
|
||||
vcsClient.VerifyWasCalledOnce().MergePull(modelPull)
|
||||
}
|
||||
|
||||
func TestApplyWithAutoMerge_DiscardedPlan(t *testing.T) {
|
||||
t.Log("if \"atlantis apply\" is run with automerge and at least one project" +
|
||||
" has a discarded plan, automerge should not take place")
|
||||
|
||||
setup(t)
|
||||
pull := &github.PullRequest{
|
||||
State: github.String("open"),
|
||||
}
|
||||
modelPull := models.PullRequest{State: models.OpenPullState}
|
||||
When(githubGetter.GetPullRequest(fixtures.GithubRepo, fixtures.Pull.Num)).ThenReturn(pull, nil)
|
||||
When(eventParsing.ParseGithubPull(pull)).ThenReturn(modelPull, modelPull.BaseRepo, fixtures.GithubRepo, nil)
|
||||
ch.GlobalAutomerge = true
|
||||
|
||||
ch.RunCommentCommand(fixtures.GithubRepo, &fixtures.GithubRepo, nil, fixtures.User, fixtures.Pull.Num, &events.CommentCommand{Name: models.ApplyCommand})
|
||||
projectStatuses := []models.ProjectStatus{
|
||||
{
|
||||
RepoRelDir: ".",
|
||||
Workspace: "default",
|
||||
ProjectName: "automerge-test",
|
||||
Status: models.DiscardedPlanStatus,
|
||||
},
|
||||
}
|
||||
pullStatus := models.PullStatus{
|
||||
Projects: projectStatuses,
|
||||
Pull: modelPull,
|
||||
}
|
||||
//When(boltDB.UpdatePullWithResults(modelPull, nil)).ThenReturn(pullStatus, nil)
|
||||
When(boltDB.UpdatePullWithResults(dbmatchers.EqModelsPullRequest(modelPull), dbmatchers.EqSliceOfModelsProjectResult(nil))).ThenReturn(pullStatus, nil)
|
||||
// TODO: stubbing here doesn't seem to work? pullStatus defined here is not actually returned and so I cannot uncomment the next two lines which would verify our scenario here
|
||||
//vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.GithubRepo, modelPull.Num, "not automerging because project at dir %q, workspace %q has status %q")
|
||||
//VerifyWasCalled(Never()).MergePull(modelPull)
|
||||
}
|
||||
|
||||
@@ -15,8 +15,17 @@ import (
|
||||
bolt "go.etcd.io/bbolt"
|
||||
)
|
||||
|
||||
// BoltDB is a database using BoltDB
|
||||
type BoltDB struct {
|
||||
//go:generate pegomock generate -m --use-experimental-model-gen --package mocks -o mocks/mock_boltdb.go BoltDB
|
||||
|
||||
// BoltDB interface defines the set of methods the DB implements. Use this to allow DB mocking when testing
|
||||
type BoltDB interface {
|
||||
UpdatePullWithResults(pull models.PullRequest, newResults []models.ProjectResult) (models.PullStatus, error)
|
||||
DeletePullStatus(pull models.PullRequest) error
|
||||
UpdateProjectStatus(pull models.PullRequest, workspace string, repoRelDir string, targetStatus models.ProjectPlanStatus) error
|
||||
}
|
||||
|
||||
// DefaultBoltDB is a database using BoltDB
|
||||
type DefaultBoltDB struct {
|
||||
db *bolt.DB
|
||||
locksBucketName []byte
|
||||
pullsBucketName []byte
|
||||
@@ -30,7 +39,7 @@ const (
|
||||
|
||||
// New returns a valid locker. We need to be able to write to dataDir
|
||||
// since bolt stores its data as a file
|
||||
func New(dataDir string) (*BoltDB, error) {
|
||||
func New(dataDir string) (*DefaultBoltDB, error) {
|
||||
if err := os.MkdirAll(dataDir, 0700); err != nil {
|
||||
return nil, errors.Wrap(err, "creating data dir")
|
||||
}
|
||||
@@ -56,19 +65,19 @@ func New(dataDir string) (*BoltDB, error) {
|
||||
return nil, errors.Wrap(err, "starting BoltDB")
|
||||
}
|
||||
// todo: close BoltDB when server is sigtermed
|
||||
return &BoltDB{db: db, locksBucketName: []byte(locksBucketName), pullsBucketName: []byte(pullsBucketName)}, nil
|
||||
return &DefaultBoltDB{db: db, locksBucketName: []byte(locksBucketName), pullsBucketName: []byte(pullsBucketName)}, nil
|
||||
}
|
||||
|
||||
// NewWithDB is used for testing.
|
||||
func NewWithDB(db *bolt.DB, bucket string) (*BoltDB, error) {
|
||||
return &BoltDB{db: db, locksBucketName: []byte(bucket), pullsBucketName: []byte(pullsBucketName)}, nil
|
||||
func NewWithDB(db *bolt.DB, bucket string) (*DefaultBoltDB, error) {
|
||||
return &DefaultBoltDB{db: db, locksBucketName: []byte(bucket), pullsBucketName: []byte(pullsBucketName)}, nil
|
||||
}
|
||||
|
||||
// TryLock attempts to create a new lock. If the lock is
|
||||
// acquired, it will return true and the lock returned will be newLock.
|
||||
// If the lock is not acquired, it will return false and the current
|
||||
// lock that is preventing this lock from being acquired.
|
||||
func (b *BoltDB) TryLock(newLock models.ProjectLock) (bool, models.ProjectLock, error) {
|
||||
func (b *DefaultBoltDB) TryLock(newLock models.ProjectLock) (bool, models.ProjectLock, error) {
|
||||
var lockAcquired bool
|
||||
var currLock models.ProjectLock
|
||||
key := b.lockKey(newLock.Project, newLock.Workspace)
|
||||
@@ -105,7 +114,7 @@ func (b *BoltDB) TryLock(newLock models.ProjectLock) (bool, models.ProjectLock,
|
||||
// If there is no lock, then it will return a nil pointer.
|
||||
// If there is a lock, then it will delete it, and then return a pointer
|
||||
// to the deleted lock.
|
||||
func (b *BoltDB) Unlock(p models.Project, workspace string) (*models.ProjectLock, error) {
|
||||
func (b *DefaultBoltDB) Unlock(p models.Project, workspace string) (*models.ProjectLock, error) {
|
||||
var lock models.ProjectLock
|
||||
foundLock := false
|
||||
key := b.lockKey(p, workspace)
|
||||
@@ -128,7 +137,7 @@ func (b *BoltDB) Unlock(p models.Project, workspace string) (*models.ProjectLock
|
||||
}
|
||||
|
||||
// List lists all current locks.
|
||||
func (b *BoltDB) List() ([]models.ProjectLock, error) {
|
||||
func (b *DefaultBoltDB) List() ([]models.ProjectLock, error) {
|
||||
var locks []models.ProjectLock
|
||||
var locksBytes [][]byte
|
||||
err := b.db.View(func(tx *bolt.Tx) error {
|
||||
@@ -156,7 +165,7 @@ func (b *BoltDB) List() ([]models.ProjectLock, error) {
|
||||
}
|
||||
|
||||
// UnlockByPull deletes all locks associated with that pull request and returns them.
|
||||
func (b *BoltDB) UnlockByPull(repoFullName string, pullNum int) ([]models.ProjectLock, error) {
|
||||
func (b *DefaultBoltDB) UnlockByPull(repoFullName string, pullNum int) ([]models.ProjectLock, error) {
|
||||
var locks []models.ProjectLock
|
||||
err := b.db.View(func(tx *bolt.Tx) error {
|
||||
c := tx.Bucket(b.locksBucketName).Cursor()
|
||||
@@ -188,7 +197,7 @@ func (b *BoltDB) UnlockByPull(repoFullName string, pullNum int) ([]models.Projec
|
||||
|
||||
// GetLock returns a pointer to the lock for that project and workspace.
|
||||
// If there is no lock, it returns a nil pointer.
|
||||
func (b *BoltDB) GetLock(p models.Project, workspace string) (*models.ProjectLock, error) {
|
||||
func (b *DefaultBoltDB) GetLock(p models.Project, workspace string) (*models.ProjectLock, error) {
|
||||
key := b.lockKey(p, workspace)
|
||||
var lockBytes []byte
|
||||
err := b.db.View(func(tx *bolt.Tx) error {
|
||||
@@ -216,7 +225,7 @@ func (b *BoltDB) GetLock(p models.Project, workspace string) (*models.ProjectLoc
|
||||
|
||||
// UpdatePullWithResults updates pull's status with the latest project results.
|
||||
// It returns the new PullStatus object.
|
||||
func (b *BoltDB) UpdatePullWithResults(pull models.PullRequest, newResults []models.ProjectResult) (models.PullStatus, error) {
|
||||
func (b *DefaultBoltDB) UpdatePullWithResults(pull models.PullRequest, newResults []models.ProjectResult) (models.PullStatus, error) {
|
||||
key, err := b.pullKey(pull)
|
||||
if err != nil {
|
||||
return models.PullStatus{}, err
|
||||
@@ -281,7 +290,7 @@ func (b *BoltDB) UpdatePullWithResults(pull models.PullRequest, newResults []mod
|
||||
|
||||
// GetPullStatus returns the status for pull.
|
||||
// If there is no status, returns a nil pointer.
|
||||
func (b *BoltDB) GetPullStatus(pull models.PullRequest) (*models.PullStatus, error) {
|
||||
func (b *DefaultBoltDB) GetPullStatus(pull models.PullRequest) (*models.PullStatus, error) {
|
||||
key, err := b.pullKey(pull)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -297,7 +306,7 @@ func (b *BoltDB) GetPullStatus(pull models.PullRequest) (*models.PullStatus, err
|
||||
}
|
||||
|
||||
// DeletePullStatus deletes the status for pull.
|
||||
func (b *BoltDB) DeletePullStatus(pull models.PullRequest) error {
|
||||
func (b *DefaultBoltDB) DeletePullStatus(pull models.PullRequest) error {
|
||||
key, err := b.pullKey(pull)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -311,7 +320,7 @@ func (b *BoltDB) DeletePullStatus(pull models.PullRequest) error {
|
||||
|
||||
// UpdateProjectStatus updates all project statuses under pull that match
|
||||
// workspace and repoRelDir.
|
||||
func (b *BoltDB) UpdateProjectStatus(pull models.PullRequest, workspace string, repoRelDir string, targetStatus models.ProjectPlanStatus) error {
|
||||
func (b *DefaultBoltDB) UpdateProjectStatus(pull models.PullRequest, workspace string, repoRelDir string, targetStatus models.ProjectPlanStatus) error {
|
||||
key, err := b.pullKey(pull)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -344,7 +353,7 @@ func (b *BoltDB) UpdateProjectStatus(pull models.PullRequest, workspace string,
|
||||
return errors.Wrap(err, "DB transaction failed")
|
||||
}
|
||||
|
||||
func (b *BoltDB) pullKey(pull models.PullRequest) ([]byte, error) {
|
||||
func (b *DefaultBoltDB) pullKey(pull models.PullRequest) ([]byte, error) {
|
||||
hostname := pull.BaseRepo.VCSHost.Hostname
|
||||
if strings.Contains(hostname, pullKeySeparator) {
|
||||
return nil, fmt.Errorf("vcs hostname %q contains illegal string %q", hostname, pullKeySeparator)
|
||||
@@ -358,11 +367,11 @@ func (b *BoltDB) pullKey(pull models.PullRequest) ([]byte, error) {
|
||||
nil
|
||||
}
|
||||
|
||||
func (b *BoltDB) lockKey(p models.Project, workspace string) string {
|
||||
func (b *DefaultBoltDB) lockKey(p models.Project, workspace string) string {
|
||||
return fmt.Sprintf("%s/%s/%s", p.RepoFullName, p.Path, workspace)
|
||||
}
|
||||
|
||||
func (b *BoltDB) getPullFromBucket(bucket *bolt.Bucket, key []byte) (*models.PullStatus, error) {
|
||||
func (b *DefaultBoltDB) getPullFromBucket(bucket *bolt.Bucket, key []byte) (*models.PullStatus, error) {
|
||||
serialized := bucket.Get(key)
|
||||
if serialized == nil {
|
||||
return nil, nil
|
||||
@@ -375,7 +384,7 @@ func (b *BoltDB) getPullFromBucket(bucket *bolt.Bucket, key []byte) (*models.Pul
|
||||
return &p, nil
|
||||
}
|
||||
|
||||
func (b *BoltDB) writePullToBucket(bucket *bolt.Bucket, key []byte, pull models.PullStatus) error {
|
||||
func (b *DefaultBoltDB) writePullToBucket(bucket *bolt.Bucket, key []byte, pull models.PullStatus) error {
|
||||
serialized, err := json.Marshal(pull)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "serializing")
|
||||
@@ -383,7 +392,7 @@ func (b *BoltDB) writePullToBucket(bucket *bolt.Bucket, key []byte, pull models.
|
||||
return bucket.Put(key, serialized)
|
||||
}
|
||||
|
||||
func (b *BoltDB) projectResultToProject(p models.ProjectResult) models.ProjectStatus {
|
||||
func (b *DefaultBoltDB) projectResultToProject(p models.ProjectResult) models.ProjectStatus {
|
||||
return models.ProjectStatus{
|
||||
Workspace: p.Workspace,
|
||||
RepoRelDir: p.RepoRelDir,
|
||||
|
||||
@@ -692,7 +692,7 @@ func TestPullStatus_UpdateMerge(t *testing.T) {
|
||||
}
|
||||
|
||||
// newTestDB returns a TestDB using a temporary path.
|
||||
func newTestDB() (*bolt.DB, *db.BoltDB) {
|
||||
func newTestDB() (*bolt.DB, *db.DefaultBoltDB) {
|
||||
// Retrieve a temporary path.
|
||||
f, err := ioutil.TempFile("", "")
|
||||
if err != nil {
|
||||
@@ -718,7 +718,7 @@ func newTestDB() (*bolt.DB, *db.BoltDB) {
|
||||
return boltDB, b
|
||||
}
|
||||
|
||||
func newTestDB2(t *testing.T) (*db.BoltDB, func()) {
|
||||
func newTestDB2(t *testing.T) (*db.DefaultBoltDB, func()) {
|
||||
tmp, cleanup := TempDir(t)
|
||||
boltDB, err := db.New(tmp)
|
||||
Ok(t, err)
|
||||
|
||||
20
server/events/db/mocks/matchers/models_projectplanstatus.go
Normal file
20
server/events/db/mocks/matchers/models_projectplanstatus.go
Normal file
@@ -0,0 +1,20 @@
|
||||
// Code generated by pegomock. DO NOT EDIT.
|
||||
package matchers
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"github.com/petergtz/pegomock"
|
||||
models "github.com/runatlantis/atlantis/server/events/models"
|
||||
)
|
||||
|
||||
func AnyModelsProjectPlanStatus() models.ProjectPlanStatus {
|
||||
pegomock.RegisterMatcher(pegomock.NewAnyMatcher(reflect.TypeOf((*(models.ProjectPlanStatus))(nil)).Elem()))
|
||||
var nullValue models.ProjectPlanStatus
|
||||
return nullValue
|
||||
}
|
||||
|
||||
func EqModelsProjectPlanStatus(value models.ProjectPlanStatus) models.ProjectPlanStatus {
|
||||
pegomock.RegisterMatcher(&pegomock.EqMatcher{Value: value})
|
||||
var nullValue models.ProjectPlanStatus
|
||||
return nullValue
|
||||
}
|
||||
20
server/events/db/mocks/matchers/models_pullrequest.go
Normal file
20
server/events/db/mocks/matchers/models_pullrequest.go
Normal file
@@ -0,0 +1,20 @@
|
||||
// Code generated by pegomock. DO NOT EDIT.
|
||||
package matchers
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"github.com/petergtz/pegomock"
|
||||
models "github.com/runatlantis/atlantis/server/events/models"
|
||||
)
|
||||
|
||||
func AnyModelsPullRequest() models.PullRequest {
|
||||
pegomock.RegisterMatcher(pegomock.NewAnyMatcher(reflect.TypeOf((*(models.PullRequest))(nil)).Elem()))
|
||||
var nullValue models.PullRequest
|
||||
return nullValue
|
||||
}
|
||||
|
||||
func EqModelsPullRequest(value models.PullRequest) models.PullRequest {
|
||||
pegomock.RegisterMatcher(&pegomock.EqMatcher{Value: value})
|
||||
var nullValue models.PullRequest
|
||||
return nullValue
|
||||
}
|
||||
20
server/events/db/mocks/matchers/models_pullstatus.go
Normal file
20
server/events/db/mocks/matchers/models_pullstatus.go
Normal file
@@ -0,0 +1,20 @@
|
||||
// Code generated by pegomock. DO NOT EDIT.
|
||||
package matchers
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"github.com/petergtz/pegomock"
|
||||
models "github.com/runatlantis/atlantis/server/events/models"
|
||||
)
|
||||
|
||||
func AnyModelsPullStatus() models.PullStatus {
|
||||
pegomock.RegisterMatcher(pegomock.NewAnyMatcher(reflect.TypeOf((*(models.PullStatus))(nil)).Elem()))
|
||||
var nullValue models.PullStatus
|
||||
return nullValue
|
||||
}
|
||||
|
||||
func EqModelsPullStatus(value models.PullStatus) models.PullStatus {
|
||||
pegomock.RegisterMatcher(&pegomock.EqMatcher{Value: value})
|
||||
var nullValue models.PullStatus
|
||||
return nullValue
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// Code generated by pegomock. DO NOT EDIT.
|
||||
package matchers
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"github.com/petergtz/pegomock"
|
||||
models "github.com/runatlantis/atlantis/server/events/models"
|
||||
)
|
||||
|
||||
func AnySliceOfModelsProjectResult() []models.ProjectResult {
|
||||
pegomock.RegisterMatcher(pegomock.NewAnyMatcher(reflect.TypeOf((*([]models.ProjectResult))(nil)).Elem()))
|
||||
var nullValue []models.ProjectResult
|
||||
return nullValue
|
||||
}
|
||||
|
||||
func EqSliceOfModelsProjectResult(value []models.ProjectResult) []models.ProjectResult {
|
||||
pegomock.RegisterMatcher(&pegomock.EqMatcher{Value: value})
|
||||
var nullValue []models.ProjectResult
|
||||
return nullValue
|
||||
}
|
||||
209
server/events/db/mocks/mock_boltdb.go
Normal file
209
server/events/db/mocks/mock_boltdb.go
Normal file
@@ -0,0 +1,209 @@
|
||||
// Code generated by pegomock. DO NOT EDIT.
|
||||
// Source: github.com/runatlantis/atlantis/server/events/db (interfaces: BoltDB)
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
pegomock "github.com/petergtz/pegomock"
|
||||
models "github.com/runatlantis/atlantis/server/events/models"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
type MockBoltDB struct {
|
||||
fail func(message string, callerSkip ...int)
|
||||
}
|
||||
|
||||
func NewMockBoltDB(options ...pegomock.Option) *MockBoltDB {
|
||||
mock := &MockBoltDB{}
|
||||
for _, option := range options {
|
||||
option.Apply(mock)
|
||||
}
|
||||
return mock
|
||||
}
|
||||
|
||||
func (mock *MockBoltDB) SetFailHandler(fh pegomock.FailHandler) { mock.fail = fh }
|
||||
func (mock *MockBoltDB) FailHandler() pegomock.FailHandler { return mock.fail }
|
||||
|
||||
func (mock *MockBoltDB) UpdatePullWithResults(pull models.PullRequest, newResults []models.ProjectResult) (models.PullStatus, error) {
|
||||
if mock == nil {
|
||||
panic("mock must not be nil. Use myMock := NewMockBoltDB().")
|
||||
}
|
||||
params := []pegomock.Param{pull, newResults}
|
||||
result := pegomock.GetGenericMockFrom(mock).Invoke("UpdatePullWithResults", params, []reflect.Type{reflect.TypeOf((*models.PullStatus)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()})
|
||||
var ret0 models.PullStatus
|
||||
var ret1 error
|
||||
if len(result) != 0 {
|
||||
if result[0] != nil {
|
||||
ret0 = result[0].(models.PullStatus)
|
||||
}
|
||||
if result[1] != nil {
|
||||
ret1 = result[1].(error)
|
||||
}
|
||||
}
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
func (mock *MockBoltDB) DeletePullStatus(pull models.PullRequest) error {
|
||||
if mock == nil {
|
||||
panic("mock must not be nil. Use myMock := NewMockBoltDB().")
|
||||
}
|
||||
params := []pegomock.Param{pull}
|
||||
result := pegomock.GetGenericMockFrom(mock).Invoke("DeletePullStatus", params, []reflect.Type{reflect.TypeOf((*error)(nil)).Elem()})
|
||||
var ret0 error
|
||||
if len(result) != 0 {
|
||||
if result[0] != nil {
|
||||
ret0 = result[0].(error)
|
||||
}
|
||||
}
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (mock *MockBoltDB) UpdateProjectStatus(pull models.PullRequest, workspace string, repoRelDir string, targetStatus models.ProjectPlanStatus) error {
|
||||
if mock == nil {
|
||||
panic("mock must not be nil. Use myMock := NewMockBoltDB().")
|
||||
}
|
||||
params := []pegomock.Param{pull, workspace, repoRelDir, targetStatus}
|
||||
result := pegomock.GetGenericMockFrom(mock).Invoke("UpdateProjectStatus", params, []reflect.Type{reflect.TypeOf((*error)(nil)).Elem()})
|
||||
var ret0 error
|
||||
if len(result) != 0 {
|
||||
if result[0] != nil {
|
||||
ret0 = result[0].(error)
|
||||
}
|
||||
}
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (mock *MockBoltDB) VerifyWasCalledOnce() *VerifierMockBoltDB {
|
||||
return &VerifierMockBoltDB{
|
||||
mock: mock,
|
||||
invocationCountMatcher: pegomock.Times(1),
|
||||
}
|
||||
}
|
||||
|
||||
func (mock *MockBoltDB) VerifyWasCalled(invocationCountMatcher pegomock.Matcher) *VerifierMockBoltDB {
|
||||
return &VerifierMockBoltDB{
|
||||
mock: mock,
|
||||
invocationCountMatcher: invocationCountMatcher,
|
||||
}
|
||||
}
|
||||
|
||||
func (mock *MockBoltDB) VerifyWasCalledInOrder(invocationCountMatcher pegomock.Matcher, inOrderContext *pegomock.InOrderContext) *VerifierMockBoltDB {
|
||||
return &VerifierMockBoltDB{
|
||||
mock: mock,
|
||||
invocationCountMatcher: invocationCountMatcher,
|
||||
inOrderContext: inOrderContext,
|
||||
}
|
||||
}
|
||||
|
||||
func (mock *MockBoltDB) VerifyWasCalledEventually(invocationCountMatcher pegomock.Matcher, timeout time.Duration) *VerifierMockBoltDB {
|
||||
return &VerifierMockBoltDB{
|
||||
mock: mock,
|
||||
invocationCountMatcher: invocationCountMatcher,
|
||||
timeout: timeout,
|
||||
}
|
||||
}
|
||||
|
||||
type VerifierMockBoltDB struct {
|
||||
mock *MockBoltDB
|
||||
invocationCountMatcher pegomock.Matcher
|
||||
inOrderContext *pegomock.InOrderContext
|
||||
timeout time.Duration
|
||||
}
|
||||
|
||||
func (verifier *VerifierMockBoltDB) UpdatePullWithResults(pull models.PullRequest, newResults []models.ProjectResult) *MockBoltDB_UpdatePullWithResults_OngoingVerification {
|
||||
params := []pegomock.Param{pull, newResults}
|
||||
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "UpdatePullWithResults", params, verifier.timeout)
|
||||
return &MockBoltDB_UpdatePullWithResults_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||
}
|
||||
|
||||
type MockBoltDB_UpdatePullWithResults_OngoingVerification struct {
|
||||
mock *MockBoltDB
|
||||
methodInvocations []pegomock.MethodInvocation
|
||||
}
|
||||
|
||||
func (c *MockBoltDB_UpdatePullWithResults_OngoingVerification) GetCapturedArguments() (models.PullRequest, []models.ProjectResult) {
|
||||
pull, newResults := c.GetAllCapturedArguments()
|
||||
return pull[len(pull)-1], newResults[len(newResults)-1]
|
||||
}
|
||||
|
||||
func (c *MockBoltDB_UpdatePullWithResults_OngoingVerification) GetAllCapturedArguments() (_param0 []models.PullRequest, _param1 [][]models.ProjectResult) {
|
||||
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
|
||||
if len(params) > 0 {
|
||||
_param0 = make([]models.PullRequest, len(c.methodInvocations))
|
||||
for u, param := range params[0] {
|
||||
_param0[u] = param.(models.PullRequest)
|
||||
}
|
||||
_param1 = make([][]models.ProjectResult, len(c.methodInvocations))
|
||||
for u, param := range params[1] {
|
||||
_param1[u] = param.([]models.ProjectResult)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (verifier *VerifierMockBoltDB) DeletePullStatus(pull models.PullRequest) *MockBoltDB_DeletePullStatus_OngoingVerification {
|
||||
params := []pegomock.Param{pull}
|
||||
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "DeletePullStatus", params, verifier.timeout)
|
||||
return &MockBoltDB_DeletePullStatus_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||
}
|
||||
|
||||
type MockBoltDB_DeletePullStatus_OngoingVerification struct {
|
||||
mock *MockBoltDB
|
||||
methodInvocations []pegomock.MethodInvocation
|
||||
}
|
||||
|
||||
func (c *MockBoltDB_DeletePullStatus_OngoingVerification) GetCapturedArguments() models.PullRequest {
|
||||
pull := c.GetAllCapturedArguments()
|
||||
return pull[len(pull)-1]
|
||||
}
|
||||
|
||||
func (c *MockBoltDB_DeletePullStatus_OngoingVerification) GetAllCapturedArguments() (_param0 []models.PullRequest) {
|
||||
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
|
||||
if len(params) > 0 {
|
||||
_param0 = make([]models.PullRequest, len(c.methodInvocations))
|
||||
for u, param := range params[0] {
|
||||
_param0[u] = param.(models.PullRequest)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (verifier *VerifierMockBoltDB) UpdateProjectStatus(pull models.PullRequest, workspace string, repoRelDir string, targetStatus models.ProjectPlanStatus) *MockBoltDB_UpdateProjectStatus_OngoingVerification {
|
||||
params := []pegomock.Param{pull, workspace, repoRelDir, targetStatus}
|
||||
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "UpdateProjectStatus", params, verifier.timeout)
|
||||
return &MockBoltDB_UpdateProjectStatus_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||
}
|
||||
|
||||
type MockBoltDB_UpdateProjectStatus_OngoingVerification struct {
|
||||
mock *MockBoltDB
|
||||
methodInvocations []pegomock.MethodInvocation
|
||||
}
|
||||
|
||||
func (c *MockBoltDB_UpdateProjectStatus_OngoingVerification) GetCapturedArguments() (models.PullRequest, string, string, models.ProjectPlanStatus) {
|
||||
pull, workspace, repoRelDir, targetStatus := c.GetAllCapturedArguments()
|
||||
return pull[len(pull)-1], workspace[len(workspace)-1], repoRelDir[len(repoRelDir)-1], targetStatus[len(targetStatus)-1]
|
||||
}
|
||||
|
||||
func (c *MockBoltDB_UpdateProjectStatus_OngoingVerification) GetAllCapturedArguments() (_param0 []models.PullRequest, _param1 []string, _param2 []string, _param3 []models.ProjectPlanStatus) {
|
||||
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
|
||||
if len(params) > 0 {
|
||||
_param0 = make([]models.PullRequest, len(c.methodInvocations))
|
||||
for u, param := range params[0] {
|
||||
_param0[u] = param.(models.PullRequest)
|
||||
}
|
||||
_param1 = make([]string, len(c.methodInvocations))
|
||||
for u, param := range params[1] {
|
||||
_param1[u] = param.(string)
|
||||
}
|
||||
_param2 = make([]string, len(c.methodInvocations))
|
||||
for u, param := range params[2] {
|
||||
_param2[u] = param.(string)
|
||||
}
|
||||
_param3 = make([]models.ProjectPlanStatus, len(c.methodInvocations))
|
||||
for u, param := range params[3] {
|
||||
_param3[u] = param.(models.ProjectPlanStatus)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -46,7 +46,7 @@ type PullClosedExecutor struct {
|
||||
VCSClient vcs.Client
|
||||
WorkingDir WorkingDir
|
||||
Logger logging.SimpleLogging
|
||||
DB *db.BoltDB
|
||||
DB db.BoltDB
|
||||
}
|
||||
|
||||
type templatedProject struct {
|
||||
|
||||
@@ -25,7 +25,7 @@ type LocksController struct {
|
||||
LockDetailTemplate TemplateWriter
|
||||
WorkingDir events.WorkingDir
|
||||
WorkingDirLocker events.WorkingDirLocker
|
||||
DB *db.BoltDB
|
||||
DB db.BoltDB
|
||||
}
|
||||
|
||||
// GetLock is the GET /locks/{id} route. It renders the lock detail view.
|
||||
|
||||
@@ -15,6 +15,8 @@ import (
|
||||
. "github.com/petergtz/pegomock"
|
||||
"github.com/runatlantis/atlantis/server"
|
||||
"github.com/runatlantis/atlantis/server/events"
|
||||
dbmocks "github.com/runatlantis/atlantis/server/events/db/mocks"
|
||||
|
||||
"github.com/runatlantis/atlantis/server/events/locking/mocks"
|
||||
mocks2 "github.com/runatlantis/atlantis/server/events/mocks"
|
||||
"github.com/runatlantis/atlantis/server/events/models"
|
||||
@@ -192,6 +194,46 @@ func TestDeleteLock_OldFormat(t *testing.T) {
|
||||
cp.VerifyWasCalled(Never()).CreateComment(AnyRepo(), AnyInt(), AnyString())
|
||||
}
|
||||
|
||||
func TestDeleteLock_UpdateProjectStatus(t *testing.T) {
|
||||
t.Log("When deleting a lock, pull status has to be updated to reflect discarded plan")
|
||||
RegisterMockTestingT(t)
|
||||
|
||||
repoName := "owner/repo"
|
||||
projectPath := "path"
|
||||
workspaceName := "workspace"
|
||||
|
||||
cp := vcsmocks.NewMockClient()
|
||||
l := mocks.NewMockLocker()
|
||||
workingDir := mocks2.NewMockWorkingDir()
|
||||
workingDirLocker := events.NewDefaultWorkingDirLocker()
|
||||
pull := models.PullRequest{
|
||||
BaseRepo: models.Repo{FullName: repoName},
|
||||
}
|
||||
When(l.Unlock("id")).ThenReturn(&models.ProjectLock{
|
||||
Pull: pull,
|
||||
Workspace: workspaceName,
|
||||
Project: models.Project{
|
||||
Path: projectPath,
|
||||
RepoFullName: repoName,
|
||||
},
|
||||
}, nil)
|
||||
db := dbmocks.NewMockBoltDB()
|
||||
lc := server.LocksController{
|
||||
Locker: l,
|
||||
Logger: logging.NewNoopLogger(),
|
||||
VCSClient: cp,
|
||||
WorkingDirLocker: workingDirLocker,
|
||||
WorkingDir: workingDir,
|
||||
DB: db,
|
||||
}
|
||||
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
||||
req = mux.SetURLVars(req, map[string]string{"id": "id"})
|
||||
w := httptest.NewRecorder()
|
||||
lc.DeleteLock(w, req)
|
||||
responseContains(t, w, http.StatusOK, "Deleted lock id \"id\"")
|
||||
db.VerifyWasCalledOnce().UpdateProjectStatus(pull, workspaceName, projectPath, models.DiscardedPlanStatus)
|
||||
}
|
||||
|
||||
func TestDeleteLock_CommentFailed(t *testing.T) {
|
||||
t.Log("If the commenting fails we return an error")
|
||||
RegisterMockTestingT(t)
|
||||
|
||||
Reference in New Issue
Block a user