github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/utilities/event/event_test.go (about) 1 package event 2 3 import ( 4 "math/rand" 5 "sync" 6 "testing" 7 "time" 8 ) 9 10 type testEvent int 11 12 func TestSubCloseUnsub(t *testing.T) { 13 14 var mux TypeMux 15 mux.Stop() 16 sub := mux.Subscribe(int(0)) 17 sub.Unsubscribe() 18 } 19 20 func TestSub(t *testing.T) { 21 mux := new(TypeMux) 22 defer mux.Stop() 23 24 sub := mux.Subscribe(testEvent(0)) 25 go func() { 26 if err := mux.Post(testEvent(5)); err != nil { 27 t.Errorf("Post returned unexpected error: %v", err) 28 } 29 }() 30 ev := <-sub.Chan() 31 32 if ev.Data.(testEvent) != testEvent(5) { 33 t.Errorf("Got %v (%T), expected event %v (%T)", 34 ev, ev, testEvent(5), testEvent(5)) 35 } 36 } 37 38 func TestMuxErrorAfterStop(t *testing.T) { 39 mux := new(TypeMux) 40 mux.Stop() 41 42 sub := mux.Subscribe(testEvent(0)) 43 if _, isopen := <-sub.Chan(); isopen { 44 t.Errorf("subscription channel was not closed") 45 } 46 if err := mux.Post(testEvent(0)); err != ErrMuxClosed { 47 t.Errorf("Post error mismatch, got: %s, expected: %s", err, ErrMuxClosed) 48 } 49 } 50 51 func TestUnsubscribeUnblockPost(t *testing.T) { 52 mux := new(TypeMux) 53 defer mux.Stop() 54 55 sub := mux.Subscribe(testEvent(0)) 56 unblocked := make(chan bool) 57 go func() { 58 mux.Post(testEvent(5)) 59 unblocked <- true 60 }() 61 62 select { 63 case <-unblocked: 64 t.Errorf("Post returned before Unsubscribe") 65 default: 66 sub.Unsubscribe() 67 <-unblocked 68 } 69 } 70 71 func TestSubscribeDuplicateType(t *testing.T) { 72 mux := new(TypeMux) 73 expected := "event: duplicate type event.testEvent in Subscribe" 74 75 defer func() { 76 err := recover() 77 if err == nil { 78 t.Errorf("Subscribe didn't panic for duplicate type") 79 } else if err != expected { 80 t.Errorf("panic mismatch: got %#v, expected %#v", err, expected) 81 } 82 }() 83 mux.Subscribe(testEvent(1), testEvent(2)) 84 } 85 86 func TestMuxConcurrent(t *testing.T) { 87 rand.Seed(time.Now().Unix()) 88 mux := new(TypeMux) 89 defer mux.Stop() 90 91 recv := make(chan int) 92 poster := func() { 93 for { 94 err := mux.Post(testEvent(0)) 95 if err != nil { 96 return 97 } 98 } 99 } 100 sub := func(i int) { 101 time.Sleep(time.Duration(rand.Intn(99)) * time.Millisecond) 102 sub := mux.Subscribe(testEvent(0)) 103 <-sub.Chan() 104 sub.Unsubscribe() 105 recv <- i 106 } 107 108 go poster() 109 go poster() 110 go poster() 111 nsubs := 1000 112 for i := 0; i < nsubs; i++ { 113 go sub(i) 114 } 115 116 counts := make(map[int]int, nsubs) 117 for i := 0; i < nsubs; i++ { 118 counts[<-recv]++ 119 } 120 for i, count := range counts { 121 if count != 1 { 122 t.Errorf("receiver %d called %d times, expected only 1 call", i, count) 123 } 124 } 125 } 126 127 func emptySubscriber(mux *TypeMux) { 128 s := mux.Subscribe(testEvent(0)) 129 go func() { 130 for range s.Chan() { 131 } 132 }() 133 } 134 135 func BenchmarkPost1000(b *testing.B) { 136 var ( 137 mux = new(TypeMux) 138 subscribed, done sync.WaitGroup 139 nsubs = 1000 140 ) 141 subscribed.Add(nsubs) 142 done.Add(nsubs) 143 for i := 0; i < nsubs; i++ { 144 go func() { 145 s := mux.Subscribe(testEvent(0)) 146 subscribed.Done() 147 for range s.Chan() { 148 } 149 done.Done() 150 }() 151 } 152 subscribed.Wait() 153 154 b.ResetTimer() 155 for i := 0; i < b.N; i++ { 156 mux.Post(testEvent(0)) 157 } 158 159 b.StopTimer() 160 mux.Stop() 161 done.Wait() 162 } 163 164 func BenchmarkPostConcurrent(b *testing.B) { 165 var mux = new(TypeMux) 166 defer mux.Stop() 167 emptySubscriber(mux) 168 emptySubscriber(mux) 169 emptySubscriber(mux) 170 171 var wg sync.WaitGroup 172 poster := func() { 173 for i := 0; i < b.N; i++ { 174 mux.Post(testEvent(0)) 175 } 176 wg.Done() 177 } 178 wg.Add(5) 179 for i := 0; i < 5; i++ { 180 go poster() 181 } 182 wg.Wait() 183 } 184 185 func BenchmarkChanSend(b *testing.B) { 186 c := make(chan interface{}) 187 closed := make(chan struct{}) 188 go func() { 189 for range c { 190 } 191 }() 192 193 for i := 0; i < b.N; i++ { 194 select { 195 case c <- i: 196 case <-closed: 197 } 198 } 199 }