mirror of
https://github.com/lightninglabs/lightning-terminal.git
synced 2026-08-13 12:33:36 +02:00
Reject `litd` startup when another SQL database exists than the selected SQL `databasebackend` choice. When starting with the `databasebackend` config flag set to `postgres`, we check whether an `sqlite` database file exists at the default path and fail startup if it does. When starting with `sqlite`, we instead check whether `postgres` database configuration has been provided and, if so, whether a database exists at the configured `postgres` connection parameters. This prevents accidental switches between SQL backends. This is especially important because allowing such a switch would retrigger the KVDB-to-SQL migration for the newly configured SQL backend. In that scenario, the data would already have been migrated previously, meaning the migration source would be stale and could result in outdated data being imported. Additionally, it would create two divergent copies of the data across separate SQL backends. Since we do not support migrations between SQL backends, recovering from such a situation would not be possible.
143 lines
4.1 KiB
Go
143 lines
4.1 KiB
Go
package terminal
|
|
|
|
import (
|
|
"database/sql"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/lightninglabs/lightning-terminal/db"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// TestBlockStartupForPostgresIfSqliteDBExists verifies that a Postgres startup
|
|
// is rejected when the default SQLite database file still exists for the
|
|
// selected network.
|
|
func TestBlockStartupForPostgresIfSqliteDBExists(t *testing.T) {
|
|
litDir := t.TempDir()
|
|
sqlitePath := filepath.Join(
|
|
litDir, "regtest", defaultSqliteDatabaseFileName,
|
|
)
|
|
|
|
fixture := db.NewTestPgFixture(
|
|
t, db.DefaultPostgresFixtureLifetime, true,
|
|
)
|
|
t.Cleanup(func() {
|
|
fixture.TearDown(t)
|
|
})
|
|
|
|
require.NoError(t, os.MkdirAll(filepath.Dir(sqlitePath), 0700))
|
|
require.NoError(t, os.WriteFile(sqlitePath, []byte("sqlite"), 0600))
|
|
|
|
cfg := &Config{
|
|
DatabaseBackend: DatabaseBackendPostgres,
|
|
LitDir: litDir,
|
|
Network: "regtest",
|
|
Postgres: fixture.GetConfig(),
|
|
}
|
|
|
|
err := validateExclusiveSQLBackends(cfg, litDir)
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "sqlite database file already exists")
|
|
require.Contains(t, err.Error(), sqlitePath)
|
|
}
|
|
|
|
// TestBlockStartupForSqliteIfPostgresDBExists verifies that a SQLite startup is
|
|
// rejected when the configured Postgres database already exists.
|
|
func TestBlockStartupForSqliteIfPostgresDBExists(t *testing.T) {
|
|
fixture := db.NewTestPgFixture(
|
|
t, db.DefaultPostgresFixtureLifetime, true,
|
|
)
|
|
t.Cleanup(func() {
|
|
fixture.TearDown(t)
|
|
})
|
|
|
|
cfg := &Config{
|
|
DatabaseBackend: DatabaseBackendSqlite,
|
|
Postgres: fixture.GetConfig(),
|
|
}
|
|
|
|
err := validateExclusiveSQLBackends(cfg, "")
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "postgres database")
|
|
require.Contains(t, err.Error(), cfg.Postgres.DBName)
|
|
}
|
|
|
|
// TestDontBlockSqliteOnlyStartup verifies that SQLite startup is allowed when
|
|
// no concrete Postgres database is configured.
|
|
func TestDontBlockSqliteOnlyStartup(t *testing.T) {
|
|
cfg := &Config{
|
|
DatabaseBackend: DatabaseBackendSqlite,
|
|
}
|
|
|
|
require.NoError(t, validateExclusiveSQLBackends(cfg, ""))
|
|
}
|
|
|
|
// TestDontBlockSqliteStartupIfConfiguredPostgresDoesntExist verifies that a
|
|
// SQLite startup is allowed when the configured Postgres database does not
|
|
// exist.
|
|
func TestDontBlockSqliteStartupIfConfiguredPostgresDoesntExist(t *testing.T) {
|
|
fixture := db.NewTestPgFixture(
|
|
t, db.DefaultPostgresFixtureLifetime, true,
|
|
)
|
|
t.Cleanup(func() {
|
|
fixture.TearDown(t)
|
|
})
|
|
|
|
pgCfg := fixture.GetConfig()
|
|
pgCfg.DBName = "does_not_exist_for_config_validation"
|
|
|
|
cfg := &Config{
|
|
DatabaseBackend: DatabaseBackendSqlite,
|
|
Postgres: pgCfg,
|
|
}
|
|
|
|
require.NoError(t, validateExclusiveSQLBackends(cfg, ""))
|
|
|
|
// We also validate that the validateExclusiveSQLBackends passed because
|
|
// the db with the configured DBName doesn't exist and not because the
|
|
// connection parameters are wrong. This proves that we're ok with a
|
|
// postgres setup existing, as long as the specific database doesn't
|
|
// exist.
|
|
dbConn, err := sql.Open("postgres", pgCfg.DSN(false))
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() {
|
|
require.NoError(t, dbConn.Close())
|
|
})
|
|
|
|
err = dbConn.Ping()
|
|
require.Error(t, err)
|
|
require.True(t, isMissingPostgresDatabase(err))
|
|
}
|
|
|
|
// TestDontBlockPostgresOnlyStartup verifies that a Postgres is allowed when
|
|
// no sqlite database file exists for the selected network, despite the actual
|
|
// folder where the file would be placed exists.
|
|
func TestDontBlockPostgresOnlyStartup(t *testing.T) {
|
|
litDir := t.TempDir()
|
|
sqlitePath := filepath.Join(
|
|
litDir, "regtest", defaultSqliteDatabaseFileName,
|
|
)
|
|
|
|
fixture := db.NewTestPgFixture(
|
|
t, db.DefaultPostgresFixtureLifetime, true,
|
|
)
|
|
t.Cleanup(func() {
|
|
fixture.TearDown(t)
|
|
})
|
|
|
|
require.NoError(t, os.MkdirAll(filepath.Dir(sqlitePath), 0700))
|
|
|
|
// NOTE: we don't write any file to the sqlite path here, so the sqlite
|
|
// database file never exists, only the default directory where it would
|
|
// be located.
|
|
|
|
cfg := &Config{
|
|
DatabaseBackend: DatabaseBackendPostgres,
|
|
LitDir: litDir,
|
|
Network: "regtest",
|
|
Postgres: fixture.GetConfig(),
|
|
}
|
|
|
|
require.NoError(t, validateExclusiveSQLBackends(cfg, litDir))
|
|
}
|