package bell_event_test import ( "errors" "testing" "time" "go-admin/app/bell/event" ) func validCommand() event.Command { return event.Command{ ProducerID: " bell.synthetic ", SourceEventID: " test-001 ", EventType: " danger_area_entered ", OccurredAt: time.Date(2026, 8, 29, 0, 0, 0, 0, time.FixedZone("CST", 8*60*60)), Location: " 东门 ", Severity: " HIGH ", Attributes: map[string]any{"z": 2, "a": "first"}, } } func TestNormalizeIsDeterministicAndTrimsBusinessFields(t *testing.T) { first, err := event.Normalize(validCommand()) if err != nil { t.Fatal(err) } secondCommand := validCommand() secondCommand.Attributes = map[string]any{"a": "first", "z": 2} second, err := event.Normalize(secondCommand) if err != nil { t.Fatal(err) } if first.Digest != second.Digest || string(first.Payload) != string(second.Payload) { t.Fatalf("normalized payload is not deterministic: %s != %s", first.Payload, second.Payload) } if first.Command.ProducerID != "bell.synthetic" || first.Command.Severity != "high" { t.Fatalf("fields were not normalized: %#v", first.Command) } if first.Command.OccurredAt.Location() != time.UTC { t.Fatalf("occurredAt was not converted to UTC: %v", first.Command.OccurredAt) } } func TestNormalizeRejectsUnsafeOrInvalidInput(t *testing.T) { tests := []struct { name string mutate func(*event.Command) }{ {name: "missing source id", mutate: func(c *event.Command) { c.SourceEventID = " " }}, {name: "unknown severity", mutate: func(c *event.Command) { c.Severity = "urgent" }}, {name: "newline in location", mutate: func(c *event.Command) { c.Location = "东门\nsecret" }}, {name: "unsafe evidence path", mutate: func(c *event.Command) { value := `C:\\secret.jpg`; c.EvidenceRef = &value }}, {name: "oversized attributes", mutate: func(c *event.Command) { c.Attributes = map[string]any{"blob": string(make([]byte, 49*1024))} }}, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { command := validCommand() test.mutate(&command) if _, err := event.Normalize(command); !errors.Is(err, event.ErrInvalid) { t.Fatalf("expected ErrInvalid, got %v", err) } }) } }