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