github.com/livekit/protocol@v1.39.3/utils/events/emitter_test.go (about) 1 // Copyright 2023 LiveKit, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package events 16 17 import ( 18 "sort" 19 "testing" 20 "time" 21 22 "github.com/stretchr/testify/require" 23 ) 24 25 func TestEventEmitter(t *testing.T) { 26 t.Run("emitter", func(t *testing.T) { 27 emitter := NewEmitter[string, int]() 28 ao0 := emitter.Observe("a") 29 ao1 := emitter.Observe("a") 30 bo := emitter.Observe("b") 31 32 emitter.Emit("a", 1) 33 emitter.Emit("b", 2) 34 require.Equal(t, 1, <-ao0.Events()) 35 require.Equal(t, 1, <-ao1.Events()) 36 require.Equal(t, 2, <-bo.Events()) 37 38 ao1.Stop() 39 emitter.Emit("a", 3) 40 require.Equal(t, 3, <-ao0.Events()) 41 select { 42 case <-ao1.Events(): 43 require.Fail(t, "expected no event from stopped observer") 44 default: 45 } 46 47 ao0.Stop() 48 49 keys := emitter.ObservedKeys() 50 sort.Strings(keys) 51 require.Equal(t, []string{"b"}, keys) 52 }) 53 54 t.Run("observer", func(t *testing.T) { 55 var closeCalled bool 56 o, emit := NewObserver[int](func() { closeCalled = true }) 57 58 emit(1) 59 require.Equal(t, 1, <-o.Events()) 60 61 o.Stop() 62 require.True(t, closeCalled) 63 }) 64 65 t.Run("notify", func(t *testing.T) { 66 emitter := NewEmitter[string, int]() 67 68 as := make(chan int, 1) 69 stop := emitter.Notify("a", as) 70 71 emitter.Emit("a", 0) 72 select { 73 case v := <-as: 74 require.Equal(t, 0, v) 75 default: 76 require.FailNow(t, "expected event in channel") 77 } 78 79 stop() 80 81 emitter.Emit("a", 0) 82 select { 83 case <-as: 84 require.FailNow(t, "expected no event in channel after stop") 85 default: 86 } 87 }) 88 89 t.Run("on", func(t *testing.T) { 90 emitter := NewEmitter[string, int]() 91 92 as := make(chan int, 1) 93 stop := emitter.On("a", func(i int) { 94 as <- i 95 }) 96 97 emitter.Emit("a", 0) 98 select { 99 case v := <-as: 100 require.Equal(t, 0, v) 101 case <-time.After(100 * time.Millisecond): 102 require.FailNow(t, "expected event in channel") 103 } 104 105 stop() 106 107 emitter.Emit("a", 0) 108 select { 109 case <-as: 110 require.FailNow(t, "expected no event in channel after stop") 111 case <-time.After(100 * time.Millisecond): 112 } 113 }) 114 115 t.Run("stop unblocks blocking observers", func(t *testing.T) { 116 observer, emit := NewObserver[int](func() {}) 117 118 list := NewObserverList[int](WithBlocking()) 119 120 emitter := NewEmitter[int, int](WithBlocking()) 121 122 cases := []struct { 123 label string 124 emit func() 125 observer Observer[int] 126 }{ 127 { 128 label: "observer", 129 emit: func() { emit(0) }, 130 observer: observer, 131 }, 132 { 133 label: "list", 134 emit: func() { list.Emit(0) }, 135 observer: list.Observe(), 136 }, 137 { 138 label: "emitter", 139 emit: func() { emitter.Emit(0, 0) }, 140 observer: emitter.Observe(0), 141 }, 142 } 143 144 for _, c := range cases { 145 t.Run(c.label, func(t *testing.T) { 146 emitDone := make(chan struct{}) 147 stopDone := make(chan struct{}) 148 ready := make(chan struct{}) 149 150 go func() { 151 for i := 0; i < DefaultQueueSize; i++ { 152 c.emit() 153 } 154 close(ready) 155 c.emit() 156 close(emitDone) 157 }() 158 159 go func() { 160 <-ready 161 time.Sleep(100 * time.Millisecond) 162 c.observer.Stop() 163 close(stopDone) 164 }() 165 166 select { 167 case <-emitDone: 168 case <-time.After(time.Second): 169 require.FailNow(t, "timeout waiting for emit to unblock") 170 } 171 172 select { 173 case <-stopDone: 174 case <-time.After(time.Second): 175 require.FailNow(t, "timeout waiting for stop to unblock") 176 } 177 }) 178 } 179 }) 180 } 181 182 func BenchmarkEventEmitter(b *testing.B) { 183 e := NewEmitter[int, int]() 184 for i := 0; i < b.N; i++ { 185 o := e.Observe(i) 186 e.Emit(i, i) 187 <-o.Events() 188 o.Stop() 189 } 190 } 191 192 func BenchmarkEventObserverList(b *testing.B) { 193 l := NewObserverList[int]() 194 for i := 0; i < b.N; i++ { 195 o := l.Observe() 196 l.Emit(i) 197 <-o.Events() 198 o.Stop() 199 } 200 }