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