NextWks/src/core/db/db_test.go

176 lines
4 KiB
Go

package db
import (
"database/sql"
"os"
"path/filepath"
"testing"
)
func TestInitialize_CreatesDirectory(t *testing.T) {
tmpDir := t.TempDir()
dbPath := filepath.Join(tmpDir, "subdir", "test.db")
db, err := Initialize(dbPath)
if err != nil {
t.Fatalf("expected no error, got: %v", err)
}
defer db.Close()
// Verify directory was created
if _, err := os.Stat(filepath.Dir(dbPath)); os.IsNotExist(err) {
t.Fatal("expected directory to be created")
}
// Verify database file was created
if _, err := os.Stat(dbPath); os.IsNotExist(err) {
t.Fatal("expected database file to be created")
}
}
func TestInitialize_OpensConnection(t *testing.T) {
tmpDir := t.TempDir()
dbPath := filepath.Join(tmpDir, "test.db")
db, err := Initialize(dbPath)
if err != nil {
t.Fatalf("expected no error, got: %v", err)
}
defer db.Close()
// Verify connection is alive
if err := db.DB.Ping(); err != nil {
t.Fatalf("expected ping to succeed, got: %v", err)
}
}
func TestInitialize_ExistingFile(t *testing.T) {
tmpDir := t.TempDir()
dbPath := filepath.Join(tmpDir, "existing.db")
// Create database once
db1, err := Initialize(dbPath)
if err != nil {
t.Fatalf("first init failed: %v", err)
}
db1.Close()
// Re-open existing database
db2, err := Initialize(dbPath)
if err != nil {
t.Fatalf("second init failed: %v", err)
}
defer db2.Close()
if err := db2.DB.Ping(); err != nil {
t.Fatalf("expected ping to succeed, got: %v", err)
}
}
func TestMigrate_CreatesTables(t *testing.T) {
tmpDir := t.TempDir()
dbPath := filepath.Join(tmpDir, "migrate-test.db")
database, err := Initialize(dbPath)
if err != nil {
t.Fatalf("init failed: %v", err)
}
defer database.Close()
if err := database.Migrate(); err != nil {
t.Fatalf("migrate failed: %v", err)
}
// Verify tables exist
expectedTables := []string{"sessions", "audit_logs"}
for _, table := range expectedTables {
var count int
row := database.DB.QueryRow(
"SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name=?",
table,
)
if err := row.Scan(&count); err != nil {
t.Fatalf("failed to check table %s: %v", table, err)
}
if count == 0 {
t.Errorf("expected table %s to exist", table)
}
}
}
func TestMigrate_Idempotent(t *testing.T) {
tmpDir := t.TempDir()
dbPath := filepath.Join(tmpDir, "idempotent-test.db")
database, err := Initialize(dbPath)
if err != nil {
t.Fatalf("init failed: %v", err)
}
defer database.Close()
// Run migrations twice
if err := database.Migrate(); err != nil {
t.Fatalf("first migrate failed: %v", err)
}
if err := database.Migrate(); err != nil {
t.Fatalf("second migrate should succeed (idempotent), got: %v", err)
}
}
func TestMigrate_TableSchemas(t *testing.T) {
tmpDir := t.TempDir()
dbPath := filepath.Join(tmpDir, "schema-test.db")
database, err := Initialize(dbPath)
if err != nil {
t.Fatalf("init failed: %v", err)
}
defer database.Close()
database.Migrate()
// Verify sessions table columns
rows, err := database.DB.Query("PRAGMA table_info(sessions)")
if err != nil {
t.Fatalf("failed to get sessions schema: %v", err)
}
defer rows.Close()
columns := map[string]bool{}
for rows.Next() {
var cid int
var name, ctype string
var notnull, pk int
var dflt sql.NullString
if err := rows.Scan(&cid, &name, &ctype, &notnull, &dflt, &pk); err != nil {
t.Fatalf("failed to scan column: %v", err)
}
columns[name] = true
_ = ctype
}
expectedCols := []string{"id", "user_id", "token_hash", "created_at", "expires_at"}
for _, col := range expectedCols {
if !columns[col] {
t.Errorf("expected column %q in sessions table", col)
}
}
}
func TestClose(t *testing.T) {
tmpDir := t.TempDir()
dbPath := filepath.Join(tmpDir, "close-test.db")
database, err := Initialize(dbPath)
if err != nil {
t.Fatalf("init failed: %v", err)
}
if err := database.Close(); err != nil {
t.Fatalf("close failed: %v", err)
}
// Ping should fail after close
if err := database.DB.Ping(); err == nil {
t.Fatal("expected ping to fail after close")
}
}