7582279077
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/claude-agent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
169 lines
3.3 KiB
Go
169 lines
3.3 KiB
Go
package eventbus
|
|
|
|
import (
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestEventBus_PublishSubscribe(t *testing.T) {
|
|
bus := New()
|
|
sub, cleanup := bus.Subscribe("test-topic")
|
|
defer cleanup()
|
|
|
|
event := &Event{Seq: 1, EventType: "status", Message: "hello"}
|
|
bus.Publish("test-topic", event)
|
|
|
|
got, ok := sub.Ring.Pop()
|
|
require.True(t, ok)
|
|
assert.Equal(t, event, got)
|
|
}
|
|
|
|
func TestEventBus_MultipleSubscribers(t *testing.T) {
|
|
bus := New()
|
|
sub1, cleanup1 := bus.Subscribe("topic")
|
|
defer cleanup1()
|
|
sub2, cleanup2 := bus.Subscribe("topic")
|
|
defer cleanup2()
|
|
sub3, cleanup3 := bus.Subscribe("topic")
|
|
defer cleanup3()
|
|
|
|
event := &Event{Seq: 1, EventType: "status"}
|
|
bus.Publish("topic", event)
|
|
|
|
got1, ok := sub1.Ring.Pop()
|
|
require.True(t, ok)
|
|
assert.Equal(t, event, got1)
|
|
|
|
got2, ok := sub2.Ring.Pop()
|
|
require.True(t, ok)
|
|
assert.Equal(t, event, got2)
|
|
|
|
got3, ok := sub3.Ring.Pop()
|
|
require.True(t, ok)
|
|
assert.Equal(t, event, got3)
|
|
}
|
|
|
|
func TestEventBus_GlobalSubscriber(t *testing.T) {
|
|
bus := New()
|
|
sub, cleanup := bus.SubscribeGlobal()
|
|
defer cleanup()
|
|
|
|
bus.Publish("topic-a", &Event{Seq: 1})
|
|
bus.Publish("topic-b", &Event{Seq: 2})
|
|
bus.Publish("topic-c", &Event{Seq: 3})
|
|
|
|
got, ok := sub.Ring.Pop()
|
|
require.True(t, ok)
|
|
assert.Equal(t, int64(1), got.Seq)
|
|
|
|
got, ok = sub.Ring.Pop()
|
|
require.True(t, ok)
|
|
assert.Equal(t, int64(2), got.Seq)
|
|
|
|
got, ok = sub.Ring.Pop()
|
|
require.True(t, ok)
|
|
assert.Equal(t, int64(3), got.Seq)
|
|
}
|
|
|
|
func TestEventBus_TopicIsolation(t *testing.T) {
|
|
bus := New()
|
|
subA, cleanupA := bus.Subscribe("topic-a")
|
|
defer cleanupA()
|
|
|
|
bus.Publish("topic-b", &Event{Seq: 1})
|
|
|
|
_, ok := subA.Ring.Pop()
|
|
assert.False(t, ok)
|
|
}
|
|
|
|
func TestEventBus_Notification(t *testing.T) {
|
|
bus := New()
|
|
sub, cleanup := bus.Subscribe("topic")
|
|
defer cleanup()
|
|
|
|
bus.Publish("topic", &Event{Seq: 1})
|
|
|
|
select {
|
|
case <-sub.C:
|
|
case <-time.After(100 * time.Millisecond):
|
|
t.Fatal("expected notification on channel")
|
|
}
|
|
}
|
|
|
|
func TestEventBus_Unsubscribe(t *testing.T) {
|
|
bus := New()
|
|
sub, cleanup := bus.Subscribe("topic")
|
|
|
|
bus.Publish("topic", &Event{Seq: 1})
|
|
_, ok := sub.Ring.Pop()
|
|
require.True(t, ok)
|
|
|
|
cleanup()
|
|
|
|
bus.Publish("topic", &Event{Seq: 2})
|
|
_, ok = sub.Ring.Pop()
|
|
assert.False(t, ok)
|
|
}
|
|
|
|
func TestEventBus_SlowSubscriber(t *testing.T) {
|
|
bus := New()
|
|
sub, cleanup := bus.Subscribe("topic")
|
|
defer cleanup()
|
|
|
|
for i := 0; i < 500; i++ {
|
|
bus.Publish("topic", &Event{Seq: int64(i)})
|
|
}
|
|
|
|
assert.Equal(t, 256, sub.Ring.Len())
|
|
|
|
first, ok := sub.Ring.Pop()
|
|
require.True(t, ok)
|
|
assert.Equal(t, int64(244), first.Seq)
|
|
}
|
|
|
|
func TestEventBus_HasTopic(t *testing.T) {
|
|
bus := New()
|
|
|
|
assert.False(t, bus.HasTopic("topic"))
|
|
|
|
sub, cleanup := bus.Subscribe("topic")
|
|
_ = sub
|
|
assert.True(t, bus.HasTopic("topic"))
|
|
|
|
cleanup()
|
|
assert.False(t, bus.HasTopic("topic"))
|
|
}
|
|
|
|
func TestEventBus_ConcurrentPublishSubscribe(t *testing.T) {
|
|
bus := New()
|
|
var wg sync.WaitGroup
|
|
|
|
for i := 0; i < 5; i++ {
|
|
wg.Add(1)
|
|
go func(id int) {
|
|
defer wg.Done()
|
|
sub, cleanup := bus.Subscribe("topic")
|
|
defer cleanup()
|
|
for j := 0; j < 100; j++ {
|
|
sub.Ring.Pop()
|
|
}
|
|
}(i)
|
|
}
|
|
|
|
for i := 0; i < 5; i++ {
|
|
wg.Add(1)
|
|
go func(id int) {
|
|
defer wg.Done()
|
|
for j := 0; j < 100; j++ {
|
|
bus.Publish("topic", &Event{Seq: int64(id*100 + j)})
|
|
}
|
|
}(i)
|
|
}
|
|
|
|
wg.Wait()
|
|
}
|