sqldb: add unit test for the v0.19.0-rc1 migration bug

This commit is contained in:
Andras Banki-Horvath
2025-03-26 15:11:52 +01:00
parent 83d62308e9
commit 4c4aeddeb0

View File

@ -578,3 +578,168 @@ func TestSchemaMigrationIdempotency(t *testing.T) {
}
})
}
// TestMigrationBug19RC1 tests a bug that was present in the migration code
// at the v0.19.0-rc1 release.
// The bug was fixed in: https://github.com/lightningnetwork/lnd/pull/9647
// NOTE: This test may be removed once the final version of 0.19.0 is released.
func TestMigrationSucceedsAfterDirtyStateMigrationFailure19RC1(t *testing.T) {
// setMigrationTrackerVersion is a helper function that
// updates the migration tracker table to a specific version that
// simulates the conditions of the bug.
setMigrationTrackerVersion := func(t *testing.T, db *BaseDB) {
_, err := db.Exec(`
DELETE FROM migration_tracker;
INSERT INTO migration_tracker (version, migration_time)
VALUES (2, CURRENT_TIMESTAMP);
`)
require.NoError(t, err)
}
const (
maxSchemaVersionBefore19RC1 = 4
failingSchemaVersion = 3
)
ctxb := context.Background()
migrations := GetMigrations()
migrations = migrations[:maxSchemaVersionBefore19RC1]
lastMigration := migrations[len(migrations)-1]
// Make sure that the last migration is the one we expect.
require.Equal(
t, maxSchemaVersionBefore19RC1, lastMigration.SchemaVersion,
)
t.Run("SQLite", func(t *testing.T) {
// First instantiate the database and run the migrations
// including the custom migrations.
t.Logf("Creating new SQLite DB for testing migrations")
dbFileName := filepath.Join(t.TempDir(), "tmp.db")
var (
db *SqliteStore
err error
)
db, err = NewSqliteStore(&SqliteConfig{
SkipMigrations: false,
}, dbFileName)
require.NoError(t, err)
dbToCleanup := db.DB
t.Cleanup(func() {
require.NoError(t, dbToCleanup.Close())
})
require.NoError(t, db.ApplyAllMigrations(ctxb, migrations))
version, dirty, err := db.GetSchemaVersion()
require.NoError(t, err)
// Now reset the schema version to 0 and make sure that
// we can apply the migrations again.
require.Equal(t, lastMigration.SchemaVersion, version)
require.False(t, dirty)
// Set the schema version to the failing version and
// make make the version dirty which essentially tells
// golang-migrate that the migration failed.
require.NoError(
t, db.SetSchemaVersion(failingSchemaVersion, true),
)
// Set the migration tracker to the failing version.
setMigrationTrackerVersion(t, db.BaseDB)
// Close the DB so we can reopen it and apply the
// migrations again.
db.DB.Close()
db, err = NewSqliteStore(&SqliteConfig{
SkipMigrations: false,
}, dbFileName)
require.NoError(t, err)
dbToCleanup2 := db.DB
t.Cleanup(func() {
require.NoError(t, dbToCleanup2.Close())
})
require.NoError(t, db.ApplyAllMigrations(ctxb, migrations))
version, dirty, err = db.GetSchemaVersion()
require.NoError(t, err)
require.Equal(t, lastMigration.SchemaVersion, version)
require.False(t, dirty)
})
t.Run("Postgres", func(t *testing.T) {
// First create a temporary Postgres database to run
// the migrations on.
fixture := NewTestPgFixture(
t, DefaultPostgresFixtureLifetime,
)
t.Cleanup(func() {
fixture.TearDown(t)
})
dbName := randomDBName(t)
// Next instantiate the database and run the migrations
// including the custom migrations.
t.Logf("Creating new Postgres DB '%s' for testing "+
"migrations", dbName)
_, err := fixture.db.ExecContext(
context.Background(), "CREATE DATABASE "+dbName,
)
require.NoError(t, err)
cfg := fixture.GetConfig(dbName)
var db *PostgresStore
cfg.SkipMigrations = false
db, err = NewPostgresStore(cfg)
require.NoError(t, err)
require.NoError(t, db.ApplyAllMigrations(ctxb, migrations))
version, dirty, err := db.GetSchemaVersion()
require.NoError(t, err)
// Now reset the schema version to 0 and make sure that
// we can apply the migrations again.
require.Equal(t, lastMigration.SchemaVersion, version)
require.False(t, dirty)
// Set the schema version to the failing version and
// make make the version dirty which essentially tells
// golang-migrate that the migration failed.
require.NoError(
t, db.SetSchemaVersion(failingSchemaVersion, true),
)
// Set the migration tracker to the failing version.
setMigrationTrackerVersion(t, db.BaseDB)
// Close the DB so we can reopen it and apply the
// migrations again.
db.DB.Close()
db, err = NewPostgresStore(cfg)
require.NoError(t, err)
dbToCleanup2 := db.DB
t.Cleanup(func() {
require.NoError(t, dbToCleanup2.Close())
})
require.NoError(t, db.ApplyAllMigrations(ctxb, migrations))
version, dirty, err = db.GetSchemaVersion()
require.NoError(t, err)
require.Equal(t, lastMigration.SchemaVersion, version)
require.False(t, dirty)
})
}