From 42f074062b513e370e471d5506cc724cfc98d111 Mon Sep 17 00:00:00 2001 From: Harald Nordgren Date: Sun, 5 Aug 2018 17:07:14 +0200 Subject: [PATCH] Update tests for 'Migrate', 'Steps' and 'UpAndDown' to assert exact migration sequence --- migrate_test.go | 573 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 518 insertions(+), 55 deletions(-) diff --git a/migrate_test.go b/migrate_test.go index 94d399265..efc988a0f 100644 --- a/migrate_test.go +++ b/migrate_test.go @@ -21,14 +21,14 @@ var sourceStubMigrations *source.Migrations func init() { sourceStubMigrations = source.NewMigrations() - sourceStubMigrations.Append(&source.Migration{Version: 1, Direction: source.Up}) - sourceStubMigrations.Append(&source.Migration{Version: 1, Direction: source.Down}) - sourceStubMigrations.Append(&source.Migration{Version: 3, Direction: source.Up}) - sourceStubMigrations.Append(&source.Migration{Version: 4, Direction: source.Up}) - sourceStubMigrations.Append(&source.Migration{Version: 4, Direction: source.Down}) - sourceStubMigrations.Append(&source.Migration{Version: 5, Direction: source.Down}) - sourceStubMigrations.Append(&source.Migration{Version: 7, Direction: source.Up}) - sourceStubMigrations.Append(&source.Migration{Version: 7, Direction: source.Down}) + sourceStubMigrations.Append(&source.Migration{Version: 1, Direction: source.Up, Identifier: "CREATE 1"}) + sourceStubMigrations.Append(&source.Migration{Version: 1, Direction: source.Down, Identifier: "DROP 1"}) + sourceStubMigrations.Append(&source.Migration{Version: 3, Direction: source.Up, Identifier: "CREATE 3"}) + sourceStubMigrations.Append(&source.Migration{Version: 4, Direction: source.Up, Identifier: "CREATE 4"}) + sourceStubMigrations.Append(&source.Migration{Version: 4, Direction: source.Down, Identifier: "DROP 4"}) + sourceStubMigrations.Append(&source.Migration{Version: 5, Direction: source.Down, Identifier: "DROP 5"}) + sourceStubMigrations.Append(&source.Migration{Version: 7, Direction: source.Up, Identifier: "CREATE 7"}) + sourceStubMigrations.Append(&source.Migration{Version: 7, Direction: source.Down, Identifier: "DROP 7"}) } type DummyInstance struct{ Name string } @@ -224,7 +224,6 @@ func TestMigrate(t *testing.T) { m, _ := New("stub://", "stub://") m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations dbDrv := m.databaseDrv.(*dStub.Stub) - seq := newMigSeq() tt := []struct { version uint @@ -233,33 +232,226 @@ func TestMigrate(t *testing.T) { expectSeq migrationSequence }{ // migrate all the way Up in single steps - {version: 0, expectErr: os.ErrNotExist}, - {version: 1, expectErr: nil, expectVersion: 1, expectSeq: seq.add(M(1))}, - {version: 2, expectErr: os.ErrNotExist}, - {version: 3, expectErr: nil, expectVersion: 3, expectSeq: seq.add(M(3))}, - {version: 4, expectErr: nil, expectVersion: 4, expectSeq: seq.add(M(4))}, - {version: 5, expectErr: nil, expectVersion: 5, expectSeq: seq.add()}, // 5 has no up migration - {version: 6, expectErr: os.ErrNotExist}, - {version: 7, expectErr: nil, expectVersion: 7, expectSeq: seq.add(M(7))}, - {version: 8, expectErr: os.ErrNotExist}, + { + version: 0, + expectErr: os.ErrNotExist, + }, + { + version: 1, + expectVersion: 1, + expectSeq: migrationSequence{ + mr("CREATE 1"), + }, + }, + { + version: 2, + expectErr: os.ErrNotExist, + expectSeq: migrationSequence{ + mr("CREATE 1"), + }, + }, + { + version: 3, + expectVersion: 3, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + }, + }, + { + version: 4, + expectVersion: 4, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + }, + }, + { + version: 5, + expectVersion: 5, + expectSeq: migrationSequence{ // 5 has no up migration + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + }, + }, + { + version: 6, + expectErr: os.ErrNotExist, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + }, + }, + { + version: 7, + expectVersion: 7, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + }, + }, + { + version: 8, + expectErr: os.ErrNotExist, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + }, + }, // migrate all the way Down in single steps - {version: 6, expectErr: os.ErrNotExist}, - {version: 5, expectErr: nil, expectVersion: 5, expectSeq: seq.add(M(7, 5))}, - {version: 4, expectErr: nil, expectVersion: 4, expectSeq: seq.add(M(5, 4))}, - {version: 3, expectErr: nil, expectVersion: 3, expectSeq: seq.add(M(4, 3))}, - {version: 2, expectErr: os.ErrNotExist}, - {version: 1, expectErr: nil, expectVersion: 1, expectSeq: seq.add()}, // 3 has no down migration - {version: 0, expectErr: os.ErrNotExist}, + { + version: 6, + expectErr: os.ErrNotExist, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + }, + }, + { + version: 5, + expectVersion: 5, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + }, + }, + { + version: 4, + expectVersion: 4, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + mr("DROP 5"), + }, + }, + { + version: 3, + expectVersion: 3, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + mr("DROP 5"), + mr("DROP 4"), + }, + }, + { + version: 2, + expectErr: os.ErrNotExist, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + mr("DROP 5"), + mr("DROP 4"), + }, + }, + { + version: 1, + expectVersion: 1, + expectSeq: migrationSequence{ // 3 has no down migration + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + mr("DROP 5"), + mr("DROP 4"), + }, + }, + { + version: 0, + expectErr: os.ErrNotExist, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + mr("DROP 5"), + mr("DROP 4"), + }, + }, // migrate all the way Up in one step - {version: 7, expectErr: nil, expectVersion: 7, expectSeq: seq.add(M(3), M(4), M(7))}, + { + version: 7, + expectVersion: 7, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + mr("DROP 5"), + mr("DROP 4"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + }, + }, // migrate all the way Down in one step - {version: 1, expectErr: nil, expectVersion: 1, expectSeq: seq.add(M(7, 5), M(5, 4), M(4, 3), M(3, 1))}, + { + version: 1, + expectVersion: 1, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + mr("DROP 5"), + mr("DROP 4"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + mr("DROP 5"), + mr("DROP 4"), + }, + }, // can't migrate the same version twice - {version: 1, expectErr: ErrNoChange}, + { + version: 1, + expectErr: ErrNoChange, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + mr("DROP 5"), + mr("DROP 4"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + mr("DROP 5"), + mr("DROP 4"), + }, + }, } for i, v := range tt { @@ -276,8 +468,8 @@ func TestMigrate(t *testing.T) { if version != v.expectVersion { t.Errorf("expected version %v, got %v, in %v", v.expectVersion, version, i) } - equalDbSeq(t, i, v.expectSeq, dbDrv) } + equalDbSeq(t, i, v.expectSeq, dbDrv) } } @@ -298,50 +490,235 @@ func TestSteps(t *testing.T) { m, _ := New("stub://", "stub://") m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations dbDrv := m.databaseDrv.(*dStub.Stub) - seq := newMigSeq() tt := []struct { - n int + steps int expectErr error expectVersion int expectSeq migrationSequence }{ // step must be != 0 - {n: 0, expectErr: ErrNoChange}, + { + steps: 0, + expectErr: ErrNoChange, + }, // can't go Down if ErrNilVersion - {n: -1, expectErr: os.ErrNotExist}, + { + steps: -1, + expectErr: os.ErrNotExist, + }, // migrate all the way Up - {n: 1, expectErr: nil, expectVersion: 1, expectSeq: seq.add(M(1))}, - {n: 1, expectErr: nil, expectVersion: 3, expectSeq: seq.add(M(3))}, - {n: 1, expectErr: nil, expectVersion: 4, expectSeq: seq.add(M(4))}, - {n: 1, expectErr: nil, expectVersion: 5, expectSeq: seq.add()}, - {n: 1, expectErr: nil, expectVersion: 7, expectSeq: seq.add(M(7))}, - {n: 1, expectErr: os.ErrNotExist}, + { + steps: 1, + expectVersion: 1, + expectSeq: migrationSequence{ + mr("CREATE 1")}, + }, + { + steps: 1, + expectVersion: 3, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + }, + }, + { + steps: 1, + expectVersion: 4, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + }, + }, + { + steps: 1, + expectVersion: 5, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + }, + }, + { + steps: 1, + expectVersion: 7, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + }, + }, + { + steps: 1, + expectErr: os.ErrNotExist, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + }, + }, // migrate all the way Down - {n: -1, expectErr: nil, expectVersion: 5, expectSeq: seq.add(M(7, 5))}, - {n: -1, expectErr: nil, expectVersion: 4, expectSeq: seq.add(M(5, 4))}, - {n: -1, expectErr: nil, expectVersion: 3, expectSeq: seq.add(M(4, 3))}, - {n: -1, expectErr: nil, expectVersion: 1, expectSeq: seq.add(M(3, 1))}, - {n: -1, expectErr: nil, expectVersion: -1, expectSeq: seq.add(M(1, -1))}, + { + steps: -1, + expectVersion: 5, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + }, + }, + { + steps: -1, + expectVersion: 4, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + mr("DROP 5"), + }, + }, + { + steps: -1, + expectVersion: 3, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + mr("DROP 5"), + mr("DROP 4"), + }, + }, + { + steps: -1, + expectVersion: 1, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + mr("DROP 5"), + mr("DROP 4"), + }, + }, + { + steps: -1, + expectVersion: -1, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + mr("DROP 5"), + mr("DROP 4"), + mr("DROP 1"), + }, + }, // migrate Up in bigger step - {n: 4, expectErr: nil, expectVersion: 5, expectSeq: seq.add(M(1), M(3), M(4), M(5))}, + { + steps: 4, + expectVersion: 5, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + mr("DROP 5"), + mr("DROP 4"), + mr("DROP 1"), + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + }, + }, // apply one migration, then reaches out of boundary - {n: 2, expectErr: ErrShortLimit{1}, expectVersion: 7, expectSeq: seq.add(M(7))}, + { + steps: 2, + expectErr: ErrShortLimit{1}, + expectVersion: 7, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + mr("DROP 5"), + mr("DROP 4"), + mr("DROP 1"), + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + }, + }, // migrate Down in bigger step - {n: -4, expectErr: nil, expectVersion: 1, expectSeq: seq.add(M(7, 5), M(5, 4), M(4, 3), M(3, 1))}, + { + steps: -4, + expectVersion: 1, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + mr("DROP 5"), + mr("DROP 4"), + mr("DROP 1"), + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + mr("DROP 5"), + mr("DROP 4"), + }, + }, // apply one migration, then reaches out of boundary - {n: -2, expectErr: ErrShortLimit{1}, expectVersion: -1, expectSeq: seq.add(M(1, -1))}, + { + steps: -2, + expectErr: ErrShortLimit{1}, + expectVersion: -1, + expectSeq: migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + mr("DROP 5"), + mr("DROP 4"), + mr("DROP 1"), + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + mr("DROP 5"), + mr("DROP 4"), + mr("DROP 1"), + }, + }, } for i, v := range tt { - err := m.Steps(v.n) + err := m.Steps(v.steps) if (v.expectErr == os.ErrNotExist && !os.IsNotExist(err)) || (v.expectErr != os.ErrNotExist && err != v.expectErr) { t.Errorf("expected err %v, got %v, in %v", v.expectErr, err, i) @@ -357,8 +734,8 @@ func TestSteps(t *testing.T) { } else if v.expectVersion >= 0 && version != uint(v.expectVersion) { t.Errorf("expected version %v, got %v, in %v", v.expectVersion, version, i) } - equalDbSeq(t, i, v.expectSeq, dbDrv) } + equalDbSeq(t, i, v.expectSeq, dbDrv) } } @@ -379,37 +756,114 @@ func TestUpAndDown(t *testing.T) { m, _ := New("stub://", "stub://") m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations dbDrv := m.databaseDrv.(*dStub.Stub) - seq := newMigSeq() // go Up first if err := m.Up(); err != nil { t.Fatal(err) } - equalDbSeq(t, 0, seq.add(M(1), M(3), M(4), M(5), M(7)), dbDrv) + expectedSequence := migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + } + equalDbSeq(t, 0, expectedSequence, dbDrv) // go Down if err := m.Down(); err != nil { t.Fatal(err) } - equalDbSeq(t, 1, seq.add(M(7, 5), M(5, 4), M(4, 3), M(3, 1), M(1, -1)), dbDrv) + expectedSequence = migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + mr("DROP 5"), + mr("DROP 4"), + mr("DROP 1"), + } + equalDbSeq(t, 1, expectedSequence, dbDrv) // go 1 Up and then all the way Up if err := m.Steps(1); err != nil { t.Fatal(err) } + expectedSequence = migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + mr("DROP 5"), + mr("DROP 4"), + mr("DROP 1"), + mr("CREATE 1"), + } + equalDbSeq(t, 2, expectedSequence, dbDrv) + if err := m.Up(); err != nil { t.Fatal(err) } - equalDbSeq(t, 2, seq.add(M(1), M(3), M(4), M(5), M(7)), dbDrv) + expectedSequence = migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + mr("DROP 5"), + mr("DROP 4"), + mr("DROP 1"), + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + } + equalDbSeq(t, 3, expectedSequence, dbDrv) // go 1 Down and then all the way Down if err := m.Steps(-1); err != nil { t.Fatal(err) } + expectedSequence = migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + mr("DROP 5"), + mr("DROP 4"), + mr("DROP 1"), + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + } + equalDbSeq(t, 1, expectedSequence, dbDrv) + if err := m.Down(); err != nil { t.Fatal(err) } - equalDbSeq(t, 0, seq.add(M(7, 5), M(5, 4), M(4, 3), M(3, 1), M(1, -1)), dbDrv) + expectedSequence = migrationSequence{ + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + mr("DROP 5"), + mr("DROP 4"), + mr("DROP 1"), + mr("CREATE 1"), + mr("CREATE 3"), + mr("CREATE 4"), + mr("CREATE 7"), + mr("DROP 7"), + mr("DROP 5"), + mr("DROP 4"), + mr("DROP 1"), + } + equalDbSeq(t, 1, expectedSequence, dbDrv) } func TestUpDirty(t *testing.T) { @@ -892,6 +1346,8 @@ func (m *migrationSequence) bodySequence() []string { v.Body = ioutil.NopCloser(bytes.NewReader(body)) r = append(r, string(body[:])) + } else { + r = append(r, "") } } return r @@ -916,6 +1372,13 @@ func M(version uint, targetVersion ...int) *Migration { return migr } +// mr is a convenience func to create a new *Migration from the raw database query +func mr(value string) *Migration { + return &Migration{ + Body: ioutil.NopCloser(bytes.NewReader([]byte(value))), + } +} + func equalMigSeq(t *testing.T, i int, expected, got migrationSequence) { if len(expected) != len(got) { t.Errorf("expected migrations %v, got %v, in %v", expected, got, i)