package aQute.lib.concurrentinit; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; import org.junit.Assert; import org.junit.Test; public class ConcurrentInitializeTest extends Assert { final static Executor executor = Executors.newCachedThreadPool(); @Test public void testSimple() throws Exception { ConcurrentInitialize<String> ci = new ConcurrentInitialize<String>() { @Override public String create() throws Exception { return "foo"; } }; assertEquals("foo", ci.get()); } @Test public void testConcurrent() throws InterruptedException { final Semaphore result = new Semaphore(0); final Semaphore onCreate = new Semaphore(0); final ConcurrentInitialize<String> ci = new ConcurrentInitialize<String>() { @Override public String create() throws Exception { onCreate.acquire(); return "foo"; } }; final Thread threads [] = new Thread[10]; for (int i = 0; i < 10; i++) { final int j = i; executor.execute(new Runnable() { @Override public void run() { threads[j] = Thread.currentThread(); try { ci.get(); result.release(); } catch (Exception e) { // cant happen } } }); } // First wait so that we can verify that nobody can // continue until we allow it Thread.sleep(100); assertEquals(0, result.availablePermits()); // allow the creator to pass onCreate.release(1); // only 1 can create // Check the results result.acquire(10); } @Test(expected = Exception.class) public void testExceptionForFirstCall() throws Exception { ConcurrentInitialize<String> ci = new ConcurrentInitialize<String>() { @Override public String create() throws Exception { throw new Exception(); } }; ci.get(); } @Test(expected = Exception.class) public void testExceptionForFurtherCalls() throws Exception { ConcurrentInitialize<String> ci = new ConcurrentInitialize<String>() { @Override public String create() throws Exception { throw new Exception(); } }; try { ci.get(); } catch (Exception e) { // ignore } ci.get(); } }