package oplog import ( "testing" "github.com/hashicorp/boundary/internal/oplog/oplog_test" dbassert "github.com/hashicorp/dbassert/gorm" "github.com/jinzhu/gorm" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) // Test_GormWriterCreate provides unit tests for GormWriter Create func Test_GormWriterCreate(t *testing.T) { cleanup, db := setup(t) defer testCleanup(t, cleanup, db) t.Run("valid", func(t *testing.T) { assert, require := assert.New(t), require.New(t) tx := db.Begin() defer tx.Rollback() w := GormWriter{tx} user := oplog_test.TestUser{ Name: "foo-" + testId(t), } require.NoError(w.Create(&user)) foundUser := testFindUser(t, tx, user.Id) assert.Equal(user.Name, foundUser.Name) }) t.Run("nil tx", func(t *testing.T) { assert, require := assert.New(t), require.New(t) w := GormWriter{nil} err := w.Create(&oplog_test.TestUser{}) require.Error(err) assert.Equal(err.Error(), "create Tx is nil") }) t.Run("nil model", func(t *testing.T) { assert, require := assert.New(t), require.New(t) tx := db.Begin() defer tx.Rollback() w := GormWriter{tx} err := w.Create(nil) require.Error(err) assert.Equal(err.Error(), "create interface is nil") }) } // Test_GormWriterDelete provides unit tests for GormWriter Delete func Test_GormWriterDelete(t *testing.T) { cleanup, db := setup(t) defer testCleanup(t, cleanup, db) t.Run("valid", func(t *testing.T) { assert, require := assert.New(t), require.New(t) tx := db.Begin() defer tx.Rollback() w := GormWriter{tx} id := testId(t) user := testUser(t, db, "foo-"+id, "", "") foundUser := testFindUser(t, db, user.Id) require.NoError(w.Delete(&user)) err := tx.Where("id = ?", user.Id).First(&foundUser).Error require.Error(err) assert.Equal(err, gorm.ErrRecordNotFound) }) t.Run("nil tx", func(t *testing.T) { assert, require := assert.New(t), require.New(t) w := GormWriter{nil} err := w.Delete(&oplog_test.TestUser{}) require.Error(err) assert.Equal(err.Error(), "delete Tx is nil") }) t.Run("nil model", func(t *testing.T) { assert, require := assert.New(t), require.New(t) tx := db.Begin() defer tx.Rollback() w := GormWriter{tx} err := w.Delete(nil) require.Error(err) assert.Equal(err.Error(), "delete interface is nil") }) } // Test_GormWriterHasTable provides unit tests for GormWriter HasTable func Test_GormWriterHasTable(t *testing.T) { cleanup, db := setup(t) defer testCleanup(t, cleanup, db) w := GormWriter{Tx: db} t.Run("success", func(t *testing.T) { assert := require.New(t) ok := w.hasTable("oplog_test_user") assert.Equal(ok, true) }) t.Run("no table", func(t *testing.T) { assert := assert.New(t) badTableName := testId(t) ok := w.hasTable(badTableName) assert.Equal(ok, false) }) t.Run("blank table name", func(t *testing.T) { assert := assert.New(t) ok := w.hasTable("") assert.Equal(ok, false) }) } // Test_GormWriterCreateTable provides unit tests for GormWriter CreateTable func Test_GormWriterCreateTable(t *testing.T) { cleanup, db := setup(t) defer testCleanup(t, cleanup, db) t.Run("success", func(t *testing.T) { assert := assert.New(t) w := GormWriter{Tx: db} suffix := testId(t) u := &oplog_test.TestUser{} newTableName := u.TableName() + "_" + suffix defer func() { assert.NoError(w.dropTableIfExists(newTableName)) }() err := w.createTableLike(u.TableName(), newTableName) assert.NoError(err) }) t.Run("call twice", func(t *testing.T) { assert, require := assert.New(t), require.New(t) w := GormWriter{Tx: db} suffix := testId(t) u := &oplog_test.TestUser{} newTableName := u.TableName() + "_" + suffix defer func() { assert.NoError(w.dropTableIfExists(newTableName)) }() err := w.createTableLike(u.TableName(), newTableName) require.NoError(err) // should be an error to create the same table twice err = w.createTableLike(u.TableName(), newTableName) require.Error(err) assert.Error(err, err.Error(), nil) }) t.Run("empty existing", func(t *testing.T) { assert, require := assert.New(t), require.New(t) w := GormWriter{Tx: db} suffix := testId(t) u := &oplog_test.TestUser{} newTableName := u.TableName() + "_" + suffix defer func() { assert.NoError(w.dropTableIfExists(newTableName)) }() err := w.createTableLike("", newTableName) require.Error(err) assert.Error(err, err.Error(), nil) assert.Equal(err.Error(), "error existingTableName is empty string") }) t.Run("blank name", func(t *testing.T) { assert, require := assert.New(t), require.New(t) w := GormWriter{Tx: db} u := &oplog_test.TestUser{} err := w.createTableLike(u.TableName(), "") require.Error(err) assert.Error(err, err.Error(), nil) assert.Equal(err.Error(), "error newTableName is empty string") }) } // Test_GormWriterDropTableIfExists provides unit tests for GormWriter DropTableIfExists func Test_GormWriterDropTableIfExists(t *testing.T) { cleanup, db := setup(t) defer testCleanup(t, cleanup, db) t.Run("success", func(t *testing.T) { assert := assert.New(t) w := GormWriter{Tx: db} suffix := testId(t) u := &oplog_test.TestUser{} newTableName := u.TableName() + "_" + suffix assert.NoError(w.createTableLike(u.TableName(), newTableName)) defer func() { assert.NoError(w.dropTableIfExists(newTableName)) }() }) t.Run("success with blank", func(t *testing.T) { assert, require := assert.New(t), require.New(t) w := GormWriter{Tx: db} err := w.dropTableIfExists("") require.Error(err) assert.Equal(err.Error(), "cannot drop table whose name is an empty string") }) } func TestGormWriter_Update(t *testing.T) { cleanup, db := setup(t) defer testCleanup(t, cleanup, db) id := testId(t) type fields struct { Tx *gorm.DB } type args struct { user *oplog_test.TestUser fieldMaskPaths []string setToNullPaths []string } tests := []struct { name string Tx *gorm.DB args args wantUser *oplog_test.TestUser wantErr bool }{ { name: "valid-fieldmask", Tx: db, args: args{ user: &oplog_test.TestUser{ Name: "valid-fieldmask", }, fieldMaskPaths: []string{"name"}, }, wantUser: &oplog_test.TestUser{ Name: "valid-fieldmask", Email: id, PhoneNumber: id, }, wantErr: false, }, { name: "valid-setToNull", Tx: db, args: args{ user: &oplog_test.TestUser{ Name: "valid-setToNull", }, fieldMaskPaths: nil, setToNullPaths: []string{"name"}, }, wantUser: &oplog_test.TestUser{ Name: "", Email: id, PhoneNumber: id, }, wantErr: false, }, { name: "valid-setToNull-and-fieldMask", Tx: db, args: args{ user: &oplog_test.TestUser{ Email: "valid-setToNull-and-fieldMask", }, fieldMaskPaths: []string{"email"}, setToNullPaths: []string{"name"}, }, wantUser: &oplog_test.TestUser{ Name: "", Email: "valid-setToNull-and-fieldMask", PhoneNumber: id, }, wantErr: false, }, { name: "no-field-mask", Tx: db, args: args{ user: &oplog_test.TestUser{ Name: "no-field-mask", }, fieldMaskPaths: []string{""}, }, wantErr: true, }, { name: "nil-field-mask", Tx: db, args: args{ user: &oplog_test.TestUser{ Name: "nil-field-mask", }, fieldMaskPaths: nil, }, wantErr: true, }, { name: "nil-tx", Tx: nil, args: args{ user: &oplog_test.TestUser{ Name: "nil-txt", }, fieldMaskPaths: []string{"name"}, }, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require, dbassert := assert.New(t), require.New(t), dbassert.New(t, db.DB(), "postgres") w := &GormWriter{ Tx: tt.Tx, } u := testUser(t, db, id, id, id) // intentionally, not relying on tt.Tx u.Name = tt.args.user.Name u.Email = tt.args.user.Email u.PhoneNumber = tt.args.user.PhoneNumber err := w.Update(tt.args.user, tt.args.fieldMaskPaths, tt.args.setToNullPaths) if tt.wantErr { require.Error(err) return } require.NoError(err) var foundUser oplog_test.TestUser err = db.Where("id = ?", u.Id).First(&foundUser).Error require.NoError(err) tt.wantUser.Id = u.Id assert.Equal(tt.wantUser, &foundUser) for _, f := range tt.args.setToNullPaths { dbassert.IsNull(u, f) } }) } t.Run("nil model", func(t *testing.T) { assert := assert.New(t) w := GormWriter{db} err := w.Create(nil) assert.Error(err) }) }