import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; import ru.lionarius.sync.MyCountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import static org.junit.jupiter.api.Assertions.*; class MyCountDownLatchTest { @Test void testInitialization() { assertThrows(IllegalArgumentException.class, () -> new MyCountDownLatch(-1)); assertDoesNotThrow(() -> new MyCountDownLatch(0)); var latch = new MyCountDownLatch(5); assertEquals(5, latch.getCount()); } @Test void testCountDown() { var latch = new MyCountDownLatch(3); assertEquals(3, latch.getCount()); latch.countDown(); assertEquals(2, latch.getCount()); latch.countDown(); assertEquals(1, latch.getCount()); latch.countDown(); assertEquals(0, latch.getCount()); latch.countDown(); assertEquals(0, latch.getCount()); } @RepeatedTest(20) void testAwait() throws InterruptedException { var latch = new MyCountDownLatch(2); var threadFinished = new AtomicBoolean(false); var thread = new Thread(() -> { try { latch.await(); threadFinished.set(true); } catch (InterruptedException ignored) { } }); thread.start(); Thread.sleep(100); assertFalse(threadFinished.get()); latch.countDown(); Thread.sleep(100); assertFalse(threadFinished.get()); latch.countDown(); thread.join(1000); assertTrue(threadFinished.get()); } @Test @Timeout(value = 1000, unit = TimeUnit.MILLISECONDS) void testMultipleThreads() throws InterruptedException { final int THREAD_COUNT = 5; var startLatch = new MyCountDownLatch(1); var endLatch = new MyCountDownLatch(THREAD_COUNT); AtomicBoolean[] threadsStarted = new AtomicBoolean[THREAD_COUNT]; AtomicBoolean[] threadsFinished = new AtomicBoolean[THREAD_COUNT]; for (int i = 0; i < THREAD_COUNT; i++) { threadsStarted[i] = new AtomicBoolean(false); threadsFinished[i] = new AtomicBoolean(false); final int index = i; new Thread(() -> { try { startLatch.await(); threadsStarted[index].set(true); Thread.sleep(100); threadsFinished[index].set(true); endLatch.countDown(); } catch (InterruptedException ignored) { } }).start(); } Thread.sleep(100); for (var started : threadsStarted) { assertFalse(started.get()); } startLatch.countDown(); Thread.sleep(50); for (var started : threadsStarted) { assertTrue(started.get()); } endLatch.await(); for (var finished : threadsFinished) { assertTrue(finished.get()); } assertEquals(0, endLatch.getCount()); } @Test @Timeout(value = 1000, unit = TimeUnit.MILLISECONDS) void testZeroCount() throws InterruptedException { var latch = new MyCountDownLatch(0); assertEquals(0, latch.getCount()); assertTrue(latch.tryAwait()); } }