Skip to content

Commit 4c4aedd

Browse files
committed
sqldb: add unit test for the v0.19.0-rc1 migration bug
1 parent 83d6230 commit 4c4aedd

File tree

1 file changed

+165
-0
lines changed

1 file changed

+165
-0
lines changed

sqldb/migrations_test.go

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,3 +578,168 @@ func TestSchemaMigrationIdempotency(t *testing.T) {
578578
}
579579
})
580580
}
581+
582+
// TestMigrationBug19RC1 tests a bug that was present in the migration code
583+
// at the v0.19.0-rc1 release.
584+
// The bug was fixed in: https://github.com/lightningnetwork/lnd/pull/9647
585+
// NOTE: This test may be removed once the final version of 0.19.0 is released.
586+
func TestMigrationSucceedsAfterDirtyStateMigrationFailure19RC1(t *testing.T) {
587+
// setMigrationTrackerVersion is a helper function that
588+
// updates the migration tracker table to a specific version that
589+
// simulates the conditions of the bug.
590+
setMigrationTrackerVersion := func(t *testing.T, db *BaseDB) {
591+
_, err := db.Exec(`
592+
DELETE FROM migration_tracker;
593+
INSERT INTO migration_tracker (version, migration_time)
594+
VALUES (2, CURRENT_TIMESTAMP);
595+
`)
596+
require.NoError(t, err)
597+
}
598+
599+
const (
600+
maxSchemaVersionBefore19RC1 = 4
601+
failingSchemaVersion = 3
602+
)
603+
604+
ctxb := context.Background()
605+
migrations := GetMigrations()
606+
migrations = migrations[:maxSchemaVersionBefore19RC1]
607+
lastMigration := migrations[len(migrations)-1]
608+
609+
// Make sure that the last migration is the one we expect.
610+
require.Equal(
611+
t, maxSchemaVersionBefore19RC1, lastMigration.SchemaVersion,
612+
)
613+
614+
t.Run("SQLite", func(t *testing.T) {
615+
// First instantiate the database and run the migrations
616+
// including the custom migrations.
617+
t.Logf("Creating new SQLite DB for testing migrations")
618+
619+
dbFileName := filepath.Join(t.TempDir(), "tmp.db")
620+
var (
621+
db *SqliteStore
622+
err error
623+
)
624+
625+
db, err = NewSqliteStore(&SqliteConfig{
626+
SkipMigrations: false,
627+
}, dbFileName)
628+
require.NoError(t, err)
629+
630+
dbToCleanup := db.DB
631+
t.Cleanup(func() {
632+
require.NoError(t, dbToCleanup.Close())
633+
})
634+
635+
require.NoError(t, db.ApplyAllMigrations(ctxb, migrations))
636+
637+
version, dirty, err := db.GetSchemaVersion()
638+
require.NoError(t, err)
639+
640+
// Now reset the schema version to 0 and make sure that
641+
// we can apply the migrations again.
642+
require.Equal(t, lastMigration.SchemaVersion, version)
643+
require.False(t, dirty)
644+
645+
// Set the schema version to the failing version and
646+
// make make the version dirty which essentially tells
647+
// golang-migrate that the migration failed.
648+
require.NoError(
649+
t, db.SetSchemaVersion(failingSchemaVersion, true),
650+
)
651+
652+
// Set the migration tracker to the failing version.
653+
setMigrationTrackerVersion(t, db.BaseDB)
654+
655+
// Close the DB so we can reopen it and apply the
656+
// migrations again.
657+
db.DB.Close()
658+
659+
db, err = NewSqliteStore(&SqliteConfig{
660+
SkipMigrations: false,
661+
}, dbFileName)
662+
require.NoError(t, err)
663+
664+
dbToCleanup2 := db.DB
665+
t.Cleanup(func() {
666+
require.NoError(t, dbToCleanup2.Close())
667+
})
668+
669+
require.NoError(t, db.ApplyAllMigrations(ctxb, migrations))
670+
671+
version, dirty, err = db.GetSchemaVersion()
672+
require.NoError(t, err)
673+
require.Equal(t, lastMigration.SchemaVersion, version)
674+
require.False(t, dirty)
675+
})
676+
677+
t.Run("Postgres", func(t *testing.T) {
678+
// First create a temporary Postgres database to run
679+
// the migrations on.
680+
fixture := NewTestPgFixture(
681+
t, DefaultPostgresFixtureLifetime,
682+
)
683+
t.Cleanup(func() {
684+
fixture.TearDown(t)
685+
})
686+
687+
dbName := randomDBName(t)
688+
689+
// Next instantiate the database and run the migrations
690+
// including the custom migrations.
691+
t.Logf("Creating new Postgres DB '%s' for testing "+
692+
"migrations", dbName)
693+
694+
_, err := fixture.db.ExecContext(
695+
context.Background(), "CREATE DATABASE "+dbName,
696+
)
697+
require.NoError(t, err)
698+
699+
cfg := fixture.GetConfig(dbName)
700+
var db *PostgresStore
701+
702+
cfg.SkipMigrations = false
703+
db, err = NewPostgresStore(cfg)
704+
require.NoError(t, err)
705+
706+
require.NoError(t, db.ApplyAllMigrations(ctxb, migrations))
707+
708+
version, dirty, err := db.GetSchemaVersion()
709+
require.NoError(t, err)
710+
711+
// Now reset the schema version to 0 and make sure that
712+
// we can apply the migrations again.
713+
require.Equal(t, lastMigration.SchemaVersion, version)
714+
require.False(t, dirty)
715+
716+
// Set the schema version to the failing version and
717+
// make make the version dirty which essentially tells
718+
// golang-migrate that the migration failed.
719+
require.NoError(
720+
t, db.SetSchemaVersion(failingSchemaVersion, true),
721+
)
722+
723+
// Set the migration tracker to the failing version.
724+
setMigrationTrackerVersion(t, db.BaseDB)
725+
726+
// Close the DB so we can reopen it and apply the
727+
// migrations again.
728+
db.DB.Close()
729+
730+
db, err = NewPostgresStore(cfg)
731+
require.NoError(t, err)
732+
733+
dbToCleanup2 := db.DB
734+
t.Cleanup(func() {
735+
require.NoError(t, dbToCleanup2.Close())
736+
})
737+
738+
require.NoError(t, db.ApplyAllMigrations(ctxb, migrations))
739+
740+
version, dirty, err = db.GetSchemaVersion()
741+
require.NoError(t, err)
742+
require.Equal(t, lastMigration.SchemaVersion, version)
743+
require.False(t, dirty)
744+
})
745+
}

0 commit comments

Comments
 (0)