package testutils import ( "sync" "sync/atomic" "testing" "time" ) func TestSetupParallelTest(t *testing.T) { // Ce test vérifie que SetupParallelTest marque le test comme parallèle // Note: On ne peut pas vraiment tester t.Parallel() directement, mais on peut // vérifier que la fonction ne panique pas et s'exécute correctement SetupParallelTest(t) } func TestRunParallelTests(t *testing.T) { var counter int64 testFuncs := map[string]func(*testing.T){ "test1": func(t *testing.T) { // Don't call SetupParallelTest here - RunParallelTests already calls t.Parallel() atomic.AddInt64(&counter, 1) t.Logf("test1 executed, counter=%d", atomic.LoadInt64(&counter)) }, "test2": func(t *testing.T) { // Don't call SetupParallelTest here - RunParallelTests already calls t.Parallel() atomic.AddInt64(&counter, 1) t.Logf("test2 executed, counter=%d", atomic.LoadInt64(&counter)) }, "test3": func(t *testing.T) { // Don't call SetupParallelTest here - RunParallelTests already calls t.Parallel() atomic.AddInt64(&counter, 1) t.Logf("test3 executed, counter=%d", atomic.LoadInt64(&counter)) }, } // RunParallelTests uses t.Run() which should wait for all sub-tests to complete // With t.Parallel(), tests are paused and resumed later, but t.Run() still blocks // until all sub-tests complete. The issue is that the check happens before parallel // tests resume. We need to check the count in a cleanup function that runs after // all tests complete. t.Cleanup(func() { // This runs after all sub-tests complete finalCount := atomic.LoadInt64(&counter) if finalCount != 3 { t.Errorf("Expected counter to be 3, got %d", finalCount) } }) RunParallelTests(t, testFuncs) } func TestRunParallelTests_MultipleExecution(t *testing.T) { var executions int64 testFuncs := map[string]func(*testing.T){ "parallel_test_1": func(t *testing.T) { // Don't call t.Parallel() here - RunParallelTests already calls it time.Sleep(10 * time.Millisecond) atomic.AddInt64(&executions, 1) }, "parallel_test_2": func(t *testing.T) { // Don't call t.Parallel() here - RunParallelTests already calls it time.Sleep(10 * time.Millisecond) atomic.AddInt64(&executions, 1) }, "parallel_test_3": func(t *testing.T) { // Don't call t.Parallel() here - RunParallelTests already calls it time.Sleep(10 * time.Millisecond) atomic.AddInt64(&executions, 1) }, } // RunParallelTests uses t.Run() which should wait for all sub-tests to complete // With t.Parallel(), tests are paused and resumed later, but t.Run() still blocks // until all sub-tests complete. The issue is that the check happens before parallel // tests resume. We need to check the count in a cleanup function that runs after // all tests complete. t.Cleanup(func() { // This runs after all sub-tests complete finalCount := atomic.LoadInt64(&executions) if finalCount != 3 { t.Errorf("Expected 3 executions, got %d", finalCount) } }) RunParallelTests(t, testFuncs) } func TestWithLock(t *testing.T) { t.Parallel() var counter int var wg sync.WaitGroup // Exécuter plusieurs goroutines qui incrémentent le compteur for i := 0; i < 10; i++ { wg.Add(1) go func() { defer wg.Done() WithLock(func() { counter++ }) }() } wg.Wait() if counter != 10 { t.Errorf("Expected counter to be 10, got %d", counter) } } func TestWithLock_Isolation(t *testing.T) { t.Parallel() var value int // Exécuter plusieurs opérations avec lock for i := 0; i < 5; i++ { WithLock(func() { oldValue := value time.Sleep(1 * time.Millisecond) value = oldValue + 1 }) } if value != 5 { t.Errorf("Expected value to be 5, got %d", value) } } func TestTestLockManager(t *testing.T) { t.Parallel() lockManager := NewTestLockManager() var counter1, counter2 int var wg sync.WaitGroup // Utiliser deux locks différents en parallèle for i := 0; i < 5; i++ { wg.Add(2) go func() { defer wg.Done() unlock := lockManager.Lock("resource1") defer unlock() counter1++ }() go func() { defer wg.Done() unlock := lockManager.Lock("resource2") defer unlock() counter2++ }() } wg.Wait() if counter1 != 5 { t.Errorf("Expected counter1 to be 5, got %d", counter1) } if counter2 != 5 { t.Errorf("Expected counter2 to be 5, got %d", counter2) } } func TestTestLockManager_SameLock(t *testing.T) { t.Parallel() lockManager := NewTestLockManager() var counter int var wg sync.WaitGroup // Utiliser le même lock pour plusieurs goroutines for i := 0; i < 10; i++ { wg.Add(1) go func() { defer wg.Done() unlock := lockManager.Lock("shared_resource") defer unlock() counter++ }() } wg.Wait() if counter != 10 { t.Errorf("Expected counter to be 10, got %d", counter) } } func TestTestLockManager_ConcurrentAccess(t *testing.T) { t.Parallel() lockManager := NewTestLockManager() var sharedValue int // Test que les locks fonctionnent correctement en accès concurrent var wg sync.WaitGroup for i := 0; i < 20; i++ { wg.Add(1) go func() { defer wg.Done() unlock := lockManager.Lock("concurrent_resource") defer unlock() oldValue := sharedValue time.Sleep(1 * time.Millisecond) sharedValue = oldValue + 1 }() } wg.Wait() if sharedValue != 20 { t.Errorf("Expected sharedValue to be 20, got %d", sharedValue) } }