vitess.io/vitess@v0.16.2/go/event/event_test.go (about) 1 /* 2 Copyright 2019 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreedto in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package event 18 19 import ( 20 "reflect" 21 "testing" 22 "time" 23 ) 24 25 type testInterface1 interface { 26 TestFunc1() 27 } 28 29 type testInterface2 interface { 30 TestFunc2() 31 } 32 33 type testEvent1 struct { 34 } 35 36 type testEvent2 struct { 37 triggered bool 38 } 39 40 func (testEvent1) TestFunc1() {} 41 42 func (*testEvent2) TestFunc2() {} 43 44 func clearListeners() { 45 listenersMutex.Lock() 46 defer listenersMutex.Unlock() 47 48 listeners = make(map[reflect.Type][]any) 49 interfaces = make([]reflect.Type, 0) 50 } 51 52 func TestStaticListener(t *testing.T) { 53 clearListeners() 54 55 triggered := false 56 AddListener(func(testEvent1) { triggered = true }) 57 AddListener(func(testEvent2) { t.Errorf("wrong listener type triggered") }) 58 Dispatch(testEvent1{}) 59 60 if !triggered { 61 t.Errorf("static listener failed to trigger") 62 } 63 } 64 65 func TestPointerListener(t *testing.T) { 66 clearListeners() 67 68 testEvent := new(testEvent2) 69 AddListener(func(ev *testEvent2) { ev.triggered = true }) 70 AddListener(func(testEvent2) { t.Errorf("non-pointer listener triggered on pointer type") }) 71 Dispatch(testEvent) 72 73 if !testEvent.triggered { 74 t.Errorf("pointer listener failed to trigger") 75 } 76 } 77 78 func TestInterfaceListener(t *testing.T) { 79 clearListeners() 80 81 triggered := false 82 AddListener(func(testInterface1) { triggered = true }) 83 AddListener(func(testInterface2) { t.Errorf("interface listener triggered on non-matching type") }) 84 Dispatch(testEvent1{}) 85 86 if !triggered { 87 t.Errorf("interface listener failed to trigger") 88 } 89 } 90 91 func TestEmptyInterfaceListener(t *testing.T) { 92 clearListeners() 93 94 triggered := false 95 AddListener(func(any) { triggered = true }) 96 Dispatch("this should match any") 97 98 if !triggered { 99 t.Errorf("any listener failed to trigger") 100 } 101 } 102 103 func TestMultipleListeners(t *testing.T) { 104 clearListeners() 105 106 triggered1, triggered2 := false, false 107 AddListener(func(testEvent1) { triggered1 = true }) 108 AddListener(func(testEvent1) { triggered2 = true }) 109 Dispatch(testEvent1{}) 110 111 if !triggered1 || !triggered2 { 112 t.Errorf("not all matching listeners triggered") 113 } 114 } 115 116 func TestBadListenerWrongInputs(t *testing.T) { 117 clearListeners() 118 119 defer func() { 120 err := recover() 121 122 if err == nil { 123 t.Errorf("bad listener func (wrong # of inputs) failed to trigger panic") 124 return 125 } 126 127 blErr, ok := err.(BadListenerError) 128 if !ok { 129 panic(err) // this is not the error we were looking for; re-panic 130 } 131 132 want := "bad listener func: listener must take exactly one input argument" 133 if got := blErr.Error(); got != want { 134 t.Errorf(`BadListenerError.Error() = "%s", want "%s"`, got, want) 135 } 136 }() 137 138 AddListener(func() {}) 139 Dispatch(testEvent1{}) 140 } 141 142 func TestBadListenerWrongType(t *testing.T) { 143 clearListeners() 144 145 defer func() { 146 err := recover() 147 148 if err == nil { 149 t.Errorf("bad listener type (not a func) failed to trigger panic") 150 } 151 152 blErr, ok := err.(BadListenerError) 153 if !ok { 154 panic(err) // this is not the error we were looking for; re-panic 155 } 156 157 want := "bad listener func: listener must be a function" 158 if got := blErr.Error(); got != want { 159 t.Errorf(`BadListenerError.Error() = "%s", want "%s"`, got, want) 160 } 161 }() 162 163 AddListener("this is not a function") 164 Dispatch(testEvent1{}) 165 } 166 167 func TestAsynchronousDispatch(t *testing.T) { 168 clearListeners() 169 170 triggered := make(chan bool) 171 AddListener(func(testEvent1) { triggered <- true }) 172 go Dispatch(testEvent1{}) 173 174 select { 175 case <-triggered: 176 case <-time.After(time.Second): 177 t.Errorf("asynchronous dispatch failed to trigger listener") 178 } 179 } 180 181 func TestDispatchPointerToValueInterfaceListener(t *testing.T) { 182 clearListeners() 183 184 triggered := false 185 AddListener(func(ev testInterface1) { 186 triggered = true 187 }) 188 Dispatch(&testEvent1{}) 189 190 if !triggered { 191 t.Errorf("Dispatch by pointer failed to trigger interface listener") 192 } 193 } 194 195 func TestDispatchValueToValueInterfaceListener(t *testing.T) { 196 clearListeners() 197 198 triggered := false 199 AddListener(func(ev testInterface1) { 200 triggered = true 201 }) 202 Dispatch(testEvent1{}) 203 204 if !triggered { 205 t.Errorf("Dispatch by value failed to trigger interface listener") 206 } 207 } 208 209 func TestDispatchPointerToPointerInterfaceListener(t *testing.T) { 210 clearListeners() 211 212 triggered := false 213 AddListener(func(testInterface2) { triggered = true }) 214 Dispatch(&testEvent2{}) 215 216 if !triggered { 217 t.Errorf("interface listener failed to trigger for pointer") 218 } 219 } 220 221 func TestDispatchValueToPointerInterfaceListener(t *testing.T) { 222 clearListeners() 223 224 AddListener(func(testInterface2) { 225 t.Errorf("interface listener triggered for value dispatch") 226 }) 227 Dispatch(testEvent2{}) 228 } 229 230 type testUpdateEvent struct { 231 update any 232 } 233 234 func (ev *testUpdateEvent) Update(update any) { 235 ev.update = update 236 } 237 238 func TestDispatchUpdate(t *testing.T) { 239 clearListeners() 240 241 triggered := false 242 AddListener(func(*testUpdateEvent) { 243 triggered = true 244 }) 245 246 ev := &testUpdateEvent{} 247 DispatchUpdate(ev, "hello") 248 249 if !triggered { 250 t.Errorf("listener failed to trigger on DispatchUpdate()") 251 } 252 want := "hello" 253 if got := ev.update.(string); got != want { 254 t.Errorf("ev.update = %#v, want %#v", got, want) 255 } 256 }