package org.threadly.concurrent.wrapper.limiter;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.threadly.BlockingTestRunnable;
import org.threadly.concurrent.DoNothingRunnable;
import org.threadly.concurrent.PriorityScheduler;
import org.threadly.concurrent.SingleThreadScheduler;
import org.threadly.concurrent.TestCallable;
import org.threadly.test.concurrent.TestRunnable;
import org.threadly.util.StringUtils;
@SuppressWarnings("javadoc")
public class KeyedSchedulerServiceLimiterTest extends AbstractKeyedLimiterTest {
protected PriorityScheduler scheduler;
@Before
public void setup() {
scheduler = new PriorityScheduler(10);
}
@After
public void cleanup() {
scheduler.shutdownNow();
scheduler = null;
}
@Override
protected KeyedSchedulerServiceLimiter makeLimiter(int limit) {
return new KeyedSchedulerServiceLimiter(scheduler, limit, null, true, 1);
}
@Test
@SuppressWarnings("unused")
public void constructorFail() {
try {
new KeyedSchedulerServiceLimiter(null, 10);
fail("Exception should have thrown");
} catch (IllegalArgumentException e) {
// expected
}
try {
new KeyedSchedulerServiceLimiter(scheduler, 0);
fail("Exception should have thrown");
} catch (IllegalArgumentException e) {
// expected
}
}
@Test
public void removeRunnableTest() {
KeyedSchedulerServiceLimiter limiter = makeLimiter(1);
String key = StringUtils.makeRandomString(5);
BlockingTestRunnable btr = new BlockingTestRunnable();
try {
assertFalse(limiter.remove(btr));
assertFalse(limiter.remove((Runnable)null));
limiter.execute(key, btr);
TestRunnable tr = new TestRunnable();
assertFalse(limiter.remove(tr));
limiter.execute(key, tr);
assertTrue(limiter.remove(tr));
assertFalse(limiter.remove(tr));
limiter.submit(key, tr);
assertTrue(limiter.remove(tr));
assertFalse(limiter.remove(tr));
} finally {
btr.unblock();
}
}
@Test
public void removeCallableTest() {
KeyedSchedulerServiceLimiter limiter = makeLimiter(1);
String key = StringUtils.makeRandomString(5);
BlockingTestRunnable btr = new BlockingTestRunnable();
try {
assertFalse(limiter.remove(btr));
assertFalse(limiter.remove((Runnable)null));
limiter.execute(key, btr);
TestCallable tc = new TestCallable();
assertFalse(limiter.remove(tc));
limiter.submit(key, tc);
assertTrue(limiter.remove(tc));
assertFalse(limiter.remove(tc));
} finally {
btr.unblock();
}
}
@Test
public void getActiveTaskCountTest() {
KeyedSchedulerServiceLimiter limiter = makeLimiter(1);
String key = StringUtils.makeRandomString(5);
assertEquals(0, limiter.getActiveTaskCount());
BlockingTestRunnable btr = new BlockingTestRunnable();
try {
limiter.execute(key, btr);
btr.blockTillStarted();
assertEquals(1, limiter.getActiveTaskCount());
} finally {
btr.unblock();
}
}
@Test
public void getQueuedTaskCountTest() {
// must be single thread scheduler so we can block one on the shceduler
KeyedSchedulerServiceLimiter limiter = new KeyedSchedulerServiceLimiter(new SingleThreadScheduler(), 1);
String key = StringUtils.makeRandomString(5);
BlockingTestRunnable btr = new BlockingTestRunnable();
try {
assertEquals(0, limiter.getQueuedTaskCount());
limiter.execute(key, btr);
btr.blockTillStarted();
limiter.execute(StringUtils.makeRandomString(2), DoNothingRunnable.instance());
// 1 blocked on scheduler due to different key
assertEquals(1, limiter.getQueuedTaskCount());
limiter.execute(key, DoNothingRunnable.instance());
// 1 additional blocked in limiter now
assertEquals(2, limiter.getQueuedTaskCount());
} finally {
btr.unblock();
}
}
@Test
public void isShutdownTest() {
KeyedSchedulerServiceLimiter limiter = makeLimiter(1);
assertFalse(limiter.isShutdown());
scheduler.shutdown();
assertTrue(limiter.isShutdown());
}
}