package net.sourceforge.cruisecontrol.util.threadpool;
import junit.framework.TestCase;
public class ThreadQueueShouldHandleDuplicateTasksTest extends TestCase {
private StubWorkerThread scheduledWorkerThread;
private StubWorkerThread dupeOfScheduledWorkerThread;
protected void setUp() throws Exception {
super.setUp();
scheduledWorkerThread = new StubWorkerThread();
dupeOfScheduledWorkerThread = new StubWorkerThread();
}
protected void tearDown() throws Exception {
super.tearDown();
scheduledWorkerThread.completeBuild();
dupeOfScheduledWorkerThread.completeBuild();
ThreadQueue.stopQueue();
}
public void testThreadQueueShouldHandleDuplicateTasks() throws Exception {
ThreadQueueProperties.setMaxThreadCount(10);
assertTrue("number of busy/started threads should yet be 0", StubWorkerThread.numberOfRunningThreads == 0);
ThreadQueue.addTask(scheduledWorkerThread);
try {
ThreadQueue.addTask(dupeOfScheduledWorkerThread);
} catch (RuntimeException e) {
fail("ThreadQueue should allow the same project to be added twice. "
+ "Duplicates are handled internally by ThreadQueue "
+ "which makes sure they are not build simultaneously");
}
int count = 0;
while (StubWorkerThread.numberOfRunningThreads == 0 && count < 5) {
Thread.sleep(count * 100);
count++;
}
assertTrue("only the first scheduledWorkerThread should be busy/started, so number of threads should be 1",
StubWorkerThread.numberOfRunningThreads == 1);
scheduledWorkerThread.completeBuild();
// This required length of this sleep may vary depending on thread scheduling...maybe we need some kind of
// queueListener to be sure of such state changes?
Thread.sleep(250);
assertTrue("now the second scheduledWorkerThread should be busy/started, so number of threads should be 1",
StubWorkerThread.numberOfRunningThreads == 1);
scheduledWorkerThread.completeBuild();
}
private static final class StubWorkerThread implements WorkerThread {
private final String taskName = "Dummy project from ThreadQueueShouldHandleDuplicateTasksTest";
private boolean completed = false;
private static int numberOfRunningThreads = 0;
public synchronized void completeBuild() {
this.completed = true;
this.notify();
}
public String getName() {
return taskName;
}
public synchronized Object getResult() {
return this.completed ? "finished" : null;
}
public synchronized void run() {
try {
if (numberOfRunningThreads > 1) {
fail("ThreadQueue should never allow to run the same project simultanously");
}
numberOfRunningThreads++;
this.wait();
numberOfRunningThreads--;
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}