From a66845bf593b4664f9a228ed80dd7e0108544684 Mon Sep 17 00:00:00 2001 From: Jim Date: Tue, 9 Jun 2020 21:22:15 -0400 Subject: [PATCH] refactor delete test to be table driven. (#102) --- internal/db/read_writer.go | 4 +- internal/db/read_writer_test.go | 334 +++++++++++++++----------------- 2 files changed, 159 insertions(+), 179 deletions(-) diff --git a/internal/db/read_writer.go b/internal/db/read_writer.go index c5bd7df04a..13e8067c30 100644 --- a/internal/db/read_writer.go +++ b/internal/db/read_writer.go @@ -342,10 +342,10 @@ func (rw *Db) Delete(ctx context.Context, i interface{}, opt ...Option) (int, er func validateOplogArgs(i interface{}, opts Options) (oplog.ReplayableMessage, error) { oplogArgs := opts.oplogOpts if oplogArgs.wrapper == nil { - return nil, errors.New("error no wrapper WithOplog") + return nil, fmt.Errorf("error no wrapper WithOplog: %w", ErrNilParameter) } if len(oplogArgs.metadata) == 0 { - return nil, errors.New("error no metadata for WithOplog") + return nil, fmt.Errorf("error no metadata for WithOplog: %w", ErrInvalidParameter) } replayable, ok := i.(oplog.ReplayableMessage) if !ok { diff --git a/internal/db/read_writer_test.go b/internal/db/read_writer_test.go index a3fa37cbc7..007d6685a6 100644 --- a/internal/db/read_writer_test.go +++ b/internal/db/read_writer_test.go @@ -11,6 +11,7 @@ import ( "github.com/golang/protobuf/ptypes" "github.com/hashicorp/go-hclog" + wrapping "github.com/hashicorp/go-kms-wrapping" "github.com/hashicorp/go-uuid" "github.com/hashicorp/vault/sdk/helper/base62" "github.com/hashicorp/watchtower/internal/db/db_test" @@ -18,6 +19,7 @@ import ( "github.com/hashicorp/watchtower/internal/oplog" "github.com/jinzhu/gorm" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestDb_Update(t *testing.T) { @@ -321,7 +323,7 @@ func TestDb_Update(t *testing.T) { ) assert.Error(err) assert.Equal(0, rowsUpdated) - assert.Equal("update: oplog validation failed error no wrapper WithOplog", err.Error()) + assert.Equal("update: oplog validation failed error no wrapper WithOplog: nil parameter", err.Error()) }) t.Run("no-metadata-WithOplog", func(t *testing.T) { w := Db{underlying: db} @@ -337,7 +339,7 @@ func TestDb_Update(t *testing.T) { ) assert.Error(err) assert.Equal(0, rowsUpdated) - assert.Equal("update: oplog validation failed error no metadata for WithOplog", err.Error()) + assert.Equal("update: oplog validation failed error no metadata for WithOplog: invalid parameter", err.Error()) }) } @@ -461,7 +463,7 @@ func TestDb_Create(t *testing.T) { ), ) assert.Error(err) - assert.Equal("create: oplog validation failed error no wrapper WithOplog", err.Error()) + assert.Equal("create: oplog validation failed error no wrapper WithOplog: nil parameter", err.Error()) }) t.Run("no-metadata-WithOplog", func(t *testing.T) { w := Db{underlying: db} @@ -479,7 +481,7 @@ func TestDb_Create(t *testing.T) { ), ) assert.Error(err) - assert.Equal("create: oplog validation failed error no metadata for WithOplog", err.Error()) + assert.Equal("create: oplog validation failed error no metadata for WithOplog: invalid parameter", err.Error()) }) t.Run("nil-tx", func(t *testing.T) { w := Db{underlying: nil} @@ -931,188 +933,166 @@ func TestDb_DoTx(t *testing.T) { } func TestDb_Delete(t *testing.T) { - // intentionally not run with t.Parallel so we don't need to use DoTx for the Create tests cleanup, db, _ := TestSetup(t, "postgres") defer func() { if err := cleanup(); err != nil { t.Error(err) } }() - assert := assert.New(t) - defer db.Close() - t.Run("simple", func(t *testing.T) { - w := Db{underlying: db} - id, err := uuid.GenerateUUID() - assert.NoError(err) - user, err := db_test.NewTestUser() - assert.NoError(err) - user.Name = "foo-" + id - err = w.Create(context.Background(), user) - assert.NoError(err) - assert.NotEmpty(user.Id) - assert.NotNil(user.GetCreateTime()) - assert.NotNil(user.GetUpdateTime()) - - foundUser, err := db_test.NewTestUser() - assert.NoError(err) - foundUser.PublicId = user.PublicId - err = w.LookupByPublicId(context.Background(), foundUser) - assert.NoError(err) - assert.Equal(foundUser.Id, user.Id) - - rowsDeleted, err := w.Delete(context.Background(), user) - assert.NoError(err) - assert.Equal(1, rowsDeleted) - - err = w.LookupByPublicId(context.Background(), foundUser) - assert.Error(err) - assert.Equal(ErrRecordNotFound, err) - }) - t.Run("valid-WithOplog", func(t *testing.T) { - w := Db{underlying: db} - id, err := uuid.GenerateUUID() - assert.NoError(err) - user, err := db_test.NewTestUser() - assert.NoError(err) - user.Name = "foo-" + id - err = w.Create( - context.Background(), - user, - WithOplog( - TestWrapper(t), - oplog.Metadata{ - "key-only": nil, - "deployment": []string{"amex"}, - "project": []string{"central-info-systems", "local-info-systems"}, - }, - ), - ) - assert.NoError(err) - assert.NotEmpty(user.Id) - - foundUser, err := db_test.NewTestUser() - assert.NoError(err) - foundUser.PublicId = user.PublicId - err = w.LookupByPublicId(context.Background(), foundUser) - assert.NoError(err) - assert.Equal(foundUser.Id, user.Id) - - rowsDeleted, err := w.Delete( - context.Background(), - user, - WithOplog( - TestWrapper(t), - oplog.Metadata{ - "key-only": nil, - "deployment": []string{"amex"}, - "project": []string{"central-info-systems", "local-info-systems"}, - }, - ), - ) - assert.NoError(err) - assert.Equal(1, rowsDeleted) - - err = w.LookupByPublicId(context.Background(), foundUser) - assert.Error(err) - assert.Equal(ErrRecordNotFound, err) - }) - t.Run("no-wrapper-WithOplog", func(t *testing.T) { - w := Db{underlying: db} - id, err := uuid.GenerateUUID() - assert.NoError(err) - user, err := db_test.NewTestUser() - assert.NoError(err) - user.Name = "foo-" + id - err = w.Create( - context.Background(), - user, - WithOplog( - TestWrapper(t), - oplog.Metadata{ - "key-only": nil, - "deployment": []string{"amex"}, - "project": []string{"central-info-systems", "local-info-systems"}, - }, - ), - ) - assert.NoError(err) - assert.NotEmpty(user.Id) - - foundUser, err := db_test.NewTestUser() - assert.NoError(err) - foundUser.PublicId = user.PublicId - err = w.LookupByPublicId(context.Background(), foundUser) - assert.NoError(err) - assert.Equal(foundUser.Id, user.Id) + defer func() { + if err := db.Close(); err != nil { + t.Error(err) + } + }() + newUser := func() *db_test.TestUser { + w := &Db{ + underlying: db, + } + u, err := db_test.NewTestUser() + assert.NoError(t, err) + err = w.Create(context.Background(), u) + assert.NoError(t, err) + return u + } + notFoundUser := func() *db_test.TestUser { + u, err := db_test.NewTestUser() + assert.NoError(t, err) + u.Id = 1111111 + return u + } - rowsDeleted, err := w.Delete( - context.Background(), - user, - WithOplog( - nil, - oplog.Metadata{ - "key-only": nil, - "deployment": []string{"amex"}, - "project": []string{"central-info-systems", "local-info-systems"}, - }, - ), - ) - assert.Error(err) - assert.Equal(0, rowsDeleted) - assert.Equal("delete: oplog validation failed error no wrapper WithOplog", err.Error()) - }) - t.Run("no-metadata-WithOplog", func(t *testing.T) { - w := Db{underlying: db} - id, err := uuid.GenerateUUID() - assert.NoError(err) - user, err := db_test.NewTestUser() - assert.NoError(err) - user.Name = "foo-" + id - err = w.Create( - context.Background(), - user, - WithOplog( - TestWrapper(t), - oplog.Metadata{ - "key-only": nil, - "deployment": []string{"amex"}, - "project": []string{"central-info-systems", "local-info-systems"}, - }, - ), - ) - assert.NoError(err) - assert.NotEmpty(user.Id) + newMetadata := func(publicId string) oplog.Metadata { + return oplog.Metadata{ + "op-type": []string{oplog.OpType_OP_TYPE_DELETE.String()}, + "resource-public-id": []string{publicId}, + } + } + type args struct { + i *db_test.TestUser + opt []Option + metadata func(publicId string) oplog.Metadata + } + tests := []struct { + name string + underlying *gorm.DB + wrapper wrapping.Wrapper + args args + want int + wantOplog bool + wantErr bool + wantErrIs error + }{ + { + name: "simple-no-oplog", + underlying: db, + wrapper: TestWrapper(t), + args: args{ + i: newUser(), + }, + want: 1, + wantErr: false, + }, + { + name: "valid-with-oplog", + underlying: db, + wrapper: TestWrapper(t), + args: args{ + i: newUser(), + metadata: newMetadata, + }, + wantOplog: true, + want: 1, + wantErr: false, + }, + { + name: "nil-wrapper", + underlying: db, + wrapper: nil, + args: args{ + i: newUser(), + metadata: newMetadata, + }, + wantOplog: true, + want: 0, + wantErr: true, + wantErrIs: ErrNilParameter, + }, + { + name: "nil-metadata", + underlying: db, + wrapper: nil, + args: args{ + i: newUser(), + metadata: func(string) oplog.Metadata { return nil }, + }, + wantOplog: true, + want: 0, + wantErr: true, + wantErrIs: ErrNilParameter, + }, + { + name: "nil-underlying", + underlying: nil, + wrapper: TestWrapper(t), + args: args{ + i: newUser(), + }, + want: 0, + wantErr: true, + wantErrIs: ErrNilParameter, + }, + { + name: "not-found", + underlying: db, + wrapper: TestWrapper(t), + args: args{ + i: notFoundUser(), + }, + want: 0, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + require := require.New(t) + assert := assert.New(t) + rw := &Db{ + underlying: tt.underlying, + } + if tt.wantOplog { + metadata := tt.args.metadata(tt.args.i.PublicId) + opLog := WithOplog(tt.wrapper, metadata) + tt.args.opt = append(tt.args.opt, opLog) + } + got, err := rw.Delete(context.Background(), tt.args.i, tt.args.opt...) + assert.Equal(tt.want, got) + if tt.wantErr { + require.Error(err) + if tt.wantErrIs != nil { + assert.Truef(errors.Is(err, tt.wantErrIs), "received unexpected error: %v", err) + } + err := TestVerifyOplog(t, rw, tt.args.i.GetPublicId(), WithOperation(oplog.OpType_OP_TYPE_DELETE), WithCreateNotBefore(5*time.Second)) + assert.Error(err) + return + } + require.NoError(err) + assert.Equal(tt.want, got) - foundUser, err := db_test.NewTestUser() - assert.NoError(err) - foundUser.PublicId = user.PublicId - err = w.LookupByPublicId(context.Background(), foundUser) - assert.NoError(err) - assert.Equal(foundUser.Id, user.Id) + foundUser := tt.args.i.Clone() + foundUser.PublicId = tt.args.i.PublicId + err = rw.LookupByPublicId(context.Background(), foundUser) + assert.Error(err) + assert.Equal(ErrRecordNotFound, err) - rowsDeleted, err := w.Delete( - context.Background(), - user, - WithOplog( - TestWrapper(t), - nil, - ), - ) - assert.Error(err) - assert.Equal(0, rowsDeleted) - assert.Equal("delete: oplog validation failed error no metadata for WithOplog", err.Error()) - }) - t.Run("nil-tx", func(t *testing.T) { - w := Db{underlying: nil} - id, err := uuid.GenerateUUID() - assert.NoError(err) - user, err := db_test.NewTestUser() - assert.NoError(err) - user.Name = "foo-" + id - err = w.Create(context.Background(), user) - assert.Error(err) - assert.Equal("create: missing underlying db nil parameter", err.Error()) - }) + err = TestVerifyOplog(t, rw, tt.args.i.GetPublicId(), WithOperation(oplog.OpType_OP_TYPE_DELETE), WithCreateNotBefore(5*time.Second)) + switch { + case tt.wantOplog: + assert.NoError(err) + default: + assert.Error(err) + } + }) + } } func TestDb_ScanRows(t *testing.T) {