package org.radargun.stages.test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.testng.PowerMockTestCase;
import org.radargun.logging.Log;
import org.radargun.logging.LogFactory;
import org.radargun.utils.TimeService;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
/**
* @author Radim Vansa <rvansa@redhat.com>
*/
@Test
@PowerMockIgnore({"javax.management.*"})
@PrepareForTest(TimeService.class)
public class SchedulingSelectorTest extends PowerMockTestCase {
private static Log log = LogFactory.getLog(SchedulingSelectorTest.class);
private ExecutorService executorService = Executors.newFixedThreadPool(1);
@Test
public void test() throws InterruptedException {
PowerMockito.mockStatic(TimeService.class);
setTime(0);
SchedulingSelector<String> selector = new SchedulingSelector.Builder<>(String.class)
.add("a", 2, 5L)
.add("b", 3, 3L)
.build();
checkReturns(selector, "a", "a", "b", "b", "b");
checkBlocks(selector);
setTime(1);
checkBlocks(selector);
setTime(2);
checkBlocks(selector);
setTime(3);
checkReturns(selector, "b", "b", "b");
checkBlocks(selector);
setTime(4);
checkBlocks(selector);
setTime(5);
checkReturns(selector, "a", "a");
checkBlocks(selector);
setTime(6);
checkReturns(selector, "b", "b", "b");
checkBlocks(selector);
setTime(7);
checkBlocks(selector);
setTime(8);
checkBlocks(selector);
setTime(9);
checkReturns(selector, "b", "b", "b");
setTime(10);
checkReturns(selector, "a", "a");
checkBlocks(selector);
setTime(11);
checkBlocks(selector);
setTime(12);
checkReturns(selector, "b", "b", "b");
checkBlocks(selector);
setTime(13);
checkBlocks(selector);
setTime(14);
checkBlocks(selector);
setTime(15);
checkReturns(selector, "a", "a", "b", "b", "b");
checkBlocks(selector);
}
protected void setTime(long value) {
PowerMockito.when(TimeService.currentTimeMillis()).thenReturn(value);
}
protected void checkReturns(SchedulingSelector<String> selector, String... expected) throws InterruptedException {
List<String> retvals = Collections.synchronizedList(new ArrayList<>());
CountDownLatch latch = new CountDownLatch(1);
executorService.execute(() -> {
for (int i = 0; i < expected.length; ++i) {
try {
String next = selector.next();
retvals.add(next);
} catch (InterruptedException e) {
log.error("Unexpected interruption", e);
break;
}
}
latch.countDown();
});
assertTrue(latch.await(10, TimeUnit.SECONDS));
assertEquals(retvals.size(), expected.length);
Collections.sort(retvals);
assertEquals(retvals, Arrays.asList(expected));
}
protected void checkBlocks(SchedulingSelector<String> selector) throws InterruptedException {
Future<?> task = executorService.submit(() -> {
try {
selector.next();
} catch (InterruptedException e) {
log.trace("Expected interruption", e);
}
});
try {
task.get(100, TimeUnit.MILLISECONDS);
fail("Unexpected return");
} catch (ExecutionException e) {
fail("Unexpected exception", e);
} catch (TimeoutException e) {
task.cancel(true);
}
}
}