/*
* Copyright (C) 2011. All rights reserved.
*/
package ro.isdc.wro.util;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.verify;
import static org.mockito.MockitoAnnotations.initMocks;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ro.isdc.wro.config.Context;
/**
* @author Alex Objelean
*/
public class TestSchedulerHelper {
private static final Logger LOG = LoggerFactory.getLogger(TestSchedulerHelper.class);
@Mock
private Runnable mockRunnable;
private SchedulerHelper helper;
@BeforeClass
public static void onBeforeClass() {
assertEquals(0, Context.countActive());
}
@AfterClass
public static void onAfterClass() {
assertEquals(0, Context.countActive());
}
@Before
public void setUp() {
initMocks(this);
}
@Test(expected = NullPointerException.class)
public void cannotAcceptNullArgument() {
SchedulerHelper.create(null);
}
@Test(expected = NullPointerException.class)
public void cannotAcceptNullRunnable() {
useNullRunnableWithPeriod(1);
}
@Test
public void canAcceptNullRunnableWhenPeriodIsZero() {
useNullRunnableWithPeriod(0);
}
@Test
public void runnableNotStartedWhenPeriodIsZero() {
createAndRunHelperForTest(createSleepingRunnable(1000), 0, TimeUnit.SECONDS);
}
@Test
public void runLongRunningThread()
throws Exception {
createAndRunHelperForTest(createSleepingRunnable(100), 100, TimeUnit.MILLISECONDS);
Thread.sleep(400);
}
@Test
public void scheduleWithDifferentPeriods()
throws Exception {
helper = SchedulerHelper.create(new DestroyableLazyInitializer<Runnable>() {
@Override
protected Runnable initialize() {
return createSleepingRunnable(10);
}
});
helper.scheduleWithPeriod(10);
Assert.assertEquals(10, helper.getPeriod());
Thread.sleep(20);
helper.scheduleWithPeriod(20);
Assert.assertEquals(20, helper.getPeriod());
Thread.sleep(40);
}
@Test
public void scheduleWithSamePeriods()
throws Exception {
helper = SchedulerHelper.create(new DestroyableLazyInitializer<Runnable>() {
@Override
protected Runnable initialize() {
return createSleepingRunnable(10);
}
});
helper.scheduleWithPeriod(10);
Assert.assertEquals(10, helper.getPeriod());
Thread.sleep(20);
helper.scheduleWithPeriod(10);
Assert.assertEquals(10, helper.getPeriod());
Thread.sleep(30);
}
@Test
public void schedulerHelperIsSynchronized()
throws Exception {
helper = SchedulerHelper.create(new DestroyableLazyInitializer<Runnable>() {
@Override
protected Runnable initialize() {
return new Runnable() {
public void run() {
try {
LOG.debug("\tRunning thread ...");
Thread.sleep(40);
} catch (final Exception e) {
LOG.error("runnable interrupted", e);
}
}
};
}
});
final ThreadLocal<Long> period = new InheritableThreadLocal<Long>() {
@Override
protected Long initialValue() {
return 0l;
}
};
final ExecutorService service = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
period.set(period.get() + 30);
// Thread.sleep(300);
service.execute(new Runnable() {
public void run() {
helper.scheduleWithPeriod(period.get(), TimeUnit.MILLISECONDS);
}
});
}
Thread.sleep(400);
helper.destroy();
service.shutdown();
}
/**
* creates a runnable which sleeps for a given period of time.
*
* @param period
* number of milliseconds to sleep.
*/
private Runnable createSleepingRunnable(final long period) {
return new Runnable() {
public void run() {
try {
Thread.sleep(period);
} catch (final Exception e) {
LOG.error("thread interrupted", e);
}
}
};
}
private void useNullRunnableWithPeriod(final long period) {
createAndRunHelperForTest(null, period, TimeUnit.SECONDS);
}
private void createAndRunHelperForTest(final Runnable runnable, final long period, final TimeUnit timeUnit) {
helper = SchedulerHelper.create(new DestroyableLazyInitializer<Runnable>() {
@Override
protected Runnable initialize() {
return runnable;
}
});
helper.scheduleWithPeriod(period, timeUnit);
}
@Test
public void shouldNotInvokeRunnableImmediatelyAfterScheduleIsInvoked()
throws Exception {
helper = SchedulerHelper.create(new DestroyableLazyInitializer<Runnable>() {
@Override
protected Runnable initialize() {
return mockRunnable;
}
});
helper.scheduleWithPeriod(7200);
Thread.sleep(10);
verify(mockRunnable, Mockito.never()).run();
}
@After
public void tearDown() {
Context.unset();
if (helper != null) {
helper.destroy();
}
}
}