| 324 | } |
| 325 | |
| 326 | func TestWantConnQueue_ThreadSafety(t *testing.T) { |
| 327 | q := newWantConnQueue() |
| 328 | const numOperations = 1000 |
| 329 | |
| 330 | var wg sync.WaitGroup |
| 331 | errors := make(chan error, numOperations*2) |
| 332 | |
| 333 | // Concurrent enqueue operations |
| 334 | wg.Add(1) |
| 335 | go func() { |
| 336 | defer wg.Done() |
| 337 | for i := 0; i < numOperations; i++ { |
| 338 | w := &wantConn{ |
| 339 | ctx: context.Background(), |
| 340 | result: make(chan wantConnResult, 1), |
| 341 | } |
| 342 | q.enqueue(w) |
| 343 | } |
| 344 | }() |
| 345 | |
| 346 | // Concurrent dequeue operations |
| 347 | wg.Add(1) |
| 348 | go func() { |
| 349 | defer wg.Done() |
| 350 | dequeued := 0 |
| 351 | for dequeued < numOperations { |
| 352 | if _, ok := q.dequeue(); ok { |
| 353 | dequeued++ |
| 354 | } else { |
| 355 | // Small delay when queue is empty |
| 356 | time.Sleep(time.Microsecond) |
| 357 | } |
| 358 | } |
| 359 | }() |
| 360 | |
| 361 | // Wait for completion |
| 362 | wg.Wait() |
| 363 | close(errors) |
| 364 | |
| 365 | // Check for any errors |
| 366 | for err := range errors { |
| 367 | t.Error(err) |
| 368 | } |
| 369 | |
| 370 | // Final queue should be empty |
| 371 | if item, ok := q.dequeue(); ok { |
| 372 | t.Errorf("queue should be empty but got item: %v", item) |
| 373 | } |
| 374 | } |
| 375 | |
| 376 | // Benchmark tests |
| 377 | func BenchmarkWantConnQueue_Enqueue(b *testing.B) { |