Files
pocket-id/backend/internal/utils/db_schema_parity_test.go
T

53 lines
2.4 KiB
Go

//go:build unit
package utils_test
import (
"maps"
"slices"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/pocket-id/pocket-id/backend/internal/utils"
testutils "github.com/pocket-id/pocket-id/backend/internal/utils/testing"
)
// TestDBSchemaParity ensures the SQLite and Postgres migrations produce schemas that encode every column the same way in a data export
// Without this, an export taken from one database provider fails to import into the other (see https://github.com/pocket-id/pocket-id/issues/1603 and https://github.com/pocket-id/pocket-id/issues/1815)
// If this test fails after adding a migration, pick column types for both databases that map to the same utils.DBExportKind
func TestDBSchemaParity(t *testing.T) {
sqliteSchema, err := utils.LoadDBSchemaTypes(testutils.NewDatabaseForTest(t))
require.NoError(t, err)
postgresSchema, err := utils.LoadDBSchemaTypes(testutils.NewPostgresDatabaseForTest(t))
require.NoError(t, err)
// The migration bookkeeping table is managed by golang-migrate and never exported
delete(sqliteSchema, "schema_migrations")
delete(postgresSchema, "schema_migrations")
// Both databases must have the same tables
require.ElementsMatch(t, slices.Collect(maps.Keys(sqliteSchema)), slices.Collect(maps.Keys(postgresSchema)), "SQLite and Postgres must have the same tables")
for table, sqliteColumns := range sqliteSchema {
postgresColumns := postgresSchema[table]
// Both databases must have the same columns in each table
if !assert.ElementsMatchf(t, slices.Collect(maps.Keys(sqliteColumns)), slices.Collect(maps.Keys(postgresColumns)), "SQLite and Postgres must have the same columns in table %q", table) {
continue
}
// Each column must be encoded the same way in an export and accept the same values
for column, sqliteColumn := range sqliteColumns {
postgresColumn := postgresColumns[column]
assert.Equalf(t, sqliteColumn.ExportKind(), postgresColumn.ExportKind(),
"column %s.%s is exported differently: SQLite type %q is %q, Postgres type %q is %q",
table, column, sqliteColumn.Name, sqliteColumn.ExportKind(), postgresColumn.Name, postgresColumn.ExportKind())
assert.Equalf(t, sqliteColumn.Nullable, postgresColumn.Nullable,
"column %s.%s has a different nullability: SQLite nullable=%t, Postgres nullable=%t",
table, column, sqliteColumn.Nullable, postgresColumn.Nullable)
}
}
}