/*
* $Id$
*
* Copyright 2009 Glencoe Software, Inc. All rights reserved.
* Use is subject to license terms supplied in LICENSE.txt
*/
package ome.services.blitz.test.utests;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import junit.framework.TestCase;
import omero.util.Resources;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
public class ResourcesTest extends TestCase {
int MAX_WAIT = 3;
ScheduledExecutorService s;
Resources r;
TestEntry e;
@BeforeMethod
void startup() {
s = Executors.newSingleThreadScheduledExecutor();
r = new Resources(1, s);
}
@AfterMethod
void shutdown() {
if (r != null) {
r.cleanup();
}
}
/**
* Can be used to pause the execution of the
* {@link ScheduledExecutorService} by inserting a blocking task into the
* single thread. Once {@link CountDownLatch#countDown()} is called on the
* return value, then execution can resume.
*/
CountDownLatch pause() throws Exception {
final CountDownLatch entered = new CountDownLatch(1);
final CountDownLatch exit = new CountDownLatch(1);
s.execute(new Runnable() {
public void run() {
entered.countDown();
try {
exit.await();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
assertTrue(entered.await(10, TimeUnit.SECONDS));
return exit;
}
class TestEntry implements Resources.Entry {
volatile CountDownLatch checkLatch = new CountDownLatch(2);
volatile CountDownLatch cleanLatch = new CountDownLatch(1);
volatile boolean checkValue = true;
volatile boolean throwOnCheck = false;
volatile boolean throwOnCleanup = false;
public boolean checkWait() throws InterruptedException {
return checkLatch.await(MAX_WAIT, TimeUnit.SECONDS);
}
public boolean cleanWait() throws InterruptedException {
return cleanLatch.await(MAX_WAIT, TimeUnit.SECONDS);
}
public boolean check() {
checkLatch.countDown();
if (throwOnCheck) {
throw new RuntimeException("They made me do it");
}
return checkValue;
}
public void cleanup() {
cleanLatch.countDown();
if (throwOnCleanup) {
throw new RuntimeException("They made me do it again.");
}
}
}
@Test
public void testSimple() throws Exception {
e = new TestEntry();
r.add(e);
assertTrue(e.checkWait());
}
@Test
public void testShouldBeRemoved() throws Exception {
e = new TestEntry();
r.add(e);
assertEquals(1, r.size());
assertTrue(e.checkWait());
CountDownLatch resume = pause();
e.checkValue = false;
resume.countDown();
assertTrue(e.cleanWait());
assertEquals(0, r.size());
}
@Test
public void testCheckFalseLeadsToRemove() throws Exception {
e = new TestEntry();
r.add(e);
assertEquals(1, r.size());
assertTrue(e.checkWait());
CountDownLatch resume = pause();
e.checkValue = false;
resume.countDown();
assertTrue(e.cleanWait());
assertEquals(0, r.size());
}
@Test
public void testCheckThrowsLeadsToRemove() throws Exception {
e = new TestEntry();
r.add(e);
assertEquals(1, r.size());
assertTrue(e.checkWait());
CountDownLatch resume = pause();
e.throwOnCheck = true;
resume.countDown();
assertTrue(e.cleanWait());
assertEquals(0, r.size());
}
@Test
public void testCleanupThrowsIsCaught() throws Exception {
e = new TestEntry();
r.add(e);
assertEquals(1, r.size());
assertTrue(e.checkWait());
CountDownLatch resume = pause();
e.checkValue = false; // Force cleanup.
e.throwOnCleanup = true;
resume.countDown();
assertTrue(e.cleanWait());
assertEquals(0, r.size());
}
}