001: /*
002: * The contents of this file are subject to the Sapient Public License
003: * Version 1.0 (the "License"); you may not use this file except in compliance
004: * with the License. You may obtain a copy of the License at
005: * http://carbon.sf.net/License.html.
006: *
007: * Software distributed under the License is distributed on an "AS IS" basis,
008: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
009: * the specific language governing rights and limitations under the License.
010: *
011: * The Original Code is The Carbon Component Framework.
012: *
013: * The Initial Developer of the Original Code is Sapient Corporation
014: *
015: * Copyright (C) 2003 Sapient Corporation. All Rights Reserved.
016: */
017:
018: package org.sape.carbon.services.scheduler.test;
019:
020: import org.sape.carbon.core.component.Component;
021: import org.sape.carbon.core.component.FunctionalInterface;
022: import org.sape.carbon.core.component.Lookup;
023: import org.sape.carbon.core.component.lifecycle.StateTransitionException;
024: import org.sape.carbon.core.config.Config;
025: import org.sape.carbon.core.config.interceptor.ConfigurationInterceptor;
026: import org.sape.carbon.core.util.calendar.DayOfWeekEnum;
027: import org.sape.carbon.core.util.calendar.MonthEnum;
028: import org.sape.carbon.services.scheduler.FixedDelayTaskConfiguration;
029: import org.sape.carbon.services.scheduler.FixedRateTaskConfiguration;
030: import org.sape.carbon.services.scheduler.SchedulerServiceConfiguration;
031: import org.sape.carbon.services.threadpool.ThreadPool;
032:
033: import junit.extensions.ActiveTestSuite;
034: import junit.framework.Test;
035: import junit.framework.TestCase;
036: import junit.framework.TestSuite;
037:
038: /**
039: * Template for junit test harness. Change this description to reflect what this class is testing.
040: *
041: * <br>Copyright 2002 Sapient
042: *
043: * @since carbon 1.0
044: * @author Douglas Voet, March 2002
045: * @version $Revision: 1.11 $($Author: dvoet $ / $Date: 2003/11/20 21:46:15 $)
046: */
047: public class SchedulerServiceTest extends TestCase implements
048: SchedulerServiceTestListener {
049:
050: private int count = 0;
051: private int secondaryCount = 0;
052: private int lastCount = 0;
053:
054: /**
055: * @see SchedulerServiceTestListener#incrementCount()
056: */
057: public synchronized void incrementCount() {
058: count++;
059: notify();
060: }
061:
062: public synchronized void incrementSecondaryCount() {
063: secondaryCount++;
064: notify();
065: }
066:
067: public SchedulerServiceTest(String name) {
068: super (name);
069: }
070:
071: public void testFixedRateTask() throws InterruptedException {
072: SchedulableComponent component = (SchedulableComponent) Lookup
073: .getInstance().fetchComponent(SCHEDULABLE_SERVICE_NAME);
074:
075: component.setListener(this );
076:
077: setFixedRateTask(null, null, null, null, null, component, null);
078:
079: synchronized (this ) {
080: this .lastCount = this .count;
081: // wait for 2 minutes max
082: wait(120000);
083: if (this .count == this .lastCount) {
084: TestCase
085: .fail("Waited 2 minutes and scheduled task was not executed: "
086: + "last call count ["
087: + this .lastCount
088: + "] current call count [ "
089: + this .count
090: + "] expected current count != last count");
091: }
092: }
093:
094: Lookup.getInstance().getComponentKeeper().destroyComponent(
095: TEST_SCHEDULER_SERVICE_NAME);
096: }
097:
098: public void testReflectionBasedFixedRateTask()
099: throws InterruptedException {
100: SchedulableComponent component = (SchedulableComponent) Lookup
101: .getInstance().fetchComponent(SCHEDULABLE_SERVICE_NAME);
102:
103: component.setListener(this );
104:
105: setFixedRateTask(null, null, null, null, null, component,
106: "doSpecializeTask");
107:
108: synchronized (this ) {
109: this .lastCount = this .secondaryCount;
110: // wait for 2 minutes max
111: wait(120000);
112: assertTrue(
113: "Waited 2 minutes and scheduled task was not executed: "
114: + "last call count [" + this .lastCount
115: + "] current call count [ "
116: + this .secondaryCount
117: + "] expected current count != last count",
118: this .secondaryCount != this .lastCount);
119:
120: }
121:
122: Lookup.getInstance().getComponentKeeper().destroyComponent(
123: TEST_SCHEDULER_SERVICE_NAME);
124: }
125:
126: public void testSchedulerWithThreadPool()
127: throws InterruptedException {
128: Component scheduler = Lookup.getInstance().fetchComponent(
129: TEST_SCHEDULER_SERVICE_NAME);
130:
131: ThreadPool threadPool = (ThreadPool) Lookup.getInstance()
132: .fetchComponent(THREAD_POOL);
133:
134: assertTrue("Thread pool was not empty at start of test",
135: threadPool.getPoolSize().equals(new Integer(0)));
136:
137: ((SchedulerServiceConfiguration) scheduler)
138: .setThreadPool(threadPool);
139: ((ConfigurationInterceptor) scheduler).applyConfiguration();
140:
141: SchedulableComponent component = (SchedulableComponent) Lookup
142: .getInstance().fetchComponent(SCHEDULABLE_SERVICE_NAME);
143:
144: component.setListener(this );
145:
146: setFixedRateTask(null, null, null, null, null, component, null);
147:
148: synchronized (this ) {
149: this .lastCount = this .count;
150: // wait for 2 minutes max
151: wait(120000);
152: if (this .count == this .lastCount) {
153: TestCase
154: .fail("Waited 2 minutes and scheduled task was not executed: "
155: + "last call count ["
156: + this .lastCount
157: + "] current call count [ "
158: + this .count
159: + "] expected current count != last count");
160: }
161:
162: assertTrue("task was not executed on thread pool",
163: threadPool.getPoolSize().equals(new Integer(1)));
164: }
165:
166: Lookup.getInstance().getComponentKeeper().destroyComponent(
167: TEST_SCHEDULER_SERVICE_NAME);
168: }
169:
170: public void testFixedDelayTask() throws InterruptedException {
171: SchedulableComponent component = (SchedulableComponent) Lookup
172: .getInstance().fetchComponent(SCHEDULABLE_SERVICE_NAME);
173:
174: component.setListener(this );
175:
176: setFixedDelayTask(0, 500, component, null);
177:
178: synchronized (this ) {
179: this .lastCount = this .count;
180: // wait for 1 sec max
181: wait(1000);
182: if (this .count == this .lastCount) {
183: TestCase
184: .fail("Waited 1 second and scheduled task was not executed: "
185: + "last call count ["
186: + this .lastCount
187: + "] current call count [ "
188: + this .count
189: + "] expected current count != last count");
190: }
191: }
192:
193: Lookup.getInstance().getComponentKeeper().destroyComponent(
194: TEST_SCHEDULER_SERVICE_NAME);
195: }
196:
197: public void testInvalidConfigurations() {
198: SchedulableComponent component = (SchedulableComponent) Lookup
199: .getInstance().fetchComponent(SCHEDULABLE_SERVICE_NAME);
200:
201: testInvalidFixedRateTask(new Integer(0), null, null, null,
202: null, null, null);
203:
204: testInvalidFixedRateTask(null, new Integer(0), null, null,
205: null, component, null);
206:
207: testInvalidFixedRateTask(new Integer(0), null, new Integer(0),
208: null, null, component, null);
209:
210: testInvalidFixedRateTask(new Integer(0), new Integer(0), null,
211: MonthEnum.JANUARY, null, component, null);
212:
213: testInvalidFixedRateTask(new Integer(0), new Integer(0),
214: new Integer(1), null, DayOfWeekEnum.MONDAY, component,
215: null);
216:
217: testInvalidFixedRateTask(new Integer(0), new Integer(0), null,
218: MonthEnum.JANUARY, DayOfWeekEnum.MONDAY, component,
219: null);
220:
221: testInvalidFixedRateTask(null, null, null, null, null,
222: component, "nonExistantMethod");
223:
224: testInvalidFixedDelayTask(-1, 100, component);
225: testInvalidFixedDelayTask(0, -1, component);
226: }
227:
228: public void testRecoverableExceptions() throws InterruptedException {
229: SchedulableComponent component = (SchedulableComponent) Lookup
230: .getInstance()
231: .fetchComponent(
232: SchedulerServiceTest.RECOVERABLE_SCHEDULABLE_SERVICE_NAME);
233:
234: component.setListener(this );
235:
236: setFixedDelayTask(0, 500, component, null);
237:
238: synchronized (this ) {
239: this .lastCount = this .count;
240: // wait twice for 1 sec to make sure that the task runs more than
241: // once
242: wait(1000);
243: wait(1000);
244: if (this .count <= this .lastCount + 1) {
245: TestCase
246: .fail("Recoverable exception caused timer to stop: "
247: + "last call count ["
248: + this .lastCount
249: + "] current call count [ "
250: + this .count
251: + "] expected <= last count + 1");
252: }
253: }
254:
255: Lookup.getInstance().getComponentKeeper().destroyComponent(
256: TEST_SCHEDULER_SERVICE_NAME);
257: }
258:
259: public void testUnrecoverableExceptions()
260: throws InterruptedException {
261: SchedulableComponent component = (SchedulableComponent) Lookup
262: .getInstance()
263: .fetchComponent(
264: SchedulerServiceTest.UNRECOVERABLE_SCHEDULABLE_SERVICE_NAME);
265:
266: component.setListener(this );
267:
268: setFixedDelayTask(0, 500, component, null);
269:
270: synchronized (this ) {
271: this .lastCount = this .count;
272: // wait twice for 1 sec to make sure that the task could run more
273: // than once (if it does, it is a failure)
274: wait(1000);
275: wait(1000);
276: if (this .count != this .lastCount + 1) {
277: TestCase
278: .fail("Unrecoverable exception did not caused task to be canceled: "
279: + "last call count ["
280: + this .lastCount
281: + "] current call count [ "
282: + this .count
283: + "] expected current count == last count + 1");
284: }
285: }
286:
287: Lookup.getInstance().getComponentKeeper().destroyComponent(
288: TEST_SCHEDULER_SERVICE_NAME);
289: }
290:
291: private void testInvalidFixedRateTask(Integer minute, Integer hour,
292: Integer dayOfMonth, MonthEnum month,
293: DayOfWeekEnum dayOfWeek, FunctionalInterface component,
294: String method) {
295:
296: try {
297: setFixedRateTask(minute, hour, dayOfMonth, month,
298: dayOfWeek, component, method);
299: fail("Did not catch expected StateTransitionException for "
300: + "configuration values: Minute [" + minute
301: + "], Hour [" + hour + "], DayOfMonth ["
302: + dayOfMonth + "], Month [" + month
303: + "], DayOfWeek [" + dayOfWeek
304: + "], SchedulableComponent [" + component + "]");
305:
306: } catch (StateTransitionException ste) {
307: // expected
308: }
309:
310: }
311:
312: private void testInvalidFixedDelayTask(long delay, long period,
313: FunctionalInterface component) {
314:
315: try {
316: setFixedDelayTask(delay, period, component, null);
317: fail("Did catch expected StateTransitionException for "
318: + "configuration values: InitialDelay [" + delay
319: + "], Period [" + period
320: + "], SchedulableComponent [" + component + "]");
321:
322: } catch (StateTransitionException ste) {
323: // expected
324: }
325:
326: }
327:
328: private void setFixedRateTask(Integer minute, Integer hour,
329: Integer dayOfMonth, MonthEnum month,
330: DayOfWeekEnum dayOfWeek, FunctionalInterface component,
331: String methodName) {
332:
333: Component scheduler = Lookup.getInstance().fetchComponent(
334: TEST_SCHEDULER_SERVICE_NAME);
335:
336: FixedRateTaskConfiguration newConfig = (FixedRateTaskConfiguration) Config
337: .getInstance().createConfiguration(
338: FixedRateTaskConfiguration.class);
339: newConfig
340: .setSchedulableComponent((FunctionalInterface) component);
341:
342: newConfig.setMinute(minute);
343: newConfig.setHour(hour);
344: newConfig.setDayOfMonth(dayOfMonth);
345: newConfig.setMonth(month);
346: newConfig.setDayOfWeek(dayOfWeek);
347: if (methodName != null)
348: newConfig.setScheduledMethod(methodName);
349:
350: ((SchedulerServiceConfiguration) scheduler)
351: .setFixedRateTask(new FixedRateTaskConfiguration[] { newConfig });
352: ((SchedulerServiceConfiguration) scheduler)
353: .setFixedDelayTask(null);
354: ((ConfigurationInterceptor) scheduler).applyConfiguration();
355: }
356:
357: private void setFixedDelayTask(long delay, long period,
358: FunctionalInterface component, String methodName) {
359:
360: Component scheduler = Lookup.getInstance().fetchComponent(
361: TEST_SCHEDULER_SERVICE_NAME);
362:
363: FixedDelayTaskConfiguration newConfig = (FixedDelayTaskConfiguration) Config
364: .getInstance().createConfiguration(
365: FixedDelayTaskConfiguration.class);
366: newConfig
367: .setSchedulableComponent((FunctionalInterface) component);
368:
369: if (methodName != null)
370: newConfig.setScheduledMethod(methodName);
371:
372: newConfig.setInitialDelay(delay);
373: newConfig.setPeriod(period);
374:
375: ((SchedulerServiceConfiguration) scheduler)
376: .setFixedRateTask(null);
377: ((SchedulerServiceConfiguration) scheduler)
378: .setFixedDelayTask(new FixedDelayTaskConfiguration[] { newConfig });
379: ((ConfigurationInterceptor) scheduler).applyConfiguration();
380: }
381:
382: /*
383: * write your test methods here following these examples:
384: *
385: * public void testFunction1() {
386: * test something
387: * }
388: *
389: * public void testFunction2() {
390: * test something else
391: * }
392: */
393:
394: private static final String SCHEDULABLE_SERVICE_NAME = "/scheduler/test/TestSchedulableComponent";
395: private static final String UNRECOVERABLE_SCHEDULABLE_SERVICE_NAME = "/scheduler/test/TestUnrecoverableSchedulableComponent";
396: private static final String RECOVERABLE_SCHEDULABLE_SERVICE_NAME = "/scheduler/test/TestRecoverableSchedulableComponent";
397: private static final String TEST_SCHEDULER_SERVICE_NAME = "/scheduler/test/TestScheduler";
398: private static final String THREAD_POOL = "/scheduler/test/SchedulerThreadPool";
399:
400: /**
401: * Method called by jUnit to get all the tests in this test case.
402: * @return Test the suite of tests in this test case
403: */
404: public static Test suite() {
405: TestSuite masterSuite = new TestSuite();
406: // add single threaded tests
407: Test singleThreadedTests = getSingleThreadedTests();
408: if (singleThreadedTests != null) {
409: masterSuite.addTest(singleThreadedTests);
410: }
411: // add multi threaded tests
412: Test multiThreadedTests = getMultiThreadedTests();
413: if (multiThreadedTests != null) {
414: masterSuite.addTest(multiThreadedTests);
415: }
416: return masterSuite;
417: }
418:
419: /**
420: * This method is used within the suite method to get all of the single threaded tests.
421: * Add all your single threaded tests in this method with a line like:
422: * suite.addTest(new SchedulerServiceTest("testFunction1"));
423: * @return Test the suite of single threaded tests in this test case
424: */
425: private static Test getSingleThreadedTests() {
426: TestSuite suite = new TestSuite();
427:
428: suite.addTest(new SchedulerServiceTest("testFixedRateTask"));
429: suite.addTest(new SchedulerServiceTest(
430: "testReflectionBasedFixedRateTask"));
431: suite.addTest(new SchedulerServiceTest(
432: "testSchedulerWithThreadPool"));
433: suite.addTest(new SchedulerServiceTest("testFixedDelayTask"));
434: suite.addTest(new SchedulerServiceTest(
435: "testRecoverableExceptions"));
436: suite.addTest(new SchedulerServiceTest(
437: "testUnrecoverableExceptions"));
438: suite.addTest(new SchedulerServiceTest(
439: "testInvalidConfigurations"));
440:
441: return suite;
442: }
443:
444: /**
445: * This method is used within the suite method to get all of the multi threaded tests.
446: * Add all your multi threaded tests in this method with a line like: addTest(suite, "testFunction1", 5);
447: * @return Test the suite of multi-threaded tests in this test case
448: */
449: private static Test getMultiThreadedTests() {
450: TestSuite suite = new ActiveTestSuite();
451:
452: /*
453: * add your tests here following these examples:
454: *
455: * addTest(suite, "testFunction1", 5);
456: * addTest(suite, "testFunction2", 10);
457: */
458:
459: return suite;
460: }
461:
462: /**
463: * This method will add the give test to the give suite the specified
464: * number of times. This is best used for multi-threaded tests where
465: * suite is an instance of ActiveTestSuite and you want to run the same test in multiple threads.
466: * @param suite the suite to add the test to.
467: * @param testName the name of the test to add.
468: * @param number the number of times to add the test to the suite
469: */
470: private static void addTest(TestSuite suite, String testName,
471: int number) {
472: for (int count = 0; count < number; count++) {
473: suite.addTest(new SchedulerServiceTest(testName));
474: }
475: }
476: }
|