package db import ( "context" "testing" ) // ExpectedUserVersion is the schema version after all migrations have been applied. // Increment this when adding a new migration file. const ExpectedUserVersion = 1 func TestSchema(t *testing.T) { var ( ctx = t.Context() db = createDB(t) ) defer db.Close() t.Run("InitialVersion", func(t *testing.T) { testInitialVersion(t, ctx, db) }) if err := db.ApplySchema(ctx, nil); err != nil { t.Fatalf("ApplySchema: %v", err) } t.Run("ApplySchema", func(t *testing.T) { testApplySchema(t, ctx, db) }) t.Run("ApplySchemaIdempotent", func(t *testing.T) { testSchemaIdempotent(t, ctx, db) }) t.Run("ApplySchemaTablesExist", func(t *testing.T) { testTablesExist(t, ctx, db) }) t.Run("ApplySchemaIndexesExist", func(t *testing.T) { testSchemaIndexes(t, ctx, db) }) } func testInitialVersion(t *testing.T, ctx context.Context, db *SQLite) { var version int err := db.Reader.QueryRowContext( ctx, "PRAGMA user_version", ).Scan(&version) if err != nil { t.Fatalf("PRAGMA user_version: %v", err) } if version != 0 { t.Fatalf("expected initial version 0, got %d", version) } } func testApplySchema(t *testing.T, ctx context.Context, db *SQLite) { var version int err := db.Reader.QueryRowContext( ctx, "PRAGMA user_version", ).Scan(&version) if err != nil { t.Fatalf("PRAGMA user_version: %v", err) } if version != ExpectedUserVersion { t.Fatalf("expected version %d, got %d", ExpectedUserVersion, version) } } func testTablesExist(t *testing.T, ctx context.Context, db *SQLite) { expected := []string{ "approvals", "conversations", "messages", "sessions", "users", } for _, table := range expected { var exists bool err := db.Reader.QueryRowContext( ctx, "SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ? LIMIT 1)", table, ).Scan(&exists) if err != nil { t.Fatalf("query sqlite_master for %s: %v", table, err) } if !exists { t.Errorf("table %s does not exist", table) } } } func testSchemaIdempotent(t *testing.T, ctx context.Context, db *SQLite) { // Apply schema again; should succeed without error. if err := db.ApplySchema(ctx, nil); err != nil { t.Fatalf("second ApplySchema: %v", err) } var version int err := db.Reader.QueryRowContext( ctx, "PRAGMA user_version", ).Scan(&version) if err != nil { t.Fatalf("PRAGMA user_version: %v", err) } if version != ExpectedUserVersion { t.Fatalf("expected version %d, got %d", ExpectedUserVersion, version) } } func testSchemaIndexes(t *testing.T, ctx context.Context, db *SQLite) { expected := []string{ "idx_approvals_message", "idx_approvals_pending", "idx_conv_user", "idx_msg_conv", "idx_msg_conv_seq", "idx_sessions_active", "idx_users_deactivated", } for _, idx := range expected { var exists bool err := db.Reader.QueryRowContext( ctx, "SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE type = 'index' AND name = ? LIMIT 1)", idx, ).Scan(&exists) if err != nil { t.Fatalf("query sqlite_master for index %s: %v", idx, err) } if !exists { t.Errorf("index %s does not exist", idx) } } }