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  }