summaryrefslogtreecommitdiff
path: root/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/ScaledTestDecorator.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/ScaledTestDecorator.java')
-rw-r--r--java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/ScaledTestDecorator.java391
1 files changed, 0 insertions, 391 deletions
diff --git a/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/ScaledTestDecorator.java b/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/ScaledTestDecorator.java
deleted file mode 100644
index 93e2a3c855..0000000000
--- a/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/ScaledTestDecorator.java
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
- *
- * 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.qpid.junit.extensions;
-
-import junit.framework.Test;
-import junit.framework.TestResult;
-
-import java.util.concurrent.BrokenBarrierException;
-import java.util.concurrent.CyclicBarrier;
-
-/**
- * A test decorator that runs a test many times simultaneously in many threads.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Clone a test run into many threads and run them simultaneously.
- * <tr><td> Inform the test results of the start and end of each concurrent test batch. <td> {@link TKTestResult}
- * <tr><td> Inform the test results of the concurrency level. <td> {@link TKTestResult}
- * </table>
- *
- * @author Rupert Smith
- */
-public class ScaledTestDecorator extends WrappedSuiteTestDecorator implements ShutdownHookable // TestDecorator
-{
- /** Used for logging. */
- // private static final Logger log = Logger.getLogger(ScaledTestDecorator.class);
-
- /** Determines how long to wait for tests to cleanly exit on shutdown. */
- private static final long SHUTDOWN_PAUSE = 3000;
-
- /**
- * The stress levels or numbers of simultaneous threads to run the test in. The test is repeated at each of
- * the concurrency levels specified here. Defaults to 1 thread.
- */
- private int[] threads = new int[] { 1 };
-
- /** Used to hold the number of tests currently being run in parallel. */
- private int concurrencyLevel;
-
- /** The test to run. */
- private WrappedSuiteTestDecorator test;
-
- /**
- * Used to hold the current {@link TKTestResult} for the tests currently being run. This is made available so that
- * the shutdown hook can ask it to cleanly end the current tests in the event of a shutdown.
- */
- private TKTestResult currentTestResult;
-
- /** Flag set by the shutdown hook. This decorator will not start any new tests when this is set. */
- private boolean shutdown = false;
-
- /**
- * Creates an active test with default multiplier (1).
- *
- * @param test The target test.
- */
- public ScaledTestDecorator(WrappedSuiteTestDecorator test)
- {
- super(test);
- this.test = test;
- }
-
- /**
- * Creates a concurrently scaled test with the specified number of threads.
- *
- * @param test The target test.
- * @param numThreads The stress level.
- */
- public ScaledTestDecorator(WrappedSuiteTestDecorator test, int numThreads)
- {
- this(test, new int[] { numThreads });
- }
-
- /**
- * Creates a concurrently scaled test with the specified thread levels, the test is repeated at each level.
- *
- * @param test The target test.
- * @param threads The concurrency levels.
- */
- public ScaledTestDecorator(WrappedSuiteTestDecorator test, int[] threads)
- {
- super(test);
-
- /*log.debug("public ScaledTestDecorator(WrappedSuiteTestDecorator test = \"" + test + "\", int[] threads = "
- + MathUtils.printArray(threads) + "): called");*/
-
- this.test = test;
- this.threads = threads;
- }
-
- /**
- * Runs the test simultaneously in at the specified concurrency levels.
- *
- * @param testResult The results object to monitor the test results with.
- */
- public void run(TestResult testResult)
- {
- // log.debug("public void run(TestResult testResult = " + testResult + "): called");
-
- // Loop through all of the specified concurrent levels for the test, provided shutdown has not been called.
- for (int i = 0; (i < threads.length) && !shutdown; i++)
- {
- // Get the number of threads for this run.
- int numThreads = threads[i];
-
- // Create test thread handlers for all the threads.
- TestThreadHandler[] threadHandlers = new TestThreadHandler[numThreads];
-
- // Create a cyclic barrier for the test threads to synch their setups and teardowns on.
- CyclicBarrier barrier = new CyclicBarrier(numThreads);
-
- // Set up the test thread handlers to output results to the same test results object.
- for (int j = 0; j < numThreads; j++)
- {
- threadHandlers[j] = new TestThreadHandler(testResult, test, barrier);
- }
-
- // Ensure the concurrency level statistic is set up correctly.
- concurrencyLevel = numThreads;
-
- // Begin batch.
- if (testResult instanceof TKTestResult)
- {
- TKTestResult tkResult = (TKTestResult) testResult;
- // tkResult.notifyStartBatch();
- tkResult.setConcurrencyLevel(numThreads);
-
- // Set the test result for the currently running tests, so that the shutdown hook can call it if necessary.
- currentTestResult = tkResult;
- }
-
- // Run all the tests and wait for them all to finish.
- executeAndWaitForRunnables(threadHandlers);
-
- // Clear the test result for the currently running tests.
- currentTestResult = null;
-
- // End batch.
- if (testResult instanceof TKTestResult)
- {
- TKTestResult tkResult = (TKTestResult) testResult;
- tkResult.notifyEndBatch();
- }
-
- // Clear up all the test threads, they hold references to their associated TestResult object and Test object,
- // which may prevent them from being garbage collected as the TestResult and Test objects are long lived.
- for (int j = 0; j < numThreads; j++)
- {
- threadHandlers[j].testResult = null;
- threadHandlers[j].test = null;
- threadHandlers[j] = null;
- }
- }
- }
-
- /**
- * Reports the number of tests that the scaled decorator is currently running concurrently.
- *
- * @return The number of tests that the scaled decorator is currently running concurrently.
- */
- public int getConcurrencyLevel()
- {
- return concurrencyLevel;
- }
-
- /**
- * Executes all of the specifed runnable using the thread pool and waits for them all to complete.
- *
- * @param runnables The set of runnables to execute concurrently.
- */
- private void executeAndWaitForRunnables(Runnable[] runnables)
- {
- int numThreads = runnables.length;
-
- // Used to keep track of the test threads in order to know when they have all completed.
- Thread[] threads = new Thread[numThreads];
-
- // Create all the test threads.
- for (int j = 0; j < numThreads; j++)
- {
- threads[j] = new Thread(runnables[j]);
- }
-
- // Start all the test threads.
- for (int j = 0; j < numThreads; j++)
- {
- threads[j].start();
- }
-
- // Wait for all the test threads to complete.
- for (int j = 0; j < numThreads; j++)
- {
- try
- {
- threads[j].join();
- }
- catch (InterruptedException e)
- {
- // Restore the interrupted state of the thread.
- Thread.currentThread().interrupt();
- }
- }
- }
-
- /**
- * Supplies the shut-down hook.
- *
- * @return The shut-down hook.
- */
- public Thread getShutdownHook()
- {
- return new Thread(new Runnable()
- {
- public void run()
- {
- // log.debug("ScaledTestDecorator::ShutdownHook: called");
-
- // Set the shutdown flag so that no new tests are started.
- shutdown = true;
-
- // Check if tests are currently running, and ask them to complete as soon as possible. Allow
- // a short pause for this to happen.
- TKTestResult testResult = currentTestResult;
-
- if (testResult != null)
- {
- // log.debug("There is a test result currently running tests, asking it to terminate ASAP.");
- testResult.shutdownNow();
-
- try
- {
- Thread.sleep(SHUTDOWN_PAUSE);
- }
- catch (InterruptedException e)
- {
- // Restore the interrupted state of the thread.
- Thread.currentThread().interrupt();
- }
- }
- }
- });
- }
-
- /**
- * Prints a string summarizing this test decorator, mainly for debugging purposes.
- *
- * @return String representation for debugging purposes.
- */
- public String toString()
- {
- return "ScaledTestDecorator: [ test = " + test + ", concurrencyLevel = " + concurrencyLevel + " ]";
- }
-
- /**
- * TestThreadHandler is a runnable used to execute a test in. This is static to avoid implicit 'this' reference to
- * the longer lived ScaledTestDecorator class. The scaled test decorator may execute many repeats but creates fresh
- * handlers for each one. It re-uses the threads in a pool but does not re-use these handlers.
- */
- private static class TestThreadHandler implements Runnable
- {
- /** The test result object for the test to be run with. */
- TestResult testResult;
-
- /** The test to run. */
- WrappedSuiteTestDecorator test;
-
- /** Holds the cyclic barrier to synchronize on the end of the setups and before the tear downs. */
- CyclicBarrier barrier;
-
- /**
- * Creates a new TestThreadHandler object.
- *
- * @param testResult The test result object for the test to be run with.
- * @param test The test to run in a sperate thread.
- * @param barrier The barrier implementation to use to synchronize per-thread setup completion and test
- * completion before moving on through the setup, test, teardown phases. The barrier should
- * be configured for the number of test threads.
- */
- TestThreadHandler(TestResult testResult, WrappedSuiteTestDecorator test, CyclicBarrier barrier)
- {
- this.testResult = testResult;
- this.test = test;
- this.barrier = barrier;
- }
-
- /**
- * Runs the test associated with this pool.
- */
- public void run()
- {
- try
- {
- // Call setup on all underlying tests in the suite that are thread aware.
- for (Test childTest : test.getAllUnderlyingTests())
- {
- // Check that the test is concurrency aware, so provides a setup method to call.
- if (childTest instanceof TestThreadAware)
- {
- // Call the tests per thread setup.
- TestThreadAware setupTest = (TestThreadAware) childTest;
- setupTest.threadSetUp();
- }
- }
-
- // Wait until all test threads have completed their setups.
- barrier.await();
-
-
- // Call setup on all underlying tests in the suite that are thread aware.
- for (Test childTest : test.getAllUnderlyingTests())
- {
- // Check that the test is concurrency aware, so provides a setup method to call.
- if (childTest instanceof TestThreadAware)
- {
- // Call the tests post thread setup.
- TestThreadAware setupTest = (TestThreadAware) childTest;
- setupTest.postThreadSetUp();
- }
- }
-
- // Wait until all test threads have completed their prefill.
- barrier.await();
-
- // Start timing the test batch, only after thread setups have completed.
- if (testResult instanceof TKTestResult)
- {
- ((TKTestResult) testResult).notifyStartBatch();
- }
-
- // Run the tests.
- test.run(testResult);
-
- // Wait unitl all test threads have completed their tests.
- barrier.await();
-
- // Call tear down on all underlying tests in the suite that are thread aware.
- for (Test childTest : test.getAllUnderlyingTests())
- {
- // Check that the test is concurrency aware, so provides a teardown method to call.
- if (childTest instanceof TestThreadAware)
- {
- // Call the tests per thread tear down.
- TestThreadAware setupTest = (TestThreadAware) childTest;
- setupTest.threadTearDown();
- }
- }
- }
- catch (InterruptedException e)
- {
- // Restore the interrupted state of the thread.
- Thread.currentThread().interrupt();
- }
- catch (BrokenBarrierException e)
- {
- // Set the interrupted state on the thread. The BrokenBarrierException may be caused where one thread
- // waiting for the barrier is interrupted, causing the remaining threads correctly waiting on the
- // barrier to fail. This condition is expected during test interruptions, and the response to it is to
- // interrupt all the other threads running in the same scaled test.
- Thread.currentThread().interrupt();
- }
- }
-
- /**
- * Prints the name of the test for debugging purposes.
- *
- * @return The name of the test.
- */
- public String toString()
- {
- return "ScaledTestDecorator: [test = \"" + test + "\"]";
- }
- }
-}