package core import ( "fmt" "io" "os" "path/filepath" "testing" "github.com/google/uuid" ) func TestNewEventsManager(t *testing.T) { m := NewEventsManager() if fmt.Sprintf("%T", m) != "*core.EventsManager" { t.Errorf("failed testing new events manager") } } func TestResolveEventsManager(t *testing.T) { NewEventsManager() m := ResolveEventsManager() if fmt.Sprintf("%T", m) != "*core.EventsManager" { t.Errorf("failed testing resolve events manager") } } func TestEventsFireAndProcess(t *testing.T) { const eventName1 string = "test-event-name1" const eventName2 string = "test-event-name2" tmpDir := t.TempDir() tmpFile1 := filepath.Join(tmpDir, uuid.NewString()) tmpFile2 := filepath.Join(tmpDir, uuid.NewString()) tmpFile3 := filepath.Join(tmpDir, uuid.NewString()) m := NewEventsManager() // Two jobs registered on the same event must BOTH run. m.Register(eventName1, func(event *Event, requestContext *Context) { f, err := os.Create(tmpFile1) if err != nil { t.Errorf("error testing register event: %v", err.Error()) return } f.WriteString(event.Name) f.Close() }) m.Register(eventName1, func(event *Event, requestContext *Context) { f, err := os.Create(tmpFile3) if err != nil { t.Errorf("error testing register event: %v", err.Error()) return } f.WriteString(event.Name) f.Close() }) if err := m.Fire(&Event{Name: eventName1}); err != nil { t.Fatalf("failed firing event: %v", err) } m.processFiredEvents() for _, fp := range []string{tmpFile1, tmpFile3} { f, err := os.Open(fp) if err != nil { t.Errorf("error opening event file %v: %v", fp, err.Error()) continue } d, err := io.ReadAll(f) if err != nil { t.Errorf("error reading event file %v: %v", fp, err.Error()) } if string(d) != eventName1 { t.Errorf("failed testing events: expected %q, got %q", eventName1, string(d)) } f.Close() } // A registered event with a distinct payload is processed independently. m.Register(eventName2, func(event *Event, requestContext *Context) { f, err := os.Create(tmpFile2) if err != nil { t.Errorf("error testing register event: %v", err.Error()) return } f.WriteString(event.Name) f.Close() }) if err := m.Fire(&Event{Name: eventName2}); err != nil { t.Fatalf("failed firing event: %v", err) } m.processFiredEvents() f, err := os.Open(tmpFile2) if err != nil { t.Fatalf("error opening event file: %v", err.Error()) } d, err := io.ReadAll(f) if err != nil { t.Errorf("error reading event file: %v", err.Error()) } f.Close() if string(d) != eventName2 { t.Errorf("failed testing events: expected %q, got %q", eventName2, string(d)) } } func TestEventFireUnregistered(t *testing.T) { m := NewEventsManager() err := m.Fire(&Event{Name: "not-registered"}) if err == nil { t.Errorf("expected error firing an unregistered event") } } func TestEventFireEmptyName(t *testing.T) { m := NewEventsManager() err := m.Fire(&Event{Name: ""}) if err == nil { t.Errorf("expected error firing an event with an empty name") } } func TestEventRegisterEmptyNamePanics(t *testing.T) { m := NewEventsManager() defer func() { if r := recover(); r == nil { t.Errorf("expected panic registering an event with an empty name") } }() m.Register("", func(event *Event, requestContext *Context) {}) } func TestEventsProcessClearsFiredList(t *testing.T) { const eventName = "test-clear-fired" m := NewEventsManager() m.Register(eventName, func(event *Event, requestContext *Context) {}) if err := m.Fire(&Event{Name: eventName}); err != nil { t.Fatalf("failed firing event: %v", err) } if len(m.firedEvents) != 1 { t.Fatalf("expected 1 fired event, got %d", len(m.firedEvents)) } m.processFiredEvents() if len(m.firedEvents) != 0 { t.Errorf("expected fired events to be cleared after processing") } } func TestEventsDisabled(t *testing.T) { DisableEvents() defer EnableEvents() const eventName = "test-disabled-event" m := NewEventsManager() m.Register(eventName, func(event *Event, requestContext *Context) {}) // When disabled, Register is a no-op and Fire returns nil without recording. if len(m.eventsJobsList) != 0 { t.Errorf("expected no jobs registered while events are disabled") } if err := m.Fire(&Event{Name: eventName}); err != nil { t.Errorf("expected Fire to be a no-op while events are disabled, got: %v", err) } if len(m.firedEvents) != 0 { t.Errorf("expected no fired events while events are disabled") } } func TestEventsSetContextAndExecute(t *testing.T) { const eventName = "test-context-event" m := NewEventsManager() var receivedCtx *Context m.Register(eventName, func(event *Event, requestContext *Context) { receivedCtx = requestContext }) expected := &Context{} m.setContext(expected) if err := m.Fire(&Event{Name: eventName}); err != nil { t.Fatalf("failed firing event: %v", err) } m.processFiredEvents() if receivedCtx != expected { t.Errorf("expected the event job to receive the request context") } }