package org.threadly.concurrent;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.threadly.test.concurrent.TestRunnable;
import org.threadly.test.concurrent.TestableScheduler;
@SuppressWarnings("javadoc")
public class ReschedulingOperationTest {
private static final int SCHEDULE_DELAY = 100;
private TestableScheduler scheduler;
@Before
public void setup() {
scheduler = new TestableScheduler();
}
@After
public void cleanup() {
scheduler = null;
}
@Test
@SuppressWarnings("unused")
public void constructorFail() {
try {
new TestReschedulingOperation(null, SCHEDULE_DELAY, false);
fail("Exception should have thrown");
} catch (IllegalArgumentException e) {
// expected
}
try {
new TestReschedulingOperation(scheduler, -1, false);
fail("Exception should have thrown");
} catch (IllegalArgumentException e) {
// expected
}
}
@Test
public void runAfterSignaledTest() {
TestReschedulingOperation testOp = new TestReschedulingOperation(scheduler, SCHEDULE_DELAY, false);
assertEquals(0, scheduler.advance(SCHEDULE_DELAY));
testOp.signalToRun();
// should run once, but not again
assertEquals(1, scheduler.advance(SCHEDULE_DELAY));
assertEquals(0, scheduler.advance(SCHEDULE_DELAY));
assertEquals(0, scheduler.getQueuedTaskCount());
testOp.signalToRun();
// should run again, but not again
assertEquals(1, scheduler.advance(SCHEDULE_DELAY));
assertEquals(0, scheduler.advance(SCHEDULE_DELAY));
assertEquals(0, scheduler.getQueuedTaskCount());
assertEquals(2, testOp.tr.getRunCount());
}
@Test
public void autoRescheduleTest() {
TestReschedulingOperation testOp = new TestReschedulingOperation(scheduler, SCHEDULE_DELAY, true);
testOp.signalToRun();
// should run every time
assertEquals(1, scheduler.advance(SCHEDULE_DELAY));
assertEquals(1, scheduler.advance(SCHEDULE_DELAY));
assertEquals(1, scheduler.getQueuedTaskCount());
assertEquals(2, testOp.tr.getRunCount());
}
@Test
public void changeScheduleDelayTest() {
TestReschedulingOperation testOp = new TestReschedulingOperation(scheduler, SCHEDULE_DELAY, true);
testOp.setScheduleDelay(SCHEDULE_DELAY / 2);
testOp.signalToRun();
assertEquals(1, scheduler.advance(SCHEDULE_DELAY / 2));
assertEquals(1, testOp.tr.getRunCount());
}
private static class TestReschedulingOperation extends ReschedulingOperation {
public final TestRunnable tr = new TestRunnable();
private final boolean alwaysReschedule;
protected TestReschedulingOperation(SubmitterScheduler scheduler,
long scheduleDelay, boolean alwaysReschedule) {
super(scheduler, scheduleDelay);
this.alwaysReschedule = alwaysReschedule;
}
@Override
protected void run() {
tr.run();
if (alwaysReschedule) {
signalToRun();
}
}
}
}