package store import ( "testing" ) func TestInsertEvent_RoundTripsWorkloadID(t *testing.T) { s := newTestStore(t) in := EventLog{ Source: "image", WorkloadID: "wl-abc", Severity: "info", Message: "my-app: deployed", Metadata: `{"workload_id":"wl-abc"}`, } saved, err := s.InsertEvent(in) if err != nil { t.Fatalf("InsertEvent: %v", err) } if saved.ID == 0 { t.Fatal("expected non-zero ID after insert") } if saved.WorkloadID != "wl-abc" { t.Fatalf("returned WorkloadID = %q, want %q", saved.WorkloadID, "wl-abc") } rows, err := s.ListEvents(EventLogFilter{WorkloadID: "wl-abc"}) if err != nil { t.Fatalf("ListEvents: %v", err) } if len(rows) != 1 { t.Fatalf("got %d rows, want 1", len(rows)) } got := rows[0] if got.WorkloadID != "wl-abc" { t.Errorf("WorkloadID = %q, want %q", got.WorkloadID, "wl-abc") } if got.Source != "image" || got.Severity != "info" || got.Message != "my-app: deployed" { t.Errorf("round-trip mismatch: %+v", got) } } func TestInsertEvent_DefaultsWorkloadIDToEmpty(t *testing.T) { s := newTestStore(t) // Non-deploy callers leave WorkloadID at its zero value; the column // must accept "" (NOT NULL DEFAULT ''). saved, err := s.InsertEvent(EventLog{Source: "stale", Severity: "warn", Message: "x"}) if err != nil { t.Fatalf("InsertEvent: %v", err) } if saved.WorkloadID != "" { t.Fatalf("WorkloadID = %q, want empty", saved.WorkloadID) } rows, err := s.ListEvents(EventLogFilter{Source: "stale"}) if err != nil { t.Fatalf("ListEvents: %v", err) } if len(rows) != 1 || rows[0].WorkloadID != "" { t.Fatalf("expected one unscoped row, got %+v", rows) } } func TestListEvents_FilterByWorkloadID(t *testing.T) { s := newTestStore(t) for _, e := range []EventLog{ {Source: "image", WorkloadID: "wl-1", Severity: "info", Message: "a"}, {Source: "image", WorkloadID: "wl-1", Severity: "error", Message: "b"}, {Source: "compose", WorkloadID: "wl-2", Severity: "info", Message: "c"}, {Source: "stale", WorkloadID: "", Severity: "warn", Message: "d"}, } { if _, err := s.InsertEvent(e); err != nil { t.Fatalf("InsertEvent %q: %v", e.Message, err) } } // Filtering by wl-1 returns only its two rows. rows, err := s.ListEvents(EventLogFilter{WorkloadID: "wl-1"}) if err != nil { t.Fatalf("ListEvents wl-1: %v", err) } if len(rows) != 2 { t.Fatalf("wl-1: got %d rows, want 2", len(rows)) } for _, r := range rows { if r.WorkloadID != "wl-1" { t.Errorf("wl-1 filter leaked row with workload_id %q", r.WorkloadID) } } // wl-2 returns exactly one row. rows, err = s.ListEvents(EventLogFilter{WorkloadID: "wl-2"}) if err != nil { t.Fatalf("ListEvents wl-2: %v", err) } if len(rows) != 1 || rows[0].Message != "c" { t.Fatalf("wl-2: got %+v, want single row 'c'", rows) } // Combined workload + severity filter still narrows correctly. rows, err = s.ListEvents(EventLogFilter{WorkloadID: "wl-1", Severity: "error"}) if err != nil { t.Fatalf("ListEvents wl-1+error: %v", err) } if len(rows) != 1 || rows[0].Message != "b" { t.Fatalf("wl-1+error: got %+v, want single row 'b'", rows) } // No filter returns all four rows (back-compat: unscoped query intact). rows, err = s.ListEvents(EventLogFilter{}) if err != nil { t.Fatalf("ListEvents all: %v", err) } if len(rows) != 4 { t.Fatalf("unfiltered: got %d rows, want 4", len(rows)) } }