(t *testing.T)
| 391 | } |
| 392 | |
| 393 | func TestConnStateMachine_FIFOOrdering(t *testing.T) { |
| 394 | sm := NewConnStateMachine() |
| 395 | sm.Transition(StateInitializing) // Start in INITIALIZING so all waiters must queue |
| 396 | |
| 397 | const numGoroutines = 10 |
| 398 | var executionOrder []int |
| 399 | var orderMu sync.Mutex |
| 400 | var wg sync.WaitGroup |
| 401 | |
| 402 | // Launch goroutines one at a time, ensuring each is queued before launching the next |
| 403 | for i := 0; i < numGoroutines; i++ { |
| 404 | wg.Add(1) |
| 405 | expectedWaiters := int32(i + 1) |
| 406 | |
| 407 | go func(id int) { |
| 408 | defer wg.Done() |
| 409 | |
| 410 | ctx := context.Background() |
| 411 | |
| 412 | // This should queue in FIFO order |
| 413 | _, err := sm.AwaitAndTransition(ctx, []ConnState{StateIdle}, StateInitializing) |
| 414 | if err != nil { |
| 415 | t.Errorf("Goroutine %d: failed to transition: %v", id, err) |
| 416 | return |
| 417 | } |
| 418 | |
| 419 | // Record execution order |
| 420 | orderMu.Lock() |
| 421 | executionOrder = append(executionOrder, id) |
| 422 | orderMu.Unlock() |
| 423 | |
| 424 | t.Logf("Goroutine %d: executed (position %d)", id, len(executionOrder)) |
| 425 | |
| 426 | // Transition back to IDLE to allow next waiter |
| 427 | sm.Transition(StateIdle) |
| 428 | }(i) |
| 429 | |
| 430 | // Wait until this goroutine has been queued before launching the next |
| 431 | // Poll the waiter count to ensure the goroutine is actually queued |
| 432 | timeout := time.After(100 * time.Millisecond) |
| 433 | for { |
| 434 | if sm.waiterCount.Load() >= expectedWaiters { |
| 435 | break |
| 436 | } |
| 437 | select { |
| 438 | case <-timeout: |
| 439 | t.Fatalf("Timeout waiting for goroutine %d to queue", i) |
| 440 | case <-time.After(1 * time.Millisecond): |
| 441 | // Continue polling |
| 442 | } |
| 443 | } |
| 444 | } |
| 445 | |
| 446 | // Give all goroutines time to fully settle in the queue |
| 447 | time.Sleep(10 * time.Millisecond) |
| 448 | |
| 449 | // Transition to IDLE to start processing the queue |
| 450 | sm.Transition(StateIdle) |
nothing calls this directly
no test coverage detected