package testutils import ( "sync" "testing" ) var ( parallelLock sync.Mutex ) // SetupParallelTest configure un test pour exécution parallèle (T0048) func SetupParallelTest(t *testing.T) { t.Parallel() // Acquérir un lock si ressources partagées // parallelLock.Lock() // t.Cleanup(func() { parallelLock.Unlock() }) } // RunParallelTests exécute plusieurs tests en parallèle (T0048) // Note: The sub-tests created by t.Run() already call t.Parallel(), so testFuncs // should NOT call SetupParallelTest() or t.Parallel() themselves to avoid "t.Parallel called multiple times" panic // The parent test must wait for all sub-tests to complete func RunParallelTests(t *testing.T, testFuncs map[string]func(*testing.T)) { // Use t.Run() which automatically waits for all sub-tests to complete // Each sub-test calls t.Parallel() to run in parallel for name, fn := range testFuncs { t.Run(name, func(t *testing.T) { t.Parallel() fn(t) }) } // t.Run() blocks until all sub-tests complete, so we don't need WaitGroup } // WithLock exécute une fonction avec un lock partagé (T0048) func WithLock(fn func()) { parallelLock.Lock() defer parallelLock.Unlock() fn() } // TestLockManager gère les locks pour les tests parallèles (T0048) type TestLockManager struct { locks map[string]*sync.Mutex mu sync.RWMutex } // NewTestLockManager crée un nouveau gestionnaire de locks (T0048) func NewTestLockManager() *TestLockManager { return &TestLockManager{ locks: make(map[string]*sync.Mutex), } } // Lock acquiert un lock nommé (T0048) func (tm *TestLockManager) Lock(name string) func() { tm.mu.Lock() lock, exists := tm.locks[name] if !exists { lock = &sync.Mutex{} tm.locks[name] = lock } tm.mu.Unlock() lock.Lock() return func() { lock.Unlock() } } // Example usage: /* func TestParallel(t *testing.T) { testFuncs := map[string]func(*testing.T){ "test1": func(t *testing.T) { SetupParallelTest(t) // Test code }, "test2": func(t *testing.T) { SetupParallelTest(t) // Test code }, } RunParallelTests(t, testFuncs) } func TestWithSharedResource(t *testing.T) { t.Parallel() WithLock(func() { // Code qui nécessite un lock }) } func TestWithNamedLock(t *testing.T) { t.Parallel() lockManager := NewTestLockManager() unlock := lockManager.Lock("resource1") defer unlock() // Code qui nécessite un lock nommé } */