github.com/kubeshop/testkube@v1.17.23/pkg/dbmigrator/dbmigrator_test.go (about) 1 package dbmigrator 2 3 import ( 4 "context" 5 "testing" 6 7 "github.com/golang/mock/gomock" 8 "github.com/pkg/errors" 9 "github.com/spf13/afero" 10 "github.com/stretchr/testify/assert" 11 "go.mongodb.org/mongo-driver/bson" 12 ) 13 14 var ( 15 migration1 = DbMigration{ 16 Name: "migration1", 17 UpScript: []bson.D{{{Key: "A1", Value: "VA1"}}}, 18 DownScript: []bson.D{{{Key: "A2", Value: "VA2"}}}, 19 } 20 migration2 = DbMigration{ 21 Name: "migration2", 22 UpScript: []bson.D{{{Key: "B1", Value: "VB1"}}}, 23 DownScript: []bson.D{{{Key: "B2", Value: "VB2"}}}, 24 } 25 migration2Changed = DbMigration{ 26 Name: "migration2", 27 UpScript: []bson.D{{{Key: "AC1", Value: "VAC1"}}}, 28 DownScript: []bson.D{{{Key: "AC2", Value: "VAC2"}}}, 29 } 30 migration3 = DbMigration{ 31 Name: "migration3", 32 UpScript: []bson.D{{{Key: "C1", Value: "VC1"}}}, 33 DownScript: []bson.D{{{Key: "C2", Value: "VC2"}}}, 34 } 35 ) 36 37 func TestDbMigrator_GetApplied(t *testing.T) { 38 mockCtrl := gomock.NewController(t) 39 db := NewMockDatabase(mockCtrl) 40 migrator := NewDbMigrator(db, []DbMigration{}) 41 ctx := context.Background() 42 expected := []DbMigration{migration1, migration2} 43 44 db.EXPECT().GetAppliedMigrations(ctx).Return(expected, nil) 45 46 result, err := migrator.GetApplied(ctx) 47 48 assert.Equal(t, result, expected) 49 assert.NoError(t, err) 50 } 51 52 func TestDbMigrator_Plan_Empty(t *testing.T) { 53 mockCtrl := gomock.NewController(t) 54 db := NewMockDatabase(mockCtrl) 55 migrator := NewDbMigrator(db, []DbMigration{}) 56 ctx := context.Background() 57 58 db.EXPECT().GetAppliedMigrations(ctx).Return([]DbMigration{}, nil) 59 60 result, err := migrator.Plan(ctx) 61 62 assert.Equal(t, DbPlan{Ups: nil, Downs: nil, Total: 0}, result) 63 assert.NoError(t, err) 64 } 65 66 func TestDbMigrator_Plan_Same(t *testing.T) { 67 mockCtrl := gomock.NewController(t) 68 db := NewMockDatabase(mockCtrl) 69 migrator := NewDbMigrator(db, []DbMigration{migration1}) 70 ctx := context.Background() 71 72 db.EXPECT().GetAppliedMigrations(ctx).Return([]DbMigration{migration1}, nil) 73 74 result, err := migrator.Plan(ctx) 75 76 assert.Equal(t, DbPlan{Ups: nil, Downs: nil, Total: 0}, result) 77 assert.NoError(t, err) 78 } 79 80 func TestDbMigrator_Plan_New(t *testing.T) { 81 mockCtrl := gomock.NewController(t) 82 db := NewMockDatabase(mockCtrl) 83 migrator := NewDbMigrator(db, []DbMigration{migration1, migration2}) 84 ctx := context.Background() 85 86 db.EXPECT().GetAppliedMigrations(ctx).Return([]DbMigration{migration1}, nil) 87 88 result, err := migrator.Plan(ctx) 89 90 assert.Equal(t, DbPlan{Ups: []DbMigration{migration2}, Downs: nil, Total: 1}, result) 91 assert.NoError(t, err) 92 } 93 94 func TestDbMigrator_Plan_Deleted(t *testing.T) { 95 mockCtrl := gomock.NewController(t) 96 db := NewMockDatabase(mockCtrl) 97 migrator := NewDbMigrator(db, []DbMigration{migration1}) 98 ctx := context.Background() 99 100 db.EXPECT().GetAppliedMigrations(ctx).Return([]DbMigration{migration1, migration2}, nil) 101 102 result, err := migrator.Plan(ctx) 103 104 assert.Equal(t, DbPlan{Ups: nil, Downs: []DbMigration{migration2}, Total: 1}, result) 105 assert.NoError(t, err) 106 } 107 108 func TestDbMigrator_Plan_Updated(t *testing.T) { 109 mockCtrl := gomock.NewController(t) 110 db := NewMockDatabase(mockCtrl) 111 migrator := NewDbMigrator(db, []DbMigration{migration1, migration2Changed, migration3}) 112 ctx := context.Background() 113 114 db.EXPECT().GetAppliedMigrations(ctx).Return([]DbMigration{migration1, migration2, migration3}, nil) 115 116 result, err := migrator.Plan(ctx) 117 118 assert.Equal(t, DbPlan{Ups: []DbMigration{migration2Changed, migration3}, Downs: []DbMigration{migration3, migration2}, Total: 4}, result) 119 assert.NoError(t, err) 120 } 121 122 func TestDbMigrator_Apply_Empty(t *testing.T) { 123 mockCtrl := gomock.NewController(t) 124 db := NewMockDatabase(mockCtrl) 125 migrator := NewDbMigrator(db, []DbMigration{}) 126 ctx := context.Background() 127 128 db.EXPECT().GetAppliedMigrations(ctx).Return([]DbMigration{}, nil) 129 130 err := migrator.Apply(ctx) 131 132 assert.NoError(t, err) 133 } 134 135 func TestDbMigrator_Apply_Same(t *testing.T) { 136 mockCtrl := gomock.NewController(t) 137 db := NewMockDatabase(mockCtrl) 138 migrator := NewDbMigrator(db, []DbMigration{migration1}) 139 ctx := context.Background() 140 141 db.EXPECT().GetAppliedMigrations(ctx).Return([]DbMigration{migration1}, nil) 142 143 err := migrator.Apply(ctx) 144 145 assert.NoError(t, err) 146 } 147 148 func TestDbMigrator_Apply_New(t *testing.T) { 149 mockCtrl := gomock.NewController(t) 150 db := NewMockDatabase(mockCtrl) 151 migrator := NewDbMigrator(db, []DbMigration{migration1, migration2}) 152 ctx := context.Background() 153 154 db.EXPECT().GetAppliedMigrations(ctx).Return([]DbMigration{migration1}, nil) 155 db.EXPECT().RunCommands(ctx, migration2.UpScript).Return(nil) 156 db.EXPECT().InsertMigrationState(ctx, &migration2).Return(nil) 157 158 err := migrator.Apply(ctx) 159 160 assert.NoError(t, err) 161 } 162 163 func TestDbMigrator_Apply_Deleted(t *testing.T) { 164 mockCtrl := gomock.NewController(t) 165 db := NewMockDatabase(mockCtrl) 166 migrator := NewDbMigrator(db, []DbMigration{migration1}) 167 ctx := context.Background() 168 169 db.EXPECT().GetAppliedMigrations(ctx).Return([]DbMigration{migration1, migration2}, nil) 170 db.EXPECT().RunCommands(ctx, migration2.DownScript).Return(nil) 171 db.EXPECT().DeleteMigrationState(ctx, &migration2).Return(nil) 172 173 err := migrator.Apply(ctx) 174 175 assert.NoError(t, err) 176 } 177 178 func TestDbMigrator_Apply_Updated(t *testing.T) { 179 mockCtrl := gomock.NewController(t) 180 db := NewMockDatabase(mockCtrl) 181 migrator := NewDbMigrator(db, []DbMigration{migration1, migration2Changed, migration3}) 182 ctx := context.Background() 183 184 gomock.InOrder( 185 db.EXPECT().GetAppliedMigrations(ctx).Return([]DbMigration{migration1, migration2, migration3}, nil), 186 db.EXPECT().RunCommands(ctx, migration3.DownScript).Return(nil), 187 db.EXPECT().DeleteMigrationState(ctx, &migration3).Return(nil), 188 db.EXPECT().RunCommands(ctx, migration2.DownScript).Return(nil), 189 db.EXPECT().DeleteMigrationState(ctx, &migration2).Return(nil), 190 db.EXPECT().RunCommands(ctx, migration2Changed.UpScript).Return(nil), 191 db.EXPECT().InsertMigrationState(ctx, &migration2Changed).Return(nil), 192 db.EXPECT().RunCommands(ctx, migration3.UpScript).Return(nil), 193 db.EXPECT().InsertMigrationState(ctx, &migration3).Return(nil), 194 ) 195 196 err := migrator.Apply(ctx) 197 198 assert.NoError(t, err) 199 } 200 201 func TestDbMigrator_Apply_Downgrade_On_Apply_Error(t *testing.T) { 202 mockCtrl := gomock.NewController(t) 203 db := NewMockDatabase(mockCtrl) 204 migrator := NewDbMigrator(db, []DbMigration{migration1, migration2}) 205 ctx := context.Background() 206 207 gomock.InOrder( 208 db.EXPECT().GetAppliedMigrations(ctx).Return([]DbMigration{migration1}, nil), 209 db.EXPECT().RunCommands(ctx, migration2.UpScript).Return(errors.New("test-failed")), 210 db.EXPECT().RunCommands(ctx, migration2.DownScript).Return(nil), 211 db.EXPECT().DeleteMigrationState(ctx, &migration2).Return(nil), 212 ) 213 214 err := migrator.Apply(ctx) 215 216 assert.Error(t, err, "test-failed") 217 } 218 219 func TestGetDbMigrationsFromFs_Empty(t *testing.T) { 220 fsys := &afero.IOFS{Fs: afero.NewMemMapFs()} 221 migrations, err := GetDbMigrationsFromFs(fsys) 222 assert.Equal(t, []DbMigration(nil), migrations) 223 assert.NoError(t, err) 224 } 225 226 func TestGetDbMigrationsFromFs_Files(t *testing.T) { 227 fsys := &afero.IOFS{Fs: afero.NewMemMapFs()} 228 _ = afero.WriteFile(fsys.Fs, "02_file.up.json", []byte(`[{"a": "2"}]`), 0644) 229 _ = afero.WriteFile(fsys.Fs, "01_file.up.json", []byte(`[{"a": "1"}]`), 0644) 230 _ = afero.WriteFile(fsys.Fs, "02_file.down.json", []byte(`[{"b": "2"}]`), 0644) 231 _ = afero.WriteFile(fsys.Fs, "no_suffix.json", []byte(`[{"b": "2"}]`), 0644) 232 _ = afero.WriteFile(fsys.Fs, "different_ext.up.js", []byte(`[{"b": "2"}]`), 0644) 233 migrations, err := GetDbMigrationsFromFs(fsys) 234 assert.Equal(t, []DbMigration{ 235 {Name: "01_file", UpScript: []bson.D{{{Key: "a", Value: "1"}}}, DownScript: []bson.D{}}, 236 {Name: "02_file", UpScript: []bson.D{{{Key: "a", Value: "2"}}}, DownScript: []bson.D{{{Key: "b", Value: "2"}}}}, 237 }, migrations) 238 assert.NoError(t, err) 239 }