package db import ( "testing" "time" ) func TestInitDB_SQLite(t *testing.T) { client, driver, err := InitDB("sqlite://:memory:") if err != nil { t.Fatalf("InitDB() error = %v", err) } if driver != "sqlite" { t.Errorf("InitDB() driver = %q, want sqlite", driver) } if client == nil { t.Fatal("InitDB() client = nil") } // Verify tables exist by running AutoMigrate (idempotent) err = client.DB.AutoMigrate(&Message{}, &ModerationLog{}, &Media{}, &ScheduleOverride{}) if err != nil { t.Errorf("AutoMigrate error = %v", err) } // Verify CRUD on Message msg := Message{ Room: "test", Username: "user1", Text: "hello", Timestamp: time.Now(), Type: "public", } if err := client.DB.Create(&msg).Error; err != nil { t.Fatalf("Create message error = %v", err) } if msg.ID == 0 { t.Error("Create message did not set ID") } var count int64 client.DB.Model(&Message{}).Count(&count) if count != 1 { t.Errorf("Message count = %d, want 1", count) } // Verify read var read Message if err := client.DB.First(&read, msg.ID).Error; err != nil { t.Fatalf("First message error = %v", err) } if read.Text != "hello" { t.Errorf("read.Text = %q, want hello", read.Text) } // Verify delete client.DB.Delete(&Message{}, msg.ID) client.DB.Model(&Message{}).Count(&count) if count != 0 { t.Errorf("Message count after delete = %d, want 0", count) } } func TestInitDB_ModerationLog(t *testing.T) { client, _, err := InitDB("sqlite://:memory:") if err != nil { t.Fatalf("InitDB() error = %v", err) } log := ModerationLog{ Action: "mute", Target: "user1", Moderator: "admin", Reason: "spam", Timestamp: time.Now(), } if err := client.DB.Create(&log).Error; err != nil { t.Fatalf("Create moderation log error = %v", err) } if log.ID == 0 { t.Error("Create moderation log did not set ID") } var count int64 client.DB.Model(&ModerationLog{}).Count(&count) if count != 1 { t.Errorf("ModerationLog count = %d, want 1", count) } } func TestInitDB_Media(t *testing.T) { client, _, err := InitDB("sqlite://:memory:") if err != nil { t.Fatalf("InitDB() error = %v", err) } media := Media{ Filename: "test.mp4", OriginalName: "test.mp4", Path: "/media/test.mp4", SizeBytes: 1024, DurationSeconds: 60, Status: "ready", Title: "Test Video", Tags: "tag1,tag2", } if err := client.DB.Create(&media).Error; err != nil { t.Fatalf("Create media error = %v", err) } if media.ID == 0 { t.Error("Create media did not set ID") } // Verify update client.DB.Model(&media).Update("status", "needs_normalization") var updated Media client.DB.First(&updated, media.ID) if updated.Status != "needs_normalization" { t.Errorf("updated.Status = %q, want needs_normalization", updated.Status) } } func TestInitDB_ScheduleOverride(t *testing.T) { client, _, err := InitDB("sqlite://:memory:") if err != nil { t.Fatalf("InitDB() error = %v", err) } now := time.Now() ov := ScheduleOverride{ MediaID: 1, StartTime: now, EndTime: now.Add(1 * time.Hour), Reason: "special event", } if err := client.DB.Create(&ov).Error; err != nil { t.Fatalf("Create schedule override error = %v", err) } if ov.ID == 0 { t.Error("Create schedule override did not set ID") } // Conflict detection var conflict int64 client.DB.Model(&ScheduleOverride{}). Where("start_time < ? AND end_time > ?", ov.EndTime, ov.StartTime). Count(&conflict) if conflict != 1 { t.Errorf("conflict count = %d, want 1", conflict) } } func TestInitDB_EmptyURL(t *testing.T) { // Empty URL should default to SQLite chat.db // This creates a file, clean up after client, driver, err := InitDB("") if err != nil { t.Fatalf("InitDB(\"\") error = %v", err) } if driver != "sqlite" { t.Errorf("InitDB(\"\") driver = %q, want sqlite", driver) } if client == nil { t.Fatal("InitDB(\"\") client = nil") } } func TestInitDB_SQLitePath(t *testing.T) { client, driver, err := InitDB("sqlite://:memory:?cache=shared") if err != nil { t.Fatalf("InitDB() error = %v", err) } if driver != "sqlite" { t.Errorf("InitDB() driver = %q, want sqlite", driver) } if client == nil { t.Fatal("InitDB() client = nil") } }