| 300 | } |
| 301 | |
| 302 | func TestMockKV_Watch(t *testing.T) { |
| 303 | // setupWatchTest spawns a goroutine to watch for events matching a particular key |
| 304 | // emitted by a mockKV. Any observed events are sent to callers via the returned channel. |
| 305 | // The goroutine can be stopped using the return cancel function and waited for using the |
| 306 | // returned wait group. |
| 307 | setupWatchTest := func(key string, prefix bool) (*mockKV, context.CancelFunc, chan *clientv3.Event, *sync.WaitGroup) { |
| 308 | kv := newMockKV() |
| 309 | // Use a WaitGroup to make sure the goroutine has started using the watch before |
| 310 | // we do anything to the mockKV that would emit an event the watcher is expecting |
| 311 | started := sync.WaitGroup{} |
| 312 | // Use another WaitGroup so that callers can tell when the channel returned by watch |
| 313 | // method is closed and the watch is complete. |
| 314 | complete := sync.WaitGroup{} |
| 315 | |
| 316 | ch := make(chan *clientv3.Event) |
| 317 | ctx, cancel := context.WithCancel(context.Background()) |
| 318 | |
| 319 | started.Add(1) |
| 320 | complete.Add(1) |
| 321 | go func() { |
| 322 | defer complete.Done() |
| 323 | |
| 324 | var ops []clientv3.OpOption |
| 325 | if prefix { |
| 326 | ops = []clientv3.OpOption{clientv3.WithPrefix()} |
| 327 | } |
| 328 | |
| 329 | watch := kv.Watch(ctx, key, ops...) |
| 330 | started.Done() |
| 331 | |
| 332 | for e := range watch { |
| 333 | if len(e.Events) > 0 { |
| 334 | ch <- e.Events[0] |
| 335 | } |
| 336 | } |
| 337 | }() |
| 338 | |
| 339 | started.Wait() |
| 340 | return kv, cancel, ch, &complete |
| 341 | } |
| 342 | |
| 343 | t.Run("watch stopped by context", func(*testing.T) { |
| 344 | // Ensure we can use the cancel method of the context given to the watch |
| 345 | // to stop the watch |
| 346 | _, cancel, _, complete := setupWatchTest("/bar", false) |
| 347 | cancel() |
| 348 | complete.Wait() |
| 349 | }) |
| 350 | |
| 351 | t.Run("watch stopped by close", func(*testing.T) { |
| 352 | // Ensure we can use the Close method of the mockKV given to the watch |
| 353 | // to stop the watch |
| 354 | kv, _, _, complete := setupWatchTest("/bar", false) |
| 355 | _ = kv.Close() |
| 356 | complete.Wait() |
| 357 | }) |
| 358 | |
| 359 | t.Run("watch exact key", func(t *testing.T) { |