package org.threadly.concurrent;
import static org.junit.Assert.*;
import static org.threadly.TestConstants.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.threadly.concurrent.AbstractPriorityScheduler.OneTimeTaskWrapper;
import org.threadly.concurrent.AbstractPriorityScheduler.QueueManager;
import org.threadly.concurrent.AbstractPriorityScheduler.QueueSet;
import org.threadly.concurrent.AbstractPriorityScheduler.QueueSetListener;
import org.threadly.concurrent.AbstractPriorityScheduler.TaskWrapper;
import org.threadly.concurrent.future.ListenableFutureTask;
import org.threadly.test.concurrent.TestRunnable;
import org.threadly.test.concurrent.TestUtils;
import org.threadly.util.Clock;
@SuppressWarnings("javadoc")
public class PrioritySchedulerQueueManagerTest {
private QueueManager queueManager;
@Before
public void setup() {
queueManager = new QueueManager(new QueueSetListener() {
@Override
public void handleQueueUpdate() {
// ignore event
}
}, AbstractPriorityScheduler.DEFAULT_LOW_PRIORITY_MAX_WAIT_IN_MS);
}
@After
public void cleanup() {
queueManager = null;
}
@Test
public void removeCallableTest() {
TestCallable callable = new TestCallable();
OneTimeTaskWrapper task = new OneTimeTaskWrapper(new ListenableFutureTask<>(false, callable),
null, Clock.lastKnownForwardProgressingMillis());
assertFalse(queueManager.remove(callable));
queueManager.highPriorityQueueSet.executeQueue.add(task);
assertTrue(queueManager.remove(callable));
assertFalse(queueManager.remove(callable));
queueManager.lowPriorityQueueSet.scheduleQueue.addFirst(task);
assertTrue(queueManager.remove(callable));
assertFalse(queueManager.remove(callable));
}
@Test
public void removeRunnableTest() {
TestRunnable runnable = new TestRunnable();
OneTimeTaskWrapper task = new OneTimeTaskWrapper(runnable, null,
Clock.lastKnownForwardProgressingMillis());
assertFalse(queueManager.remove(runnable));
queueManager.highPriorityQueueSet.executeQueue.add(task);
assertTrue(queueManager.remove(runnable));
assertFalse(queueManager.remove(runnable));
queueManager.lowPriorityQueueSet.scheduleQueue.addFirst(task);
assertTrue(queueManager.remove(runnable));
assertFalse(queueManager.remove(runnable));
}
@Test
public void getNextReadyTaskExecuteOnlyHighTest() {
getNextReadyTaskExecuteTest(queueManager.highPriorityQueueSet);
}
@Test
public void getNextReadyTaskExecuteOnlyLowTest() {
getNextReadyTaskExecuteTest(queueManager.lowPriorityQueueSet);
}
private void getNextReadyTaskExecuteTest(QueueSet queueSet) {
OneTimeTaskWrapper task = new OneTimeTaskWrapper(DoNothingRunnable.instance(), queueSet.executeQueue,
Clock.lastKnownForwardProgressingMillis());
queueSet.addExecute(task);
assertTrue(task == queueManager.getNextTask());
}
@Test
public void getNextReadyTaskScheduleOnlyHighTest() {
getNextReadyTaskScheduledTest(queueManager.highPriorityQueueSet);
}
@Test
public void getNextReadyTaskScheduleOnlyLowTest() {
getNextReadyTaskScheduledTest(queueManager.lowPriorityQueueSet);
}
private void getNextReadyTaskScheduledTest(QueueSet queueSet) {
TaskWrapper task = new OneTimeTaskWrapper(DoNothingRunnable.instance(), queueSet.scheduleQueue,
Clock.lastKnownForwardProgressingMillis());
queueSet.addScheduled(task);
assertTrue(task == queueManager.getNextTask());
}
@Test
public void getNextReadyTaskExecuteAheadOfScheduledTest() {
OneTimeTaskWrapper executeTask = new OneTimeTaskWrapper(DoNothingRunnable.instance(),
queueManager.highPriorityQueueSet.executeQueue,
Clock.accurateForwardProgressingMillis());
queueManager.highPriorityQueueSet.addExecute(executeTask);
TestUtils.blockTillClockAdvances();
TaskWrapper scheduleTask = new OneTimeTaskWrapper(DoNothingRunnable.instance(),
queueManager.highPriorityQueueSet.scheduleQueue,
Clock.lastKnownForwardProgressingMillis());
queueManager.highPriorityQueueSet.addScheduled(scheduleTask);
assertTrue(executeTask == queueManager.getNextTask());
assertTrue(executeTask == queueManager.getNextTask()); // execute task has not been removed yet
// this should remove the execute task so we can get the scheduled task
assertTrue(executeTask.canExecute(executeTask.getExecuteReference()));
assertTrue(scheduleTask == queueManager.getNextTask());
}
@Test
public void getNextReadyTaskScheduledAheadOfExecuteTest() {
TaskWrapper scheduleTask = new OneTimeTaskWrapper(DoNothingRunnable.instance(),
queueManager.highPriorityQueueSet.scheduleQueue,
Clock.accurateForwardProgressingMillis());
queueManager.highPriorityQueueSet.addScheduled(scheduleTask);
TestUtils.blockTillClockAdvances();
OneTimeTaskWrapper executeTask = new OneTimeTaskWrapper(DoNothingRunnable.instance(),
queueManager.highPriorityQueueSet.executeQueue,
Clock.lastKnownForwardProgressingMillis());
queueManager.highPriorityQueueSet.addExecute(executeTask);
assertTrue(scheduleTask == queueManager.getNextTask());
assertTrue(scheduleTask == queueManager.getNextTask()); // schedule task has not been removed yet
// this should remove the schedule task so we can get the execute task
assertTrue(scheduleTask.canExecute(executeTask.getExecuteReference()));
assertTrue(executeTask == queueManager.getNextTask());
}
@Test
public void getNextReadyTaskHighPriorityDelayedTest() {
TaskWrapper scheduleTask = new OneTimeTaskWrapper(DoNothingRunnable.instance(),
queueManager.highPriorityQueueSet.scheduleQueue,
Clock.accurateForwardProgressingMillis() + 1000);
queueManager.highPriorityQueueSet.addScheduled(scheduleTask);
TestUtils.blockTillClockAdvances();
OneTimeTaskWrapper executeTask = new OneTimeTaskWrapper(DoNothingRunnable.instance(),
queueManager.lowPriorityQueueSet.executeQueue,
Clock.lastKnownForwardProgressingMillis());
queueManager.lowPriorityQueueSet.addExecute(executeTask);
assertTrue(executeTask == queueManager.getNextTask());
}
@Test
public void getNextReadyTaskHighPriorityReadyFirstTest() {
TaskWrapper highTask = new OneTimeTaskWrapper(DoNothingRunnable.instance(),
queueManager.highPriorityQueueSet.scheduleQueue,
Clock.accurateForwardProgressingMillis() + DELAY_TIME);
TaskWrapper lowTask = new OneTimeTaskWrapper(DoNothingRunnable.instance(),
queueManager.lowPriorityQueueSet.scheduleQueue,
Clock.lastKnownForwardProgressingMillis() + (DELAY_TIME * 10));
queueManager.highPriorityQueueSet.addScheduled(highTask);
queueManager.lowPriorityQueueSet.addScheduled(lowTask);
assertTrue(highTask == queueManager.getNextTask());
}
@Test
public void getNextReadyTaskLowPriorityReadyFirstTest() {
TaskWrapper highTask = new OneTimeTaskWrapper(DoNothingRunnable.instance(),
queueManager.highPriorityQueueSet.scheduleQueue,
Clock.accurateForwardProgressingMillis() + (DELAY_TIME * 10));
TaskWrapper lowTask = new OneTimeTaskWrapper(DoNothingRunnable.instance(),
queueManager.lowPriorityQueueSet.scheduleQueue,
Clock.lastKnownForwardProgressingMillis() + DELAY_TIME);
queueManager.highPriorityQueueSet.addScheduled(highTask);
queueManager.lowPriorityQueueSet.addScheduled(lowTask);
assertTrue(lowTask == queueManager.getNextTask());
}
@Test
public void getAndSetLowPriorityWaitTest() {
assertEquals(AbstractPriorityScheduler.DEFAULT_LOW_PRIORITY_MAX_WAIT_IN_MS, queueManager.getMaxWaitForLowPriority());
long lowPriorityWait = Long.MAX_VALUE;
queueManager.setMaxWaitForLowPriority(lowPriorityWait);
assertEquals(lowPriorityWait, queueManager.getMaxWaitForLowPriority());
}
@Test
public void setLowPriorityWaitFail() {
try {
queueManager.setMaxWaitForLowPriority(-1);
fail("Exception should have thrown");
} catch (IllegalArgumentException e) {
// expected
}
assertEquals(AbstractPriorityScheduler.DEFAULT_LOW_PRIORITY_MAX_WAIT_IN_MS, queueManager.getMaxWaitForLowPriority());
}
}