@Test public void testNegativePendingNanos() throws InterruptedException { executor.setWorkFactor(0.5); executor.setPendingNanos(-1000); assertEquals(-1000, executor.getPendingNanos()); // Note: we do not expect the delay time to be used because work time + pending delay is // negative. setWorkTime(500); executor.execute(NO_OP); // Sleep should not be called with negative pending nanos Mockito.verify(executor, Mockito.never()).sleep(Mockito.anyLong()); assertEquals(-1000 + 500, executor.getPendingNanos()); }
@Test public void testInitialState() { ThrottlingExecutor throttler = new ThrottlingExecutor(MAX_NANOS); assertEquals(0, throttler.getPendingNanos()); assertEquals(1.0, throttler.getWorkFactor()); }
@Test public void testDecreaseWorkFactor() { executor.setWorkFactor(0.5); executor.setPendingNanos(5000); executor.setWorkFactor(0.3); assertEquals(5000, executor.getPendingNanos()); }
@Test public void testSetWorkRate() { executor.setWorkFactor(1.0); assertEquals(1.0, executor.getWorkFactor()); executor.setWorkFactor(0.5); assertEquals(0.5, executor.getWorkFactor()); executor.setWorkFactor(ThrottlingExecutor.MIN_WORK_FACTOR); assertEquals(ThrottlingExecutor.MIN_WORK_FACTOR, executor.getWorkFactor()); }
private void verifySleepTime(long expectedDelayTimeNanos) throws InterruptedException { Mockito.verify(executor).sleep(expectedDelayTimeNanos); } }
@Test public void test100PercentWorkRate() throws InterruptedException { setWorkTime(TimeUnit.MILLISECONDS.toNanos(5)); executor.execute(NO_OP); assertEquals(0L, executor.getPendingNanos()); // At 100% work rate sleep should not be called Mockito.verify(executor, Mockito.never()).sleep(Mockito.anyLong()); }
@Test public void testSleepOvershoot() throws InterruptedException { executor.setWorkFactor(0.5); final long workTimeNanos = TimeUnit.MILLISECONDS.toNanos(5); final long expectedDelayNanos = workTimeNanos; final long actualDelayTimeNanos = TimeUnit.MILLISECONDS.toNanos(6); setWorkTime(workTimeNanos); setActualSleepTime(actualDelayTimeNanos); executor.execute(NO_OP); verifySleepTime(expectedDelayNanos); assertEquals(expectedDelayNanos - actualDelayTimeNanos, executor.getPendingNanos()); }
@Test public void testClampDelayMillis() throws InterruptedException { final long maxDelayMillis = 10; final long maxDelayNanos = TimeUnit.MILLISECONDS.toNanos(maxDelayMillis); executor = Mockito.spy(new ThrottlingExecutor(maxDelayMillis, clock)); executor.setWorkFactor(0.5); // Note work time exceeds maxDelayMillis setWorkTime(TimeUnit.MILLISECONDS.toNanos(100)); setActualSleepTime(maxDelayNanos); executor.execute(NO_OP); verifySleepTime(maxDelayNanos); assertEquals(0L, executor.getPendingNanos()); }
@Test(expected = IllegalArgumentException.class) public void testLessThan0PercentWorkRate() { new ThrottlingExecutor(MAX_NANOS).setWorkFactor(-0.1); }
@Before public void setUp() { clock = Mockito.mock(HighResolutionClock.class); executor = Mockito.spy(new ThrottlingExecutor(MAX_NANOS, clock)); }
if (pendingNanos > 0) { try { pendingNanos = sleep(pendingNanos); } catch (InterruptedException e) { Thread.currentThread().interrupt();
@Test public void testSleepUndershoot() throws InterruptedException { executor.setWorkFactor(0.5); final long workTimeNanos = TimeUnit.MILLISECONDS.toNanos(5); final long expectedDelayNanos = workTimeNanos; final long actualDelayNanos = TimeUnit.MILLISECONDS.toNanos(4); setWorkTime(workTimeNanos); setActualSleepTime(actualDelayNanos); executor.execute(NO_OP); verifySleepTime(expectedDelayNanos); assertEquals(expectedDelayNanos - actualDelayNanos, executor.getPendingNanos()); }
@Test(expected = IllegalArgumentException.class) public void testLessThan0PercentWorkRate() { new ThrottlingExecutor(MAX_NANOS).setWorkFactor(-0.1); }
@Test public void testNegativePendingNanosGoesPositive() throws InterruptedException { executor.setWorkFactor(0.5); long startPendingNanos = -1000; executor.setPendingNanos(startPendingNanos); assertEquals(-1000, executor.getPendingNanos()); setWorkTime(1250); setActualSleepTime(1250 + startPendingNanos); executor.execute(NO_OP); verifySleepTime(1250 + startPendingNanos); assertEquals(0, executor.getPendingNanos()); }
if (pendingNanos > 0) { try { pendingNanos = sleep(pendingNanos); } catch (InterruptedException e) { Thread.currentThread().interrupt();
@Test public void test50PercentWorkRate() throws InterruptedException { executor.setWorkFactor(0.5); final long workTimeNanos = TimeUnit.MILLISECONDS.toNanos(5); setWorkTime(workTimeNanos); // Sleep time is same as work time at 50% work rate setActualSleepTime(workTimeNanos); executor.execute(NO_OP); verifySleepTime(workTimeNanos); assertEquals(0L, executor.getPendingNanos()); }
@Test public void testInitialState() { ThrottlingExecutor throttler = new ThrottlingExecutor(MAX_NANOS); assertEquals(0, throttler.getPendingNanos()); assertEquals(1.0, throttler.getWorkFactor()); }
@Test(expected = IllegalArgumentException.class) public void testGreaterThan100PercentWorkRate() { new ThrottlingExecutor(MAX_NANOS).setWorkFactor(1.1); }
@Test public void testOverflowOfSleepNanos() throws InterruptedException { executor.setWorkFactor(0.5); executor.setPendingNanos(Long.MAX_VALUE); assertEquals(Long.MAX_VALUE, executor.getPendingNanos()); // At a 50% work factor we'd expect work and sleep to match. As they don't, the function will // try to increment the pending sleep nanos, which could (but should not) result in overflow. setWorkTime(5000); setActualSleepTime(Long.MAX_VALUE); executor.execute(NO_OP); // Expect sleep nanos to be clamped to the maximum long value verifySleepTime(Long.MAX_VALUE); }
if (pendingNanos > 0) { try { pendingNanos = sleep(pendingNanos); } catch (InterruptedException e) { Thread.currentThread().interrupt();