/* * NOTE: This copyright does *not* cover user programs that use HQ * program services by normal system calls through the application * program interfaces provided as part of the Hyperic Plug-in Development * Kit or the Hyperic Client Development Kit - this is merely considered * normal use of the program, and does *not* fall under the heading of * "derived work". * * Copyright (C) [2004-2008], Hyperic, Inc. * This file is part of HQ. * * HQ is free software; you can redistribute it and/or modify * it under the terms version 2 of the GNU General Public License as * published by the Free Software Foundation. This program is distributed * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. */ package org.hyperic.hq.application; import java.util.concurrent.ScheduledFuture; import org.hyperic.util.SpinBarrier; import org.hyperic.util.SpinBarrierCondition; import junit.framework.TestCase; /** * Tests the Scheduler class. */ public class SchedulerTest extends TestCase { private Scheduler scheduler; public void tearDown() throws Exception{ super.tearDown(); if(this.scheduler != null) { this.scheduler.shutdown(); } } public void testIllegalPoolSize() { try { new Scheduler(-1); fail("Expected IllegalArgumentException."); } catch (IllegalArgumentException e) { // expected outcome } catch (Exception e) { fail("Expected IllegalArgumentException instead of:"+e); } try { new Scheduler(0); fail("Expected IllegalArgumentException."); } catch (IllegalArgumentException e) { // expected outcome } catch (Exception e) { fail("Expected IllegalArgumentException instead of:"+e); } } public void testExecuteAtFixedRate() throws Exception { this.scheduler = new Scheduler(1); final RunnableCounter counter = new RunnableCounter(50, false); ScheduledFuture future = scheduler.scheduleAtFixedRate(counter, Scheduler.NO_INITIAL_DELAY, 100); final SpinBarrier counterUpdated = new SpinBarrier(new SpinBarrierCondition() { public boolean evaluate() { return counter.numRuns() >= 2; } }); assertTrue(counterUpdated.waitFor()); assertFalse(future.isDone()); assertFalse(future.isCancelled()); } public void testExecuteWithFixedDelay() throws Exception { this.scheduler = new Scheduler(1); final RunnableCounter counter = new RunnableCounter(100, false); // the execution period is about 200 msec (delay+runtime) ScheduledFuture future = scheduler.scheduleWithFixedDelay(counter, Scheduler.NO_INITIAL_DELAY, 100); final SpinBarrier counterUpdated = new SpinBarrier(new SpinBarrierCondition() { public boolean evaluate() { return counter.numRuns() >= 2; } }); assertTrue(counterUpdated.waitFor()); assertFalse(future.isDone()); assertFalse(future.isCancelled()); } public void testCancellingScheduledTask() throws Exception { this.scheduler = new Scheduler(1); final RunnableCounter counter = new RunnableCounter(50, false); ScheduledFuture future = scheduler.scheduleAtFixedRate(counter, Scheduler.NO_INITIAL_DELAY, 100); SpinBarrier counterUpdated = new SpinBarrier(new SpinBarrierCondition() { public boolean evaluate() { return counter.numRuns() >= 2; } }); assertTrue(counterUpdated.waitFor()); assertFalse(future.isDone()); assertFalse(future.isCancelled()); future.cancel(true); assertTrue(future.isDone()); assertTrue(future.isCancelled()); } public void testExecuteAtFixedRateWithInitialDelay() throws Exception { this.scheduler = new Scheduler(1); final RunnableCounter counter = new RunnableCounter(50, false); ScheduledFuture future = scheduler.scheduleAtFixedRate(counter, 100, 100); final SpinBarrier counterUpdated = new SpinBarrier(new SpinBarrierCondition() { public boolean evaluate() { return counter.numRuns() >= 2; } }); assertTrue(counterUpdated.waitFor()); assertFalse(future.isDone()); assertFalse(future.isCancelled()); } public void testExecuteWithFixedDelayWithInitialDelay() throws Exception { this.scheduler = new Scheduler(1); final RunnableCounter counter = new RunnableCounter(50, false); ScheduledFuture future = scheduler.scheduleWithFixedDelay(counter, 100, 50); final SpinBarrier counterUpdated = new SpinBarrier(new SpinBarrierCondition() { public boolean evaluate() { return counter.numRuns() >= 2; } }); assertTrue(counterUpdated.waitFor()); assertFalse(future.isDone()); assertFalse(future.isCancelled()); } /** * Test executing one task at a fixed rate and one task with a fixed delay. * * @throws Exception */ public void testExecuteConcurrentTasks() throws Exception { this.scheduler = new Scheduler(2); final RunnableCounter counter1 = new RunnableCounter(10, false); final RunnableCounter counter2 = new RunnableCounter(10, false); ScheduledFuture future1 = scheduler.scheduleAtFixedRate(counter1, Scheduler.NO_INITIAL_DELAY, 50); // the execution period is about 60 msec (delay+runtime) ScheduledFuture future2 = scheduler.scheduleWithFixedDelay(counter2, Scheduler.NO_INITIAL_DELAY, 50); final SpinBarrier counterUpdated = new SpinBarrier(new SpinBarrierCondition() { public boolean evaluate() { return ((counter1.numRuns() >= 5) && (counter2.numRuns() >= 4)); } }); assertTrue(counterUpdated.waitFor()); assertFalse(future1.isDone()); assertFalse(future1.isCancelled()); assertFalse(future2.isDone()); assertFalse(future2.isCancelled()); } /** * Test that a scheduled task will stop executing if it throws an * unchecked exception. */ public void testUncheckedExceptionInTask() throws Exception { this.scheduler = new Scheduler(1); final RunnableCounter counter = new RunnableCounter(50, true); final ScheduledFuture future = scheduler.scheduleAtFixedRate(counter, Scheduler.NO_INITIAL_DELAY, 100); final SpinBarrier counterUpdated = new SpinBarrier(new SpinBarrierCondition() { public boolean evaluate() { // only should have run once since a runtime exception was thrown return ((counter.numRuns() == 1) && (future.isDone()) && !(future.isCancelled())); } }); assertTrue(counterUpdated.waitFor()); } private class RunnableCounter implements Runnable { private final long _sleepTime; private int _numRuns; private final boolean _throwException; private final Object _lock = new Object(); public RunnableCounter(long sleepTime, boolean throwUncheckedException) { _sleepTime = sleepTime; _throwException = throwUncheckedException; } public void run() { synchronized (this) { _numRuns++; } try { Thread.sleep(_sleepTime); } catch (InterruptedException e) { } if (_throwException) { throw new RuntimeException("unchecked exception"); } } public synchronized int numRuns() { return _numRuns; } } }