package storage import ( "strings" "testing" ) func TestAssetsRepoStoresTemplateProfileAndOverlayJSON(t *testing.T) { store := openTestStore(t) defer store.Close() repo := NewAssetsRepo(store.DB()) if err := repo.SaveTemplate("helmet", "helmet template", `{"name":"helmet","template":{"nodes":[],"edges":[]}}`); err != nil { t.Fatalf("SaveTemplate: %v", err) } if err := repo.SaveProfile("gate_a", "helmet", "gate", "gate profile", `{"name":"gate_a","instances":[{"name":"cam1","template":"helmet","params":{"display_name":"Gate A"}}]}`); err != nil { t.Fatalf("SaveProfile: %v", err) } if err := repo.SaveOverlay("night_relaxed", "overlay", `{"name":"night_relaxed","instance_overrides":{"cam1":{"override":{}}}}`); err != nil { t.Fatalf("SaveOverlay: %v", err) } templates, err := repo.ListTemplates() if err != nil { t.Fatalf("ListTemplates: %v", err) } profiles, err := repo.ListProfiles() if err != nil { t.Fatalf("ListProfiles: %v", err) } overlays, err := repo.ListOverlays() if err != nil { t.Fatalf("ListOverlays: %v", err) } if len(templates) != 1 || templates[0].Name != "helmet" { t.Fatalf("unexpected templates: %#v", templates) } if len(profiles) != 1 || profiles[0].Name != "gate_a" || profiles[0].TemplateName != "helmet" { t.Fatalf("unexpected profiles: %#v", profiles) } if len(overlays) != 1 || overlays[0].Name != "night_relaxed" { t.Fatalf("unexpected overlays: %#v", overlays) } } func TestAssetsRepoRenameTemplateUpdatesProfileReferences(t *testing.T) { store := openTestStore(t) defer store.Close() repo := NewAssetsRepo(store.DB()) if err := repo.SaveTemplate("helmet", "helmet template", `{"name":"helmet","description":"helmet template","template":{"nodes":[],"edges":[]}}`); err != nil { t.Fatalf("SaveTemplate: %v", err) } if err := repo.SaveProfile("gate_a", "helmet", "gate", "gate profile", `{"name":"gate_a","business_name":"gate","instances":[{"name":"cam1","template":"helmet","params":{"display_name":"Gate A","rtsp_url":"rtsp://10.0.0.1/live"}}]}`); err != nil { t.Fatalf("SaveProfile: %v", err) } err := repo.RenameTemplate("helmet", "helmet_v2", "helmet v2", `{"name":"helmet_v2","description":"helmet v2","template":{"nodes":[],"edges":[]}}`) if err != nil { t.Fatalf("RenameTemplate: %v", err) } oldRecord, err := repo.GetTemplate("helmet") if err != nil { t.Fatalf("GetTemplate old: %v", err) } if oldRecord != nil { t.Fatalf("expected old template to be removed, got %#v", oldRecord) } newRecord, err := repo.GetTemplate("helmet_v2") if err != nil { t.Fatalf("GetTemplate new: %v", err) } if newRecord == nil || newRecord.Description != "helmet v2" || !strings.Contains(newRecord.BodyJSON, `"name":"helmet_v2"`) { t.Fatalf("expected renamed template, got %#v", newRecord) } profile, err := repo.GetProfile("gate_a") if err != nil { t.Fatalf("GetProfile: %v", err) } if profile == nil || profile.TemplateName != "helmet_v2" || !strings.Contains(profile.BodyJSON, `"primary_template_name": "helmet_v2"`) && !strings.Contains(profile.BodyJSON, `"primary_template_name":"helmet_v2"`) { t.Fatalf("expected profile template ref updated, got %#v", profile) } } func TestAssetsRepoDeleteTemplateRemovesRecord(t *testing.T) { store := openTestStore(t) defer store.Close() repo := NewAssetsRepo(store.DB()) if err := repo.SaveTemplate("helmet", "helmet template", `{"name":"helmet","template":{"nodes":[],"edges":[]}}`); err != nil { t.Fatalf("SaveTemplate: %v", err) } if err := repo.DeleteTemplate("helmet"); err != nil { t.Fatalf("DeleteTemplate: %v", err) } record, err := repo.GetTemplate("helmet") if err != nil { t.Fatalf("GetTemplate: %v", err) } if record != nil { t.Fatalf("expected template deleted, got %#v", record) } } func TestAssetsRepoStoresIntegrationServiceDisabledState(t *testing.T) { store := openTestStore(t) defer store.Close() repo := NewAssetsRepo(store.DB()) if err := repo.SaveIntegrationService( "minio_primary", "object_storage", "primary object store", false, `{"name":"minio_primary","type":"object_storage","provider":"minio","enabled":false}`, ); err != nil { t.Fatalf("SaveIntegrationService: %v", err) } records, err := repo.ListIntegrationServices() if err != nil { t.Fatalf("ListIntegrationServices: %v", err) } if len(records) != 1 { t.Fatalf("expected one integration service, got %#v", records) } if records[0].ServiceType != "object_storage" || records[0].Enabled { t.Fatalf("unexpected integration service record: %#v", records[0]) } record, err := repo.GetIntegrationService("minio_primary") if err != nil { t.Fatalf("GetIntegrationService: %v", err) } if record == nil { t.Fatal("expected integration service record") } if record.ServiceType != "object_storage" || record.Enabled { t.Fatalf("unexpected integration service fetch: %#v", record) } if !strings.Contains(record.BodyJSON, `"provider":"minio"`) { t.Fatalf("expected body_json payload preserved, got %#v", record) } } func TestAssetsRepoStoresVideoSource(t *testing.T) { store := openTestStore(t) defer store.Close() repo := NewAssetsRepo(store.DB()) if err := repo.SaveVideoSource( "gate_cam_01", "rtsp", "东门入口", "东门主入口摄像头", `{"name":"gate_cam_01","source_type":"rtsp","area":"东门入口","description":"东门主入口摄像头","config":{"url":"rtsp://10.0.0.1/live","resolution":"1080p","frame_size":"1920x1080","fps":"25","video_format":"h264"}}`, ); err != nil { t.Fatalf("SaveVideoSource: %v", err) } records, err := repo.ListVideoSources() if err != nil { t.Fatalf("ListVideoSources: %v", err) } if len(records) != 1 { t.Fatalf("expected one video source, got %#v", records) } if records[0].SourceType != "rtsp" || records[0].Area != "东门入口" { t.Fatalf("unexpected video source record: %#v", records[0]) } record, err := repo.GetVideoSource("gate_cam_01") if err != nil { t.Fatalf("GetVideoSource: %v", err) } if record == nil { t.Fatal("expected video source record") } if record.SourceType != "rtsp" || record.Area != "东门入口" { t.Fatalf("unexpected video source fetch: %#v", record) } if !strings.Contains(record.BodyJSON, `"resolution":"1080p"`) { t.Fatalf("expected body_json payload preserved, got %#v", record) } }