Files
bl/common/utils/event/main_test.go

169 lines
3.0 KiB
Go
Raw Normal View History

package bus_test
import (
"sync"
"sync/atomic"
"testing"
"github.com/badu/bus"
)
func TestSubTopicWhilePub(t *testing.T) {
// scenario : we have a large number of subscribers.
// we publish an event and while doing that,
// we register another one on a different goroutine
topic := bus.NewTopic[*Uint32AsyncEvent]()
for i := 0; i < 4096; i++ {
topic.Sub(func(v *Uint32AsyncEvent) {})
}
finishPubWait := make(chan struct{})
finishSubWait := make(chan struct{})
start := make(chan struct{})
go func() {
<-start
topic.PubAsync(&Uint32AsyncEvent{u: 1})
defer close(finishPubWait)
}()
newSubCalled := false
go func() {
<-start
topic.Sub(func(v *Uint32AsyncEvent) {
newSubCalled = true
})
close(finishSubWait)
}()
close(start) // start both goroutines
<-finishPubWait // wait for pub to finish
<-finishSubWait // wait for sub to finish
if newSubCalled {
t.Fatal("new subscriber should not be called")
}
}
func TestReusePayloadPointerAsync(t *testing.T) {
// if you reuse the payload, you can alter it's content, of course
topic := bus.NewTopic[*Uint32AsyncEvent]()
c := uint32(0)
for i := 0; i < 4096; i++ {
k := i
topic.Sub(func(v *Uint32AsyncEvent) {
if v.u == 2048 {
atomic.AddUint32(&c, 1)
return
}
if k == 2048 {
v.u = 2048
}
})
}
finishPubWait := make(chan struct{})
payload := Uint32AsyncEvent{u: 1}
topic.Pub(&payload)
close(finishPubWait)
<-finishPubWait // wait for pub to finish
t.Logf("altered payload %d for %d listeners", payload.u, c)
}
func TestAsyncBus(t *testing.T) {
c := uint32(0)
var wg sync.WaitGroup
wg.Add(4096)
bus.Sub(
func(event Uint32AsyncEvent) {
atomic.AddUint32(&c, 1)
wg.Done()
},
)
go func() {
for i := 0; i < 1024; i++ {
bus.PubAsync(Uint32AsyncEvent{})
}
}()
go func() {
for i := 0; i < 1024; i++ {
bus.PubAsync(Uint32AsyncEvent{})
}
}()
go func() {
for i := 0; i < 1024; i++ {
bus.PubAsync(Uint32AsyncEvent{})
}
}()
go func() {
for i := 0; i < 1024; i++ {
bus.PubAsync(Uint32AsyncEvent{})
}
}()
wg.Wait()
if c != 4096 {
t.Fatalf("error : counter should be 4096 but is %d", c)
}
t.Logf("%d", c)
}
func TestRange(t *testing.T) {
type Event1 struct{}
type Event2 struct{}
type Event3 struct{}
type Event4 struct{}
type Event5 struct{}
bus.Sub(func(e Event1) {})
bus.Sub(func(e Event2) {})
bus.Sub(func(e Event2) {})
bus.Sub(func(e Event3) {})
bus.Sub(func(e Event3) {})
bus.Sub(func(e Event3) {})
bus.Sub(func(e Event4) {})
bus.Sub(func(e Event4) {})
bus.Sub(func(e Event4) {})
bus.Sub(func(e Event4) {})
bus.Sub(func(e Event5) {})
bus.Sub(func(e Event5) {})
bus.Sub(func(e Event5) {})
bus.Sub(func(e Event5) {})
bus.Sub(func(e Event5) {})
seen := map[string]struct{}{
"bus_test.Event2": {},
"bus_test.Event3": {},
"bus_test.Event1": {},
"bus_test.Event5": {},
"bus_test.Event4": {},
}
bus.Range(func(k, _ any) bool {
if _, has := seen[k.(string)]; has {
delete(seen, k.(string))
}
return true
})
if len(seen) > 0 {
t.Fatalf("error : not all events were seen")
}
}