import org.junit.jupiter.api.Test; import ru.lionarius.sync.MySemaphore; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import static org.junit.jupiter.api.Assertions.*; class MySemaphoreTest { @Test void testInitialization() { assertDoesNotThrow(() -> new MySemaphore(-1)); assertDoesNotThrow(() -> new MySemaphore(0)); var semaphore = new MySemaphore(5); assertEquals(5, semaphore.availablePermits()); } @Test void testAcquireAndRelease() throws InterruptedException { var semaphore = new MySemaphore(2); assertEquals(2, semaphore.availablePermits()); semaphore.acquire(); assertEquals(1, semaphore.availablePermits()); semaphore.acquire(); assertEquals(0, semaphore.availablePermits()); assertFalse(semaphore.tryAcquire()); semaphore.release(); assertEquals(1, semaphore.availablePermits()); assertTrue(semaphore.tryAcquire()); assertEquals(0, semaphore.availablePermits()); } @Test void testTryAcquire() { var semaphore = new MySemaphore(2); assertTrue(semaphore.tryAcquire()); assertEquals(1, semaphore.availablePermits()); assertTrue(semaphore.tryAcquire()); assertEquals(0, semaphore.availablePermits()); assertFalse(semaphore.tryAcquire()); assertEquals(0, semaphore.availablePermits()); } @Test void testMultipleThreads() throws InterruptedException { final int THREAD_COUNT = 10; final int PERMITS = 3; var semaphore = new MySemaphore(PERMITS); var startLatch = new CountDownLatch(1); var finishLatch = new CountDownLatch(THREAD_COUNT); var concurrentThreads = new AtomicInteger(0); var maxConcurrentThreads = new AtomicInteger(0); for (int i = 0; i < THREAD_COUNT; i++) { new Thread(() -> { try { startLatch.await(); semaphore.acquire(); int current = concurrentThreads.incrementAndGet(); maxConcurrentThreads.updateAndGet(max -> Math.max(max, current)); Thread.sleep(100); concurrentThreads.decrementAndGet(); semaphore.release(); finishLatch.countDown(); } catch (InterruptedException ignored) { } }).start(); } startLatch.countDown(); assertTrue(finishLatch.await(5, TimeUnit.SECONDS)); assertEquals(PERMITS, maxConcurrentThreads.get()); assertEquals(PERMITS, semaphore.availablePermits()); } @Test void testBlockingAcquire() throws InterruptedException { var semaphore = new MySemaphore(1); semaphore.acquire(); assertEquals(0, semaphore.availablePermits()); var startLatch = new CountDownLatch(1); var doneLatch = new CountDownLatch(1); var thread = new Thread(() -> { try { startLatch.countDown(); semaphore.acquire(); } catch (InterruptedException ignored) { } doneLatch.countDown(); }); thread.start(); startLatch.await(); assertTrue(thread.isAlive()); assertEquals(0, semaphore.availablePermits()); semaphore.release(); doneLatch.await(); assertFalse(thread.isAlive()); assertEquals(0, semaphore.availablePermits()); } @Test void testAvailablePermits() { var semaphore = new MySemaphore(5); assertEquals(5, semaphore.availablePermits()); semaphore.tryAcquire(); assertEquals(4, semaphore.availablePermits()); semaphore.release(); assertEquals(5, semaphore.availablePermits()); } }