package database import ( "context" "path/filepath" "testing" ) func TestOpenAppliesPragmasAndMigrates(t *testing.T) { ctx := context.Background() path := filepath.Join(t.TempDir(), "db", "glchat.db") db, err := Open(ctx, Options{Path: path, ReadPool: 2, Migrate: true}) if err != nil { t.Fatalf("Open() returned error: %v", err) } defer db.Close() journal, err := db.JournalMode(ctx) if err != nil { t.Fatalf("JournalMode() returned error: %v", err) } if journal != "wal" { t.Errorf("journal mode = %q, want wal", journal) } version, err := db.SchemaVersion(ctx) if err != nil { t.Fatalf("SchemaVersion() returned error: %v", err) } if version < 1 { t.Errorf("schema version = %d, want >= 1", version) } var foreignKeys int if err := db.Writer.QueryRowContext(ctx, "PRAGMA foreign_keys").Scan(&foreignKeys); err != nil { t.Fatalf("read foreign_keys pragma: %v", err) } if foreignKeys != 1 { t.Errorf("foreign_keys = %d, want 1", foreignKeys) } var baseline string if err := db.Reader.QueryRowContext(ctx, `SELECT value FROM instance_settings WHERE key = 'registration_enabled'`, ).Scan(&baseline); err != nil { t.Fatalf("read instance setting: %v", err) } if baseline != "true" { t.Errorf("registration_enabled = %q, want true", baseline) } } func TestMigrateIsIdempotent(t *testing.T) { ctx := context.Background() path := filepath.Join(t.TempDir(), "glchat.db") db, err := Open(ctx, Options{Path: path, ReadPool: 2, Migrate: true}) if err != nil { t.Fatalf("first Open() returned error: %v", err) } if err := db.Migrate(ctx); err != nil { t.Fatalf("second Migrate() returned error: %v", err) } var applied int if err := db.Reader.QueryRowContext(ctx, `SELECT COUNT(*) FROM goose_db_version WHERE version_id = 1 AND is_applied = 1`, ).Scan(&applied); err != nil { t.Fatalf("count applied migrations: %v", err) } if applied != 1 { t.Errorf("migration 1 applied %d times, want 1", applied) } // Baseline-миграция должна применяться ровно один раз, независимо от их числа. version, err := db.SchemaVersion(ctx) if err != nil { t.Fatalf("SchemaVersion: %v", err) } if version < 2 { t.Errorf("schema version = %d, want >= 2 after phase 1 migration", version) } if err := db.Close(); err != nil { t.Fatalf("Close() returned error: %v", err) } } func TestOpenRejectsEmptyPath(t *testing.T) { if _, err := Open(context.Background(), Options{}); err == nil { t.Fatal("Open() accepted an empty path") } } func TestReadyFailsOnClosedDatabase(t *testing.T) { ctx := context.Background() db, err := Open(ctx, Options{Path: filepath.Join(t.TempDir(), "glchat.db"), Migrate: true}) if err != nil { t.Fatalf("Open() returned error: %v", err) } if err := db.Close(); err != nil { t.Fatalf("Close() returned error: %v", err) } if err := db.Ready(ctx); err == nil { t.Fatal("Ready() returned nil for a closed database") } }