github.com/kubeshop/testkube@v1.17.23/pkg/event/emitter_test.go (about) 1 package event 2 3 import ( 4 "context" 5 "os" 6 "testing" 7 "time" 8 9 "github.com/stretchr/testify/assert" 10 11 "github.com/kubeshop/testkube/pkg/api/v1/testkube" 12 "github.com/kubeshop/testkube/pkg/event/bus" 13 "github.com/kubeshop/testkube/pkg/event/kind/common" 14 "github.com/kubeshop/testkube/pkg/event/kind/dummy" 15 ) 16 17 func init() { 18 os.Setenv("DEBUG", "true") 19 } 20 21 func TestEmitter_Register(t *testing.T) { 22 t.Parallel() 23 24 t.Run("Register adds new listener", func(t *testing.T) { 25 t.Parallel() 26 // given 27 eventBus := bus.NewEventBusMock() 28 emitter := NewEmitter(eventBus, "", nil) 29 // when 30 emitter.Register(&dummy.DummyListener{Id: "l1"}) 31 32 // then 33 assert.Equal(t, 1, len(emitter.Listeners)) 34 35 t.Log("T1 completed") 36 }) 37 } 38 39 func TestEmitter_Listen(t *testing.T) { 40 t.Parallel() 41 42 t.Run("listener handles only given events based on selectors", func(t *testing.T) { 43 t.Parallel() 44 // given 45 eventBus := bus.NewEventBusMock() 46 emitter := NewEmitter(eventBus, "", nil) 47 // given listener with matching selector 48 listener1 := &dummy.DummyListener{Id: "l1", SelectorString: "type=listener1"} 49 // and listener with second matic selector 50 listener2 := &dummy.DummyListener{Id: "l2", SelectorString: "type=listener2"} 51 52 // and emitter with registered listeners 53 emitter.Register(listener1) 54 emitter.Register(listener2) 55 56 // listening emitter 57 ctx, cancel := context.WithCancel(context.Background()) 58 defer cancel() 59 60 emitter.Listen(ctx) 61 // wait for listeners to start 62 time.Sleep(time.Millisecond * 50) 63 64 // events 65 event1 := newExampleTestEvent1() 66 event1.TestExecution.Labels = map[string]string{"type": "listener1"} 67 event2 := newExampleTestEvent2() 68 event2.TestExecution.Labels = map[string]string{"type": "listener2"} 69 70 // when 71 emitter.Notify(event1) 72 emitter.Notify(event2) 73 74 // then 75 retryCount := 100 76 notificationsCountListener1 := 0 77 notificationsCountListener2 := 0 78 for i := 0; i < retryCount; i++ { 79 notificationsCountListener1 = listener1.GetNotificationCount() 80 notificationsCountListener2 = listener2.GetNotificationCount() 81 if notificationsCountListener1 == 1 && notificationsCountListener2 == 1 { 82 break 83 } 84 time.Sleep(50 * time.Millisecond) 85 } 86 87 assert.Equal(t, 1, notificationsCountListener1) 88 assert.Equal(t, 1, notificationsCountListener2) 89 }) 90 91 } 92 93 func TestEmitter_Notify(t *testing.T) { 94 t.Parallel() 95 96 t.Run("notifies listeners in queue groups", func(t *testing.T) { 97 t.Parallel() 98 // given 99 eventBus := bus.NewEventBusMock() 100 emitter := NewEmitter(eventBus, "", nil) 101 // and 2 listeners subscribed to the same queue 102 // * first on pod1 103 listener1 := &dummy.DummyListener{Id: "l3"} 104 // * second on pod2 105 listener2 := &dummy.DummyListener{Id: "l3"} 106 107 emitter.Register(listener1) 108 emitter.Register(listener2) 109 110 // and listening emitter 111 ctx, cancel := context.WithCancel(context.Background()) 112 defer cancel() 113 emitter.Listen(ctx) 114 115 time.Sleep(time.Millisecond * 50) 116 117 // when event sent to queue group 118 emitter.Notify(newExampleTestEvent1()) 119 120 time.Sleep(time.Millisecond * 50) 121 122 // then only one listener should be notified 123 assert.Equal(t, 1, listener2.GetNotificationCount()+listener1.GetNotificationCount()) 124 }) 125 } 126 127 func TestEmitter_Reconcile(t *testing.T) { 128 t.Parallel() 129 130 t.Run("emitter refersh listeners in reconcile loop", func(t *testing.T) { 131 t.Parallel() 132 // given first reconciler loop was done 133 eventBus := bus.NewEventBusMock() 134 emitter := NewEmitter(eventBus, "", nil) 135 emitter.Loader.Register(&dummy.DummyLoader{IdPrefix: "dummy1"}) 136 emitter.Loader.Register(&dummy.DummyLoader{IdPrefix: "dummy2"}) 137 138 ctx, cancel := context.WithCancel(context.Background()) 139 140 go emitter.Reconcile(ctx) 141 142 time.Sleep(100 * time.Millisecond) 143 assert.Len(t, emitter.GetListeners(), 4) 144 145 cancel() 146 147 // and we'll add additional new loader 148 emitter.Loader.Register(&dummy.DummyLoader{IdPrefix: "dummy1"}) // existing one 149 emitter.Loader.Register(&dummy.DummyLoader{IdPrefix: "dummy3"}) 150 151 ctx, cancel = context.WithCancel(context.Background()) 152 153 // when 154 go emitter.Reconcile(ctx) 155 156 // then each reconciler (3 reconcilers) should load 2 listeners 157 time.Sleep(100 * time.Millisecond) 158 assert.Len(t, emitter.GetListeners(), 6) 159 160 cancel() 161 }) 162 163 } 164 165 func newExampleTestEvent1() testkube.Event { 166 return testkube.Event{ 167 Id: "eventID1", 168 Type_: testkube.EventStartTest, 169 TestExecution: testkube.NewExecutionWithID("executionID1", "test/test", "test"), 170 } 171 } 172 173 func newExampleTestEvent2() testkube.Event { 174 return testkube.Event{ 175 Id: "eventID2", 176 Type_: testkube.EventStartTest, 177 TestExecution: testkube.NewExecutionWithID("executionID2", "test/test", "test"), 178 } 179 } 180 181 func TestEmitter_UpdateListeners(t *testing.T) { 182 t.Parallel() 183 184 t.Run("add, update and delete new listeners", func(t *testing.T) { 185 t.Parallel() 186 // given 187 eventBus := bus.NewEventBusMock() 188 emitter := NewEmitter(eventBus, "", nil) 189 // given listener with matching selector 190 listener1 := &dummy.DummyListener{Id: "l1", SelectorString: "type=listener1"} 191 // and listener with second matching selector 192 listener2 := &dummy.DummyListener{Id: "l2", SelectorString: "type=listener2"} 193 // and listener with third matching selector 194 listener3 := &dummy.DummyListener{Id: "l1", SelectorString: "type=listener3"} 195 // and listener with different kind 196 listener4 := &FakeListener{name: "l4"} 197 // and listener with different kind 198 listener5 := &FakeListener{name: "l5"} 199 200 // when listeners are added 201 emitter.UpdateListeners(common.Listeners{listener1, listener2}) 202 203 // then should have 2 listeners 204 assert.Len(t, emitter.Listeners, 2) 205 206 // when listeners are deleted 207 emitter.UpdateListeners(common.Listeners{listener1}) 208 assert.Equal(t, "type=listener1", emitter.Listeners[0].Selector()) 209 210 // then should have 1 listener 211 assert.Len(t, emitter.Listeners, 1) 212 213 // when listeners are updated 214 emitter.UpdateListeners(common.Listeners{listener3}) 215 216 // then should have 1 listener 217 assert.Len(t, emitter.Listeners, 1) 218 assert.Equal(t, "type=listener3", emitter.Listeners[0].Selector()) 219 220 // when listeners are added 221 emitter.UpdateListeners(common.Listeners{listener3, listener2}) 222 223 // then should have 2 listeners 224 assert.Len(t, emitter.Listeners, 2) 225 226 // when listeners are added 227 emitter.UpdateListeners(common.Listeners{listener4}) 228 229 // then should have 1 listeners 230 assert.Len(t, emitter.Listeners, 1) 231 232 // when listeners are added 233 emitter.UpdateListeners(common.Listeners{listener4, listener5}) 234 235 // then should have 4 listeners 236 assert.Len(t, emitter.Listeners, 2) 237 }) 238 239 } 240 241 var _ common.Listener = (*FakeListener)(nil) 242 243 type FakeListener struct { 244 name string 245 } 246 247 func (l *FakeListener) Notify(event testkube.Event) testkube.EventResult { 248 return testkube.EventResult{Id: event.Id} 249 } 250 251 func (l *FakeListener) Name() string { 252 return l.name 253 } 254 255 func (l *FakeListener) Events() []testkube.EventType { 256 return nil 257 } 258 259 func (l FakeListener) Selector() string { 260 return "" 261 } 262 263 func (l *FakeListener) Kind() string { 264 return "fake" 265 } 266 267 func (l *FakeListener) Metadata() map[string]string { 268 return map[string]string{} 269 }