Java tutorial
/** * Copyright [2011] [Datasalt Systems S.L.] * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.datasalt.utils.commons; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import org.apache.hadoop.io.BooleanWritable; import org.junit.Test; import com.datasalt.utils.commons.ExpiringSemaphore; /** * Unit tests for the {@link ExpiringSemaphore} * * @author pere * */ public class TestExpiringSemaphore { /* * Here we will test that after "expiring" time the acquires() done with no release() afterwards become available again */ @Test public void testPermitExpiring() throws InterruptedException { long expiring = 1000; long start = System.currentTimeMillis(); ExpiringSemaphore semaphore = new ExpiringSemaphore(2, expiring); assertEquals(semaphore.availablePermits(), 2); semaphore.acquire(); assertEquals(semaphore.availablePermits(), 1); semaphore.acquire(); // next call will block until one permit expires assertEquals(semaphore.availablePermits(), 0); semaphore.acquire(); // expired assertTrue(semaphore.expiredCount() >= 1); long end = System.currentTimeMillis(); assertTrue((end - start) >= expiring); // let's grab one more one semaphore.acquire(); // expire count = 2 assertEquals(semaphore.expiredCount(), 2); } /* * Here we will test the usedPermits() method. We will block on it until it reaches = 0 because of automatic expiring. */ @Test public void testUsedPermits() throws InterruptedException { long expiring = 1000; ExpiringSemaphore semaphore = new ExpiringSemaphore(4, expiring); semaphore.acquire(); semaphore.acquire(); semaphore.acquire(); semaphore.acquire(); assertEquals(semaphore.availablePermits(), 0); assertEquals(semaphore.usedPermits(), 4); while (semaphore.usedPermits() > 0) { Thread.sleep(100); } assertEquals(semaphore.availablePermits(), 4); /* * Here we are also testing the currentlyExpiredPermits() which shows us a snapshot of the * permits that are expired in the semaphore. It tells us how many permits someone could * grab with acquire() such that these permits have expired (there wasn't release() called for them). */ assertEquals(semaphore.currentlyExpiredPermits(), 4); semaphore.acquire(); semaphore.acquire(); semaphore.acquire(); semaphore.acquire(); assertEquals(semaphore.expiredCount(), 4); } /* * Here we will test that release() behaves like a normal semaphore. We won't expire any permit. */ @Test public void testSequentialRelease() throws InterruptedException { long expiring = 10000; ExpiringSemaphore semaphore = new ExpiringSemaphore(3, expiring); /* * Acquire 3 */ semaphore.acquire(); semaphore.acquire(); semaphore.acquire(); long start = System.currentTimeMillis(); /* * release + acquire */ semaphore.release(); semaphore.acquire(); long end = System.currentTimeMillis(); assertTrue((end - start) < 50); start = System.currentTimeMillis(); /* * release + acquire */ semaphore.release(); semaphore.acquire(); end = System.currentTimeMillis(); assertTrue((end - start) < 50); start = System.currentTimeMillis(); /* * release + acquire */ semaphore.release(); semaphore.acquire(); end = System.currentTimeMillis(); assertTrue((end - start) < 50); /* * Assert we have had no expired permits */ assertEquals(semaphore.expiredCount() + semaphore.currentlyExpiredPermits(), 0); } /* * Here we will test that release() is an operation that awakes threads blocking on acquire() * One thread will block on an acquire() and the other (main) thread will release() a resource. */ @Test public void testConcurrentRelease() throws InterruptedException { final long expiring = 10000; final ExpiringSemaphore semaphore = new ExpiringSemaphore(3, expiring); Thread t = new Thread() { public void run() { try { semaphore.acquire(); semaphore.acquire(); long start = System.currentTimeMillis(); semaphore.acquire(); long end = System.currentTimeMillis(); assertTrue((end - start) < 50); } catch (InterruptedException e) { e.printStackTrace(); } } }; semaphore.acquire(); t.start(); semaphore.release(); t.join(); assertEquals(semaphore.expiredCount(), 0); } /* * This parallelism thread just asserts that the semaphore can be used like a normal semaphore. * We will use 10 threads that will compete for a 1-sized semaphore and execute a block of code like this: * * flag = true * flag = false * * The threads will assert that flag is always false when they have acquired() the semaphore, otherwise * the semaphore is not acting like a mutex. */ @Test public void testParallelism() throws InterruptedException { final ExpiringSemaphore semaphore = new ExpiringSemaphore(1, 2000); final BooleanWritable flag = new BooleanWritable(); Thread[] threads = new Thread[10]; for (int i = 0; i < 10; i++) { threads[i] = new Thread() { @Override public void run() { try { for (int i = 0; i < 200; i++) { semaphore.acquire(); if (flag.get()) { throw new RuntimeException("Semaphore is not behaving as expected"); } flag.set(true); flag.set(false); semaphore.release(); } } catch (InterruptedException e) { throw new RuntimeException(e); } } }; } for (int i = 0; i < 10; i++) { threads[i].start(); } for (int i = 0; i < 10; i++) { threads[i].join(); } } }