package freenet.support;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
import junit.framework.TestCase;
import freenet.node.PrioRunnable;
import freenet.support.io.NativeThread;
public class PrioritizedSerialExecutorTest extends TestCase {
private Executor realExec;
private PrioritizedSerialExecutor exec;
private SynchronousQueue<String> completingJob;
private List<String> completedJobs;
private class J implements PrioRunnable {
private int prio;
private String name;
J(String name, int prio) {
this.name = name;
this.prio = prio;
}
@Override
public int getPriority() {
return prio;
}
@Override
public void run() {
synchronized (this) {
notifyAll();
}
try {
assertTrue(exec.onThread());
completingJob.put(name);
} catch (InterruptedException e) {
fail(e.toString());
}
}
}
@Override
protected void setUp() throws Exception {
super.setUp();
realExec = new PooledExecutor();
completedJobs = new ArrayList<String>();
completingJob = new SynchronousQueue<String>();
exec = new PrioritizedSerialExecutor(NativeThread.MAX_PRIORITY, 10, 5, true);
}
private void Q(String j, int i, boolean waitForStart) throws InterruptedException {
J job = new J(j, i);
synchronized (job) {
exec.execute(job, j);
if (waitForStart)
job.wait(5000);
}
}
private void waitFor(int count) throws InterruptedException {
int completed = 0;
while (completed < count) {
String s = completingJob.poll(5, TimeUnit.SECONDS);
if (s == null)
fail("Hang?");
completed++;
completedJobs.add(s);
}
System.out.println(completedJobs);
}
public void testRun() throws InterruptedException {
assertTrue(completedJobs.isEmpty());
Q("J1", 0, false);
Q("J2", 0, false);
Q("J3", 0, false);
Q("J4", 0, false);
Thread.yield();
Thread.sleep(10);
assertTrue(completedJobs.isEmpty()); // not started yet!
exec.start(realExec, "testRun"); // start !
waitFor(4);
assertTrue(completedJobs.contains("J1"));
assertTrue(completedJobs.contains("J2"));
assertTrue(completedJobs.contains("J3"));
assertTrue(completedJobs.contains("J4"));
assertFalse(exec.onThread());
}
public void testRunPrio() throws InterruptedException {
assertTrue(completedJobs.isEmpty());
Q("JM", 9, false);
Q("J8", 8, false);
assertTrue(completedJobs.isEmpty()); // not started yet!
assertEquals(0, exec.getWaitingThreadsCount());
exec.start(realExec, "testRunPrio"); // start !
waitFor(1); // JM
Q("J2", 2, false);
Q("JN", 4, false);
Q("JO", 2, false);
Q("JP", 3, false);
assertEquals(0, exec.getQueueSize(9));
assertEquals(1, exec.getQueueSize(3));
assertEquals(2, exec.getQueueSize(2));
waitFor(2); // J8,JN
assertEquals(0, exec.getQueueSize(9));
assertEquals(0, exec.getQueueSize(4));
assertEquals(2, exec.getQueueSize(2));
Thread.yield();
Thread.sleep(10);
Q("JQ", 4, false);
Q("JR", 0, false);
assertEquals(1, exec.getQueueSize(4));
assertEquals(2, exec.getQueueSize(2));
assertEquals(0, exec.getQueueSize(1));
assertEquals(1, exec.getQueueSize(0));
int[] r = exec.getQueuedJobsCountByPriority();
assertTrue(
Arrays.equals(new int[] { 1, 0, 2, 0, 1, 0, 0, 0, 0, 0 }, r) ||
Arrays.equals(new int[] { 1, 0, 2, 1, 1, 0, 0, 0, 0, 0 }, r)
);
waitFor(5); // JP, JQ, J2, JO, JR
int i = 0;
for (String s : new String[] { "JM", "J8", "JN", "JP", "JQ", "J2", "JO", "JR" })
assertEquals(s, s, completedJobs.get(i++));
}
}