package sensor import ( "sync" "testing" "time" ) func TestHubDeliveryCoalescingAndCancel(t *testing.T) { var hub Hub slow, cancelSlow := hub.Subscribe() fast, cancelFast := hub.Subscribe() defer cancelFast() done := make(chan struct{}) go func() { for range 1000 { hub.Notify() } close(done) }() select { case <-done: case <-time.After(time.Second): t.Fatal("slow subscribers blocked notification") } for _, events := range []<-chan struct{}{slow, fast} { select { case <-events: default: t.Fatal("subscriber missed notification") } select { case <-events: t.Fatal("burst was not coalesced") default: } } cancelSlow() cancelSlow() hub.Notify() select { case _, ok := <-slow: if ok { t.Fatal("cancelled subscriber received a new event") } default: } select { case <-fast: default: t.Fatal("remaining subscriber missed notification") } } func TestHubConcurrentUse(t *testing.T) { var hub Hub hub.Notify() // The zero value also supports notification without subscribers. var workers sync.WaitGroup for range 10 { workers.Go(func() { for range 100 { events, cancel := hub.Subscribe() hub.Notify() select { case <-events: default: t.Error("subscriber missed notification") } cancel() cancel() } }) } workers.Wait() }