/* * 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(); } } }