yao/event/service_test.go
Max fd24e31912 Update Makefile for enhanced testing and add new event documentation
- Modify unit test commands in the Makefile to include additional skip patterns for memory leak tests, improving test coverage and accuracy.
- Expand benchmark and memory leak detection to include the event module, ensuring comprehensive testing across all components.
- Add new design and TODO documentation files for the event module to facilitate future development.
2026-02-23 12:18:13 +08:00

229 lines
4.7 KiB
Go

package event_test
import (
"context"
"testing"
"github.com/yaoapp/yao/event"
"github.com/yaoapp/yao/event/types"
)
// stubHandler is a minimal Handler for testing registration and lifecycle.
type stubHandler struct {
shutdownCalled bool
}
func (h *stubHandler) Handle(ctx context.Context, ev *types.Event, resp chan<- types.Result) {}
func (h *stubHandler) Shutdown(ctx context.Context) error {
h.shutdownCalled = true
return nil
}
// --- Register + Start/Stop lifecycle ---
func TestStartStop_Basic(t *testing.T) {
event.Reset()
defer event.Reset()
if event.IsStarted() {
t.Fatal("service should not be started initially")
}
if err := event.Start(); err != nil {
t.Fatalf("Start failed: %v", err)
}
if !event.IsStarted() {
t.Fatal("service should be started after Start")
}
if err := event.Stop(context.Background()); err != nil {
t.Fatalf("Stop failed: %v", err)
}
if event.IsStarted() {
t.Fatal("service should not be started after Stop")
}
}
func TestStart_Double(t *testing.T) {
event.Reset()
defer event.Reset()
if err := event.Start(); err != nil {
t.Fatalf("Start failed: %v", err)
}
err := event.Start()
if err != event.ErrAlreadyStart {
t.Fatalf("expected ErrAlreadyStart, got: %v", err)
}
_ = event.Stop(context.Background())
}
func TestStop_WhenNotStarted(t *testing.T) {
event.Reset()
defer event.Reset()
if err := event.Stop(context.Background()); err != nil {
t.Fatalf("Stop on non-started service should succeed, got: %v", err)
}
}
func TestReload_WhenNotStarted(t *testing.T) {
event.Reset()
defer event.Reset()
err := event.Reload()
if err != event.ErrNotStarted {
t.Fatalf("expected ErrNotStarted, got: %v", err)
}
}
func TestReload_WhenStarted(t *testing.T) {
event.Reset()
defer event.Reset()
_ = event.Start()
if err := event.Reload(); err != nil {
t.Fatalf("Reload failed: %v", err)
}
_ = event.Stop(context.Background())
}
// --- Register + options ---
func TestRegister_DefaultOptions(t *testing.T) {
event.Reset()
defer event.Reset()
h := &stubHandler{}
event.Register("test", h)
_ = event.Start()
defer func() { _ = event.Stop(context.Background()) }()
if !event.IsStarted() {
t.Fatal("service should be started")
}
}
func TestRegister_CustomOptions(t *testing.T) {
event.Reset()
defer event.Reset()
h := &stubHandler{}
event.Register("test", h,
event.MaxWorkers(128),
event.ReservedWorkers(5),
event.QueueSize(2048),
)
_ = event.Start()
defer func() { _ = event.Stop(context.Background()) }()
if !event.IsStarted() {
t.Fatal("service should be started")
}
}
// --- Stop calls Shutdown on handlers ---
func TestStop_CallsHandlerShutdown(t *testing.T) {
event.Reset()
defer event.Reset()
h := &stubHandler{}
event.Register("test", h)
_ = event.Start()
if err := event.Stop(context.Background()); err != nil {
t.Fatalf("Stop failed: %v", err)
}
if !h.shutdownCalled {
t.Fatal("Handler.Shutdown should have been called on Stop")
}
}
func TestStop_MultipleHandlersShutdown(t *testing.T) {
event.Reset()
defer event.Reset()
h1 := &stubHandler{}
h2 := &stubHandler{}
event.Register("alpha", h1)
event.Register("bravo", h2)
_ = event.Start()
if err := event.Stop(context.Background()); err != nil {
t.Fatalf("Stop failed: %v", err)
}
if !h1.shutdownCalled || !h2.shutdownCalled {
t.Fatal("all handlers should have been shut down")
}
}
// --- Context SID/Auth propagation ---
func TestWithSID_SIDFrom(t *testing.T) {
ctx := event.WithSID(context.Background(), "sess-123")
got := event.SIDFrom(ctx)
if got != "sess-123" {
t.Fatalf("expected sess-123, got %s", got)
}
}
func TestSIDFrom_Empty(t *testing.T) {
got := event.SIDFrom(context.Background())
if got != "" {
t.Fatalf("expected empty, got %s", got)
}
}
func TestWithAuth_AuthFrom(t *testing.T) {
auth := &types.AuthorizedInfo{UserID: "u-1", TeamID: "t-1"}
ctx := event.WithAuth(context.Background(), auth)
got := event.AuthFrom(ctx)
if got == nil {
t.Fatal("expected non-nil auth")
}
if got.UserID != "u-1" || got.TeamID != "t-1" {
t.Fatalf("unexpected auth: %+v", got)
}
}
func TestAuthFrom_Nil(t *testing.T) {
got := event.AuthFrom(context.Background())
if got != nil {
t.Fatal("expected nil auth from bare context")
}
}
func TestWithSIDAndAuth_Combined(t *testing.T) {
auth := &types.AuthorizedInfo{UserID: "u-2"}
ctx := event.WithSID(context.Background(), "sess-456")
ctx = event.WithAuth(ctx, auth)
if event.SIDFrom(ctx) != "sess-456" {
t.Fatal("SID mismatch")
}
if event.AuthFrom(ctx).UserID != "u-2" {
t.Fatal("Auth mismatch")
}
}
// --- Reset ---
func TestReset_ClearsState(t *testing.T) {
event.Reset()
h := &stubHandler{}
event.Register("test", h)
_ = event.Start()
event.Reset()
if event.IsStarted() {
t.Fatal("service should not be started after Reset")
}
}