package org.threadly.concurrent.wrapper.limiter; import static org.junit.Assert.*; import static org.threadly.TestConstants.*; import java.util.concurrent.RejectedExecutionException; import org.junit.Test; import org.threadly.concurrent.DoNothingRunnable; import org.threadly.concurrent.PriorityScheduler; import org.threadly.concurrent.PrioritySchedulerTest.PrioritySchedulerFactory; import org.threadly.concurrent.SchedulerService; import org.threadly.concurrent.SchedulerServiceInterfaceTest; import org.threadly.concurrent.SubmitterExecutor; import org.threadly.concurrent.SubmitterScheduler; import org.threadly.concurrent.TaskPriority; import org.threadly.concurrent.TestCallable; import org.threadly.test.concurrent.TestableScheduler; @SuppressWarnings("javadoc") public class PrioritySchedulerServiceQueueLimitRejectorTest extends SchedulerServiceInterfaceTest { @Override protected SchedulerServiceFactory getSchedulerServiceFactory() { return new PrioritySchedulerServiceQueueRejectorFactory(); } @Override protected boolean isSingleThreaded() { return false; } @SuppressWarnings("unused") @Test (expected = IllegalArgumentException.class) public void constructorFail() { new PrioritySchedulerServiceQueueLimitRejector(null, TEST_QTY); } @Test public void getSetQueueLimitTest() { TestableScheduler testableScheduler = new TestableScheduler(); PrioritySchedulerServiceQueueLimitRejector queueRejector = new PrioritySchedulerServiceQueueLimitRejector(testableScheduler, TEST_QTY); assertEquals(TEST_QTY, queueRejector.getQueueLimit()); queueRejector.setQueueLimit(TEST_QTY * 2); assertEquals(TEST_QTY * 2, queueRejector.getQueueLimit()); } @Test public void getQueuedTaskCountTest() { TestableScheduler testableScheduler = new TestableScheduler(); PrioritySchedulerServiceQueueLimitRejector queueRejector = new PrioritySchedulerServiceQueueLimitRejector(testableScheduler, TEST_QTY); for (int i = 0; i < TEST_QTY; i++) { assertEquals(i, queueRejector.getQueuedTaskCount()); queueRejector.execute(DoNothingRunnable.instance()); } assertEquals(TEST_QTY, testableScheduler.tick()); assertEquals(0, queueRejector.getQueuedTaskCount()); } @Test public void getQueuedTaskByPriorityCountTest() { getQueuedTaskByPriorityCountTest(TaskPriority.High); getQueuedTaskByPriorityCountTest(TaskPriority.Low); getQueuedTaskByPriorityCountTest(TaskPriority.Starvable); } private static void getQueuedTaskByPriorityCountTest(TaskPriority submitPriority) { TestableScheduler testableScheduler = new TestableScheduler(); PrioritySchedulerServiceQueueLimitRejector queueRejector = new PrioritySchedulerServiceQueueLimitRejector(testableScheduler, TEST_QTY); for (int i = 0; i < TEST_QTY; i++) { assertEquals(TaskPriority.High == submitPriority ? i : 0, queueRejector.getQueuedTaskCount(TaskPriority.High)); assertEquals(TaskPriority.Low == submitPriority ? i : 0, queueRejector.getQueuedTaskCount(TaskPriority.Low)); assertEquals(TaskPriority.Starvable == submitPriority ? i : 0, queueRejector.getQueuedTaskCount(TaskPriority.Starvable)); queueRejector.execute(DoNothingRunnable.instance(), submitPriority); } assertEquals(TEST_QTY, testableScheduler.tick()); assertEquals(0, queueRejector.getQueuedTaskCount(submitPriority)); } @Test public void rejectRunnableTest() { TestableScheduler testableScheduler = new TestableScheduler(); PrioritySchedulerServiceQueueLimitRejector queueRejector = new PrioritySchedulerServiceQueueLimitRejector(testableScheduler, TEST_QTY); for (int i = 0; i < TEST_QTY; i++) { queueRejector.execute(DoNothingRunnable.instance()); } try { queueRejector.execute(DoNothingRunnable.instance()); fail("Exception should have thrown"); } catch (RejectedExecutionException e) { // expected } // verify the task was never added assertEquals(TEST_QTY, testableScheduler.tick()); // we should be able to add again now for (int i = 0; i < TEST_QTY; i++) { queueRejector.execute(DoNothingRunnable.instance()); } } @Test public void rejectCallableTest() { TestableScheduler testableScheduler = new TestableScheduler(); PrioritySchedulerServiceQueueLimitRejector queueRejector = new PrioritySchedulerServiceQueueLimitRejector(testableScheduler, TEST_QTY); for (int i = 0; i < TEST_QTY; i++) { queueRejector.submit(new TestCallable()); } try { queueRejector.submit(new TestCallable()); fail("Exception should have thrown"); } catch (RejectedExecutionException e) { // expected } // verify the task was never added assertEquals(TEST_QTY, testableScheduler.tick()); // we should be able to add again now for (int i = 0; i < TEST_QTY; i++) { queueRejector.submit(new TestCallable()); } } @Test public void starvablePriorityNotIgnoredTest() { starvablePriorityIgnoredTest(false); } @Test public void starvablePriorityIgnoredTest() { starvablePriorityIgnoredTest(true); } private static void starvablePriorityIgnoredTest(boolean ignored) { TestableScheduler testableScheduler = new TestableScheduler(); PrioritySchedulerServiceQueueLimitRejector queueRejector = new PrioritySchedulerServiceQueueLimitRejector(testableScheduler, TEST_QTY, ignored); for (int i = 0; i < TEST_QTY; i++) { assertEquals(ignored ? 0 : i, queueRejector.getQueuedTaskCount()); queueRejector.execute(DoNothingRunnable.instance(), TaskPriority.Starvable); } assertEquals(TEST_QTY, testableScheduler.tick()); } private static class PrioritySchedulerServiceQueueRejectorFactory implements SchedulerServiceFactory { private final PrioritySchedulerFactory schedulerFactory = new PrioritySchedulerFactory(); @Override public SubmitterExecutor makeSubmitterExecutor(int poolSize, boolean prestartIfAvailable) { return makeSubmitterScheduler(poolSize, prestartIfAvailable); } @Override public SubmitterScheduler makeSubmitterScheduler(int poolSize, boolean prestartIfAvailable) { return makeSchedulerService(poolSize, prestartIfAvailable); } @Override public SchedulerService makeSchedulerService(int poolSize, boolean prestartIfAvailable) { PriorityScheduler scheduler = schedulerFactory.makePriorityScheduler(poolSize); if (prestartIfAvailable) { scheduler.prestartAllThreads(); } return new PrioritySchedulerServiceQueueLimitRejector(scheduler, Integer.MAX_VALUE); } @Override public void shutdown() { schedulerFactory.shutdown(); } } }