From e5b7380c874745c989d1816b8f552504f038e1bc Mon Sep 17 00:00:00 2001 From: lresende Date: Thu, 26 Sep 2013 20:33:20 +0000 Subject: 2.0 branch for possible maintenance release git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1526672 13f79535-47bb-0310-9956-ffa450edef68 --- .../tuscany/sca/core/work/impl/FailingWork.java | 54 +++++ .../core/work/impl/JSR237MyFailingRunnable.java | 43 ++++ .../sca/core/work/impl/JSR237MyRunnable.java | 71 ++++++ .../sca/core/work/impl/JSR237MyRunnerListener.java | 154 +++++++++++++ .../work/impl/Jsr237WorkSchedulerTestCase.java | 240 +++++++++++++++++++++ .../sca/core/work/impl/TestWorkListener.java | 153 +++++++++++++ .../work/impl/ThreadPoolWorkManagerTestCase.java | 227 +++++++++++++++++++ .../tuscany/sca/core/work/impl/TimeDelayWork.java | 86 ++++++++ 8 files changed, 1028 insertions(+) create mode 100644 sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/FailingWork.java create mode 100644 sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyFailingRunnable.java create mode 100644 sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnable.java create mode 100644 sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnerListener.java create mode 100644 sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/Jsr237WorkSchedulerTestCase.java create mode 100644 sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TestWorkListener.java create mode 100644 sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManagerTestCase.java create mode 100644 sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TimeDelayWork.java (limited to 'sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work') diff --git a/sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/FailingWork.java b/sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/FailingWork.java new file mode 100644 index 0000000000..16ca5fd00e --- /dev/null +++ b/sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/FailingWork.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.work.impl; + + + +/** + * Simple Work item that will throw an exception + * + * @version $Rev$ $Date$ + */ +public class FailingWork extends Work { + + public FailingWork() { + super(null); + } + + /** + * {@inheritDoc} + */ + public boolean isDaemon() { + return false; + } + + /** + * {@inheritDoc} + */ + public void release() { + } + + /** + * Throws an IllegalArgumentException + */ + public void run() { + System.out.println("Starting " + this + " and throwing an Exception"); + throw new IllegalArgumentException("Sample exception from " + this); + } +} diff --git a/sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyFailingRunnable.java b/sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyFailingRunnable.java new file mode 100644 index 0000000000..2d791e5012 --- /dev/null +++ b/sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyFailingRunnable.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.work.impl; + +/** + * Simple Runnable that throws an IllegalArgumentException + * + * @version $Rev$ $Date$ + */ +public class JSR237MyFailingRunnable extends JSR237MyRunnable { + + /** + * Constructor + */ + public JSR237MyFailingRunnable() { + super(-1); + } + + /** + * Sleeps for a period of time defined by sleepTime + */ + @Override + public void run() { + System.out.println("Starting " + this + " and throwing an Exception"); + throw new IllegalArgumentException("Sample exception from " + this); + } +} diff --git a/sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnable.java b/sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnable.java new file mode 100644 index 0000000000..c0183b6f9b --- /dev/null +++ b/sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnable.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.work.impl; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Simple Runnable that is used for testing Jsr237WorkScheduler + * + * @version $Rev$ $Date$ + */ +public class JSR237MyRunnable implements Runnable { + + /** + * Count of workAccepted() method calls + */ + private AtomicInteger runCompletedCount = new AtomicInteger(); + + /** + * The amount of time to sleep in the Run loop + */ + private final long sleepTime; + + /** + * Constructor + * + * @param sleepTime The amount of time to sleep (in milliseconds) in the run() method + */ + public JSR237MyRunnable(long sleepTime) { + this.sleepTime = sleepTime; + } + + /** + * Sleeps for a period of time defined by sleepTime + */ + public void run() { + System.out.println("Starting " + this); + try { + Thread.sleep(sleepTime); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("Done " + this); + runCompletedCount.incrementAndGet(); + } + + /** + * Returns the number of completed calls to run() + * + * @return The number of completed calls to run() + */ + public int getRunCompletedCount() { + return runCompletedCount.get(); + } +} diff --git a/sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnerListener.java b/sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnerListener.java new file mode 100644 index 0000000000..307f24aca7 --- /dev/null +++ b/sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnerListener.java @@ -0,0 +1,154 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.work.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.tuscany.sca.work.NotificationListener; + +/** + * Simple NotificationListener that is used for testing Jsr237WorkScheduler + * + * @version $Rev$ $Date$ + */ +public class JSR237MyRunnerListener implements NotificationListener { + + /** + * Count of workAccepted() method calls + */ + private AtomicInteger workAcceptedCallCount = new AtomicInteger(); + + /** + * Count of workStarted() method calls + */ + private AtomicInteger workStartedCallCount = new AtomicInteger(); + + /** + * Count of workCompleted() method calls + */ + private AtomicInteger workCompletedCallCount = new AtomicInteger(); + + /** + * Count of workFailed() method calls + */ + private AtomicInteger workFailedCallCount = new AtomicInteger(); + + /** + * Count of workRejected() method calls + */ + private AtomicInteger workRejectedCallCount = new AtomicInteger(); + + /** + * List of all exceptions thrown by Work items + */ + private List workExceptions = Collections.synchronizedList(new ArrayList()); + + /** + * {@inheritDoc} + */ + public void workAccepted(JSR237MyRunnable work) { + workAcceptedCallCount.incrementAndGet(); + } + + /** + * {@inheritDoc} + */ + public void workCompleted(JSR237MyRunnable work) { + workCompletedCallCount.incrementAndGet(); + } + + /** + * {@inheritDoc} + */ + public void workFailed(JSR237MyRunnable work, Throwable error) { + workExceptions.add(error); + workFailedCallCount.incrementAndGet(); + } + + /** + * {@inheritDoc} + */ + public void workRejected(JSR237MyRunnable work) { + workRejectedCallCount.incrementAndGet(); + } + + /** + * {@inheritDoc} + */ + public void workStarted(JSR237MyRunnable work) { + workStartedCallCount.incrementAndGet(); + } + + /** + * Returns the number of calls to workAccepted() + * + * @return The number of calls to workAccepted() + */ + public int getWorkAcceptedCallCount() { + return workAcceptedCallCount.get(); + } + + /** + * Returns the number of calls to workStarted() + * + * @return The number of calls to workStarted() + */ + public int getWorkStartedCallCount() { + return workStartedCallCount.get(); + } + + /** + * Returns the number of calls to workCompleted() + * + * @return The number of calls to workCompleted() + */ + public int getWorkCompletedCallCount() { + return workCompletedCallCount.get(); + } + + /** + * Returns the number of calls to workFailed() + * + * @return The number of calls to workFailed() + */ + public int getWorkFailedCallCount() { + return workFailedCallCount.get(); + } + + /** + * Returns the number of calls to workRejected() + * + * @return The number of calls to workRejected() + */ + public int getWorkRejectedCallCount() { + return workRejectedCallCount.get(); + } + + /** + * Returns a List of all exceptions that are thrown by the Work items + * + * @return A List of all exceptions that are thrown by the Work items + */ + public List getWorkExceptions() { + return Collections.unmodifiableList(workExceptions); + } +} diff --git a/sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/Jsr237WorkSchedulerTestCase.java b/sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/Jsr237WorkSchedulerTestCase.java new file mode 100644 index 0000000000..4ec0f55867 --- /dev/null +++ b/sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/Jsr237WorkSchedulerTestCase.java @@ -0,0 +1,240 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.work.impl; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * Test case for Jsr237WorkScheduler + * + * @version $Rev$ $Date$ + */ +public class Jsr237WorkSchedulerTestCase { + + /** + * Wait up to 20 seconds for the Work units to complete + */ + private static final long WAIT_TIMEOUT = 20000; + + /** + * This is the shared instance of the ThreadPoolWorkManager used by the tests + */ + private static DefaultWorkScheduler workSchedular = null; + + /** + * Setup the Jsr237WorkScheduler + */ + @BeforeClass + public static void setup() { + workSchedular = new DefaultWorkScheduler(null, null); + } + + /** + * Make sure that the Jsr237WorkScheduler is stopped after running the tests + */ + @AfterClass + public static void destroy() { + if (workSchedular != null) { + workSchedular.stop(); + } + } + + /** + * Tests running a single fast job on the Jsr237WorkScheduler + */ + @Test + public void testSingleFastJob() { + // Create the work and register it + JSR237MyRunnable fast = new JSR237MyRunnable(10); + JSR237MyRunnerListener listener = new JSR237MyRunnerListener(); + workSchedular.scheduleWork(fast, listener); + + // Wait for the 1 job to complete + waitForWorkToComplete(listener, 1); + + // Test that the job completed successfully. + Assert.assertEquals(1, listener.getWorkAcceptedCallCount()); + Assert.assertEquals(0, listener.getWorkRejectedCallCount()); + Assert.assertEquals(1, listener.getWorkStartedCallCount()); + Assert.assertEquals(1, listener.getWorkCompletedCallCount()); + Assert.assertEquals(0, listener.getWorkExceptions().size()); + } + + /** + * Tests running a single job that fails on the Jsr237WorkScheduler + */ + @Test + public void testSingleFailingJob() { + // Create the work and register it + JSR237MyFailingRunnable fail = new JSR237MyFailingRunnable(); + JSR237MyRunnerListener listener = new JSR237MyRunnerListener(); + workSchedular.scheduleWork(fail, listener); + + // Wait for the 1 job to complete + waitForWorkToComplete(listener, 1); + + // Test that the job completed successfully. + Assert.assertEquals(1, listener.getWorkAcceptedCallCount()); + Assert.assertEquals(0, listener.getWorkRejectedCallCount()); + Assert.assertEquals(1, listener.getWorkStartedCallCount()); + Assert.assertEquals(0, listener.getWorkCompletedCallCount()); + Assert.assertEquals(1, listener.getWorkFailedCallCount()); + Assert.assertEquals(1, listener.getWorkExceptions().size()); + } + + /** + * Tests running a mixture of fast and slow jobs on the Jsr237WorkScheduler + */ + @Test + public void testMultipleJobs() { + // Create the work and register it + JSR237MyRunnable fast1 = new JSR237MyRunnable(5); + JSR237MyRunnable fast2 = new JSR237MyRunnable(10); + JSR237MyRunnable fast3 = new JSR237MyRunnable(20); + JSR237MyRunnable slow1= new JSR237MyRunnable(200); + JSR237MyRunnable slow2 = new JSR237MyRunnable(200); + JSR237MyRunnerListener listener = new JSR237MyRunnerListener(); + workSchedular.scheduleWork(fast1, listener); + workSchedular.scheduleWork(fast2, listener); + workSchedular.scheduleWork(fast3, listener); + workSchedular.scheduleWork(slow1, listener); + workSchedular.scheduleWork(slow2, listener); + + // Wait for the 5 jobs to complete + waitForWorkToComplete(listener, 5); + + // Test that the job completed successfully. + Assert.assertEquals(5, listener.getWorkAcceptedCallCount()); + Assert.assertEquals(0, listener.getWorkRejectedCallCount()); + Assert.assertEquals(5, listener.getWorkStartedCallCount()); + Assert.assertEquals(5, listener.getWorkCompletedCallCount()); + Assert.assertEquals(0, listener.getWorkExceptions().size()); + } + + /** + * Tests running a mixture of fast and slow jobs some of which fail on the + * Jsr237WorkScheduler + */ + @Test + public void testMultipleJobsSomeFail() { + // Create the work and register it + JSR237MyRunnable fast1 = new JSR237MyRunnable(5); + JSR237MyRunnable fast2 = new JSR237MyRunnable(10); + JSR237MyRunnable fast3 = new JSR237MyRunnable(20); + JSR237MyRunnable slow1= new JSR237MyRunnable(200); + JSR237MyRunnable slow2 = new JSR237MyRunnable(200); + JSR237MyFailingRunnable fail1 = new JSR237MyFailingRunnable(); + JSR237MyFailingRunnable fail2 = new JSR237MyFailingRunnable(); + JSR237MyRunnerListener listener = new JSR237MyRunnerListener(); + workSchedular.scheduleWork(fast1, listener); + workSchedular.scheduleWork(fast2, listener); + workSchedular.scheduleWork(fail1, listener); + workSchedular.scheduleWork(fast3, listener); + workSchedular.scheduleWork(slow1, listener); + workSchedular.scheduleWork(fail2, listener); + workSchedular.scheduleWork(slow2, listener); + + // Wait for the 7 jobs to complete + waitForWorkToComplete(listener, 7); + + // Test that the job completed successfully. + Assert.assertEquals(7, listener.getWorkAcceptedCallCount()); + Assert.assertEquals(0, listener.getWorkRejectedCallCount()); + Assert.assertEquals(7, listener.getWorkStartedCallCount()); + Assert.assertEquals(5, listener.getWorkCompletedCallCount()); + Assert.assertEquals(2, listener.getWorkFailedCallCount()); + Assert.assertEquals(2, listener.getWorkExceptions().size()); + } + + /** + * Tests running a single job that has no listener + */ + @Test + public void testSingleFastJobWithNoListener() { + // Create the work and register it + JSR237MyRunnable fast = new JSR237MyRunnable(10); + workSchedular.scheduleWork(fast); + + // Wait for the job to complete + long startTime = System.currentTimeMillis(); + while (true) { + int completedCount = fast.getRunCompletedCount(); + if (completedCount == 1) { + break; + } + + if (System.currentTimeMillis() - startTime > WAIT_TIMEOUT) { + Assert.fail("Only " + completedCount + " work items completed before timeout"); + return; + } + + // Lets wait for the job to complete + try { + Thread.sleep(25); + } catch (InterruptedException ex) { + Assert.fail("Unexpected exception: " + ex); + } + } + } + + /** + * Tests scheduling a null as the work item + */ + @Test + public void testNullWork() { + try { + workSchedular.scheduleWork(null); + Assert.fail("Should have thrown IllegalArgumentException "); + } catch (IllegalArgumentException ex) { + // As expected + Assert.assertTrue(ex.toString().indexOf("null") != -1); + } + } + + /** + * Waits for the specified number of jobs to complete or the timeout to fire. + * + * @param listener The listener to use to track Work unit completion + * @param completedWorkItemsToWaitFor The number of Work items to complete + */ + private void waitForWorkToComplete(JSR237MyRunnerListener listener, int completedWorkItemsToWaitFor) { + long startTime = System.currentTimeMillis(); + while (true) { + int completedCount = listener.getWorkCompletedCallCount() + listener.getWorkFailedCallCount(); + if (completedCount == completedWorkItemsToWaitFor) { + return; + } + + if (System.currentTimeMillis() - startTime > WAIT_TIMEOUT) { + Assert.fail("Only " + completedCount + " work items completed before timeout"); + return; + } + + // Lets wait for more jobs to complete + try { + Thread.sleep(25); + } catch (InterruptedException ex) { + Assert.fail("Unexpected exception: " + ex); + } + } + } +} diff --git a/sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TestWorkListener.java b/sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TestWorkListener.java new file mode 100644 index 0000000000..a452d6f371 --- /dev/null +++ b/sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TestWorkListener.java @@ -0,0 +1,153 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.work.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.tuscany.sca.work.WorkSchedulerException; +import org.junit.Assert; + +/** + * A simple WorkListener that tracks invocations to it. + * + * @version $Rev$ $Date$ + */ +public class TestWorkListener implements WorkListener { + + /** + * Count of workAccepted() method calls + */ + private AtomicInteger workAcceptedCallCount = new AtomicInteger(); + + /** + * Count of workStarted() method calls + */ + private AtomicInteger workStartedCallCount = new AtomicInteger(); + + /** + * Count of workCompleted() method calls + */ + private AtomicInteger workCompletedCallCount = new AtomicInteger(); + + /** + * Count of workRejected() method calls + */ + private AtomicInteger workRejectedCallCount = new AtomicInteger(); + + /** + * List of all exceptions thrown by Work items + */ + private List workExceptions = Collections.synchronizedList(new ArrayList()); + + /** + * {@inheritDoc} + */ + public void workAccepted(WorkEvent work) { + workAcceptedCallCount.incrementAndGet(); + + // Validate the WorkEvent + Assert.assertNotNull(work.getWorkItem()); + Assert.assertEquals(WorkEvent.WORK_ACCEPTED, work.getType()); + } + + /** + * {@inheritDoc} + */ + public void workStarted(WorkEvent work) { + workStartedCallCount.incrementAndGet(); + + // Validate the WorkEvent + Assert.assertNotNull(work.getWorkItem()); + Assert.assertEquals(WorkEvent.WORK_STARTED, work.getType()); + } + + /** + * {@inheritDoc} + */ + public void workCompleted(WorkEvent work) { + if (work.getException() != null) { + workExceptions.add(work.getException()); + } + + // Validate the WorkEvent + Assert.assertNotNull(work.getWorkItem()); + Assert.assertEquals(WorkEvent.WORK_COMPLETED, work.getType()); + + workCompletedCallCount.incrementAndGet(); + } + + /** + * {@inheritDoc} + */ + public void workRejected(WorkEvent work) { + workRejectedCallCount.incrementAndGet(); + + // Validate the WorkEvent + Assert.assertNotNull(work.getWorkItem()); + Assert.assertEquals(WorkEvent.WORK_REJECTED, work.getType()); + } + + /** + * Returns the number of calls to workAccepted() + * + * @return The number of calls to workAccepted() + */ + public int getWorkAcceptedCallCount() { + return workAcceptedCallCount.get(); + } + + /** + * Returns the number of calls to workStarted() + * + * @return The number of calls to workStarted() + */ + public int getWorkStartedCallCount() { + return workStartedCallCount.get(); + } + + /** + * Returns the number of calls to workCompleted() + * + * @return The number of calls to workCompleted() + */ + public int getWorkCompletedCallCount() { + return workCompletedCallCount.get(); + } + + /** + * Returns the number of calls to workRejected() + * + * @return The number of calls to workRejected() + */ + public int getWorkRejectedCallCount() { + return workRejectedCallCount.get(); + } + + /** + * Returns a List of all exceptions that are thrown by the Work items + * + * @return A List of all exceptions that are thrown by the Work items + */ + public List getWorkExceptions() { + return Collections.unmodifiableList(workExceptions); + } +} diff --git a/sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManagerTestCase.java b/sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManagerTestCase.java new file mode 100644 index 0000000000..122609d7e6 --- /dev/null +++ b/sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManagerTestCase.java @@ -0,0 +1,227 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.work.impl; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * This test case will test the ThreadPoolWorkManager + * + * @version $Rev$ $Date$ + */ +public class ThreadPoolWorkManagerTestCase { + + /** + * Wait up to 20 seconds for the Work units to complete + */ + private static final long WAIT_TIMEOUT = 20000; + + /** + * This is the shared instance of the ThreadPoolWorkManager used by the tests + */ + private static ThreadPoolWorkManager workManager = null; + + /** + * Setup the ThreadPoolWorkManager + */ + @BeforeClass + public static void setup() { + workManager = new ThreadPoolWorkManager(10); + } + + /** + * Make sure that the ThreadPoolWorkManager is stopped after running the tests + */ + @AfterClass + public static void destroy() { + if (workManager != null) { + workManager.destroy(); + } + } + + /** + * Tests running a single fast job on the ThreadPoolWorkManager + */ + @Test + public void testSingleFastJob() { + // Create the work and register it + TimeDelayWork fast = new TimeDelayWork(10); + TestWorkListener listener = new TestWorkListener(); + workManager.schedule(fast, listener); + + // Wait for the 1 job to complete + waitForWorkToComplete(listener, 1); + + // Test that the job completed successfully. + Assert.assertEquals(1, listener.getWorkAcceptedCallCount()); + Assert.assertEquals(0, listener.getWorkRejectedCallCount()); + Assert.assertEquals(1, listener.getWorkStartedCallCount()); + Assert.assertEquals(1, listener.getWorkCompletedCallCount()); + Assert.assertEquals(0, listener.getWorkExceptions().size()); + } + + /** + * Tests running a single job that fails on the ThreadPoolWorkManager + */ + @Test + public void testSingleFailingJob() { + // Create the work and register it + FailingWork fail = new FailingWork(); + TestWorkListener listener = new TestWorkListener(); + workManager.schedule(fail, listener); + + // Wait for the 1 job to complete + waitForWorkToComplete(listener, 1); + + // Test that the job completed successfully. + Assert.assertEquals(1, listener.getWorkAcceptedCallCount()); + Assert.assertEquals(0, listener.getWorkRejectedCallCount()); + Assert.assertEquals(1, listener.getWorkStartedCallCount()); + Assert.assertEquals(1, listener.getWorkCompletedCallCount()); + Assert.assertEquals(1, listener.getWorkExceptions().size()); + } + + /** + * Tests running a mixture of fast and slow jobs on the ThreadPoolWorkManager + */ + @Test + public void testMultipleJobs() { + // Create the work and register it + TimeDelayWork fast1 = new TimeDelayWork(5); + TimeDelayWork fast2 = new TimeDelayWork(10); + TimeDelayWork fast3 = new TimeDelayWork(20); + TimeDelayWork slow1= new TimeDelayWork(200); + TimeDelayWork slow2 = new TimeDelayWork(200); + TestWorkListener listener = new TestWorkListener(); + workManager.schedule(fast1, listener); + workManager.schedule(fast2, listener); + workManager.schedule(fast3, listener); + workManager.schedule(slow1, listener); + workManager.schedule(slow2, listener); + + // Wait for the 5 jobs to complete + waitForWorkToComplete(listener, 5); + + // Test that the job completed successfully. + Assert.assertEquals(5, listener.getWorkAcceptedCallCount()); + Assert.assertEquals(0, listener.getWorkRejectedCallCount()); + Assert.assertEquals(5, listener.getWorkStartedCallCount()); + Assert.assertEquals(5, listener.getWorkCompletedCallCount()); + Assert.assertEquals(0, listener.getWorkExceptions().size()); + } + + /** + * Tests running a mixture of fast and slow jobs some of which fail on the + * ThreadPoolWorkManager + */ + @Test + public void testMultipleJobsSomeFail() { + // Create the work and register it + TimeDelayWork fast1 = new TimeDelayWork(5); + TimeDelayWork fast2 = new TimeDelayWork(10); + TimeDelayWork fast3 = new TimeDelayWork(20); + TimeDelayWork slow1= new TimeDelayWork(200); + TimeDelayWork slow2 = new TimeDelayWork(200); + FailingWork fail1 = new FailingWork(); + FailingWork fail2 = new FailingWork(); + TestWorkListener listener = new TestWorkListener(); + workManager.schedule(fast1, listener); + workManager.schedule(fast2, listener); + workManager.schedule(fail1, listener); + workManager.schedule(fast3, listener); + workManager.schedule(slow1, listener); + workManager.schedule(fail2, listener); + workManager.schedule(slow2, listener); + + // Wait for the 7 jobs to complete + waitForWorkToComplete(listener, 7); + + // Test that the job completed successfully. + Assert.assertEquals(7, listener.getWorkAcceptedCallCount()); + Assert.assertEquals(0, listener.getWorkRejectedCallCount()); + Assert.assertEquals(7, listener.getWorkStartedCallCount()); + Assert.assertEquals(7, listener.getWorkCompletedCallCount()); + Assert.assertEquals(2, listener.getWorkExceptions().size()); + } + + /** + * Tests running a single job that has no listener + */ + @Test + public void testSingleFastJobWithNoListener() { + // Create the work and register it + TimeDelayWork fast = new TimeDelayWork(10); + workManager.schedule(fast); + + // Wait for the job to complete + long startTime = System.currentTimeMillis(); + while (true) { + int completedCount = fast.getRunCompletedCount(); + if (completedCount == 1) { + break; + } + + if (System.currentTimeMillis() - startTime > WAIT_TIMEOUT) { + Assert.fail("Only " + completedCount + " work items completed before timeout"); + return; + } + + // Lets wait for the job to complete + try { + Thread.sleep(25); + } catch (InterruptedException ex) { + Assert.fail("Unexpected exception: " + ex); + } + } + + // Make sure we have got one completed run + Assert.assertEquals(1, fast.getRunCompletedCount()); + } + + /** + * Waits for the specified number of jobs to complete or the timeout to fire. + * + * @param listener The listener to use to track Work unit completion + * @param completedWorkItemsToWaitFor The number of Work items to complete + */ + private void waitForWorkToComplete(TestWorkListener listener, int completedWorkItemsToWaitFor) { + long startTime = System.currentTimeMillis(); + while (true) { + int completedCount = listener.getWorkCompletedCallCount(); + if (completedCount == completedWorkItemsToWaitFor) { + return; + } + + if (System.currentTimeMillis() - startTime > WAIT_TIMEOUT) { + Assert.fail("Only " + completedCount + " work items completed before timeout"); + return; + } + + // Lets wait for more jobs to complete + try { + Thread.sleep(25); + } catch (InterruptedException ex) { + Assert.fail("Unexpected exception: " + ex); + } + } + } +} diff --git a/sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TimeDelayWork.java b/sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TimeDelayWork.java new file mode 100644 index 0000000000..f6435659ef --- /dev/null +++ b/sca-java-2.x/branches/2.0/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TimeDelayWork.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.work.impl; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Simple Work item that will sleep in the run() method for the specified + * period of time + * + * @version $Rev$ $Date$ + */ +public class TimeDelayWork extends Work { + + /** + * Count of completed run() method calls + */ + private AtomicInteger runCompletedCount = new AtomicInteger(); + + /** + * The amount of time to sleep in the Run loop + */ + private final long sleepTime; + + /** + * Constructor + * + * @param sleepTime The amount of time to sleep (in milliseconds) in the run() method + */ + public TimeDelayWork(long sleepTime) { + super(null); + this.sleepTime = sleepTime; + } + + /** + * {@inheritDoc} + */ + public boolean isDaemon() { + return false; + } + + /** + * {@inheritDoc} + */ + public void release() { + } + + /** + * Sleeps for a period of time defined by sleepTime + */ + public void run() { + System.out.println("Starting " + this); + try { + Thread.sleep(sleepTime); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("Done " + this); + runCompletedCount.incrementAndGet(); + } + + /** + * Returns the number of completed calls to run() + * + * @return The number of completed calls to run() + */ + public int getRunCompletedCount() { + return runCompletedCount.get(); + } +} -- cgit v1.2.3