// Copyright 2016 Twitter. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.twitter.heron.common.basics;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.Duration;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* WakeableLooper Tester.
*/
public class WakeableLooperTest {
private static int globalValue;
private static final long SECONDS_TO_NANOSECONDS = 1000 * 1000 * 1000;
private WakeableLooper slaveLooper;
@Before
public void before() throws Exception {
slaveLooper = new SlaveLooper();
globalValue = 6;
}
@After
public void after() throws Exception {
slaveLooper = null;
}
/**
* Method: loop()
*/
@Test
public void testLoop() throws Exception {
Runnable r = new Runnable() {
private int i = 3;
@Override
public void run() {
globalValue += 10;
slaveLooper.wakeUp();
i--;
if (i == 0) {
slaveLooper.exitLoop();
}
}
};
slaveLooper.addTasksOnWakeup(r);
slaveLooper.loop();
Assert.assertEquals(36, globalValue);
}
/**
* Method: addTasksOnWakeup(Runnable task)
*/
@Test
public void testAddTasksOnWakeup() throws Exception {
Runnable r = new Runnable() {
@Override
public void run() {
slaveLooper.exitLoop();
globalValue = 10;
}
};
slaveLooper.addTasksOnWakeup(r);
slaveLooper.loop();
Assert.assertEquals(10, globalValue);
}
/**
* Method: registerTimerEventInSeconds(long timerInSeconds, Runnable task)
*/
@Test
public void testRegisterTimerEventInSeconds() throws Exception {
Runnable r = new Runnable() {
@Override
public void run() {
slaveLooper.exitLoop();
globalValue = 10;
}
};
long startTime = System.nanoTime();
Duration interval = Duration.ofSeconds(1);
slaveLooper.registerTimerEvent(interval, r);
slaveLooper.loop();
long endTime = System.nanoTime();
Assert.assertTrue(endTime - startTime - interval.toNanos() >= 0);
Assert.assertEquals(10, globalValue);
}
/**
* Method: registerTimerEventInNanoSeconds(long timerInNanoSecnods, Runnable task)
*/
@Test
public void testRegisterTimerEventInNanoSeconds() throws Exception {
Runnable r = new Runnable() {
@Override
public void run() {
slaveLooper.exitLoop();
globalValue = 10;
}
};
long startTime = System.nanoTime();
Duration interval = Duration.ofMillis(6);
slaveLooper.registerTimerEvent(interval, r);
slaveLooper.loop();
long endTime = System.nanoTime();
Assert.assertTrue(endTime - startTime - interval.toNanos() >= 0);
Assert.assertEquals(10, globalValue);
}
/**
* Method: exitLoop()
*/
@Test
public void testExitLoop() throws Exception {
Runnable r = new Runnable() {
@Override
public void run() {
slaveLooper.exitLoop();
globalValue = 10;
}
};
slaveLooper.addTasksOnWakeup(r);
slaveLooper.loop();
Assert.assertEquals(10, globalValue);
}
/**
* Method: getNextTimeoutInterval()
*/
@Test
public void testGetNextTimeoutIntervalMs() throws Exception {
Runnable r = new Runnable() {
@Override
public void run() {
slaveLooper.exitLoop();
globalValue = 10;
}
};
Duration interval = Duration.ofSeconds(6);
slaveLooper.registerTimerEvent(interval, r);
Duration res = Duration.ofNanos(1000);
try {
Method method =
slaveLooper.getClass().getSuperclass().getDeclaredMethod("getNextTimeoutInterval");
method.setAccessible(true);
res = (Duration) method.invoke(slaveLooper);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
Assert.assertNotNull(res);
Assert.assertTrue(res.compareTo(interval) <= 0 && res.compareTo(interval.dividedBy(2)) > 0);
}
/**
* Method: runOnce()
*/
@Test
public void testRunOnce() throws Exception {
Runnable r = new Runnable() {
@Override
public void run() {
globalValue = 10;
}
};
slaveLooper.addTasksOnWakeup(r);
try {
Method method = slaveLooper.getClass().getSuperclass().getDeclaredMethod("runOnce");
method.setAccessible(true);
method.invoke(slaveLooper);
} catch (NoSuchMethodException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
Assert.assertEquals(10, globalValue);
}
/**
* Method: executeTasksOnWakeup()
*/
@Test
public void testExecuteTasksOnWakeup() throws Exception {
Runnable r = new Runnable() {
@Override
public void run() {
globalValue = 10;
}
};
slaveLooper.addTasksOnWakeup(r);
try {
Method method =
slaveLooper.getClass().getSuperclass().getDeclaredMethod("executeTasksOnWakeup");
method.setAccessible(true);
method.invoke(slaveLooper);
} catch (NoSuchMethodException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
Assert.assertEquals(10, globalValue);
}
/**
* Method: triggerExpiredTimers(long currentTime)
*/
@Test
public void testTriggerExpiredTimers() throws Exception {
Runnable r = new Runnable() {
@Override
public void run() {
globalValue = 10;
}
};
Duration interval = Duration.ofNanos(1);
slaveLooper.registerTimerEvent(interval, r);
try {
Method method =
slaveLooper.getClass().getSuperclass().getDeclaredMethod(
"triggerExpiredTimers", long.class);
long current = System.nanoTime();
method.setAccessible(true);
method.invoke(slaveLooper, current);
} catch (NoSuchMethodException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
Assert.assertEquals(10, globalValue);
}
}