Hello All, Below I have included a proposed API for a concurrency test helper. The goal of this test helper is to make it easier for tests to use multiple threads. I believe providing a helper for this will reduce the number of tests that incorrectly use threads, and help make our DUnit tests more readable.
I would like feedback on the API below. I have provided the method signatures that I plan on implementing, as well as an example usage. Please let me know if there are any methods that seem unnecessary or if there are any important use cases that I missed here. Thank you, Helena Bales public class ConcurrencyTestHelper { private List<Callable<T>> toRun; private Integer timeout; private final Integer DEFAULT_TIMEOUT = 30; /** * A default constructor that sets the timeout to a default of 30 seconds */ public ConcurrencyTestHelper() { toRun = new ArrayList<Callable<T>>(); timeout = DEFAULT_TIMEOUT; } /** * Run the given Runnable and assert that an exception of the given type is thrown. The thread * will be cancelled when the class timeout is reached. * @param runnable a Runnable that throws an exception and responds to cancellation signal * @param exceptionType a Class of Exception that is expected to be thrown by the runnable */ public void runAndExpectException(Runnable runnable, Class exceptionType); /** * Run the given Runnable and assert that no exceptions are thrown. The thread will be cancelled * when the class timeout is reached. * @param runnable a Runnable that does not throw an exception and responds to cancellation signal */ public void runAndExpectNoException(Runnable runnable); /** * Run the given Callable and assert that the result of that callable is the given expected value. * The thread will be cancelled when the class timeout is reached. * @param callable a Callable that returns an object, does not throw exceptions and responds to * cancellation signal * @param value an Object that is the expected return value from the Callable. */ public void runAndExpectValue(Callable callable, Object value); /** * Run the given runnable in a loop until the rest of the threads complete. Fails if the runnable * throws an exception during any iteration. After the rest of the threads complete the loop will * not restart the runnable. The running iteration will be cancelled when the timeout set on the * class is reached. A cancellation will result in a test failure. * @param runnable a Runnable that does not throw an exception and responds to cancellation signal */ public void repeatUntilAllThreadsComplete(Runnable runnable); /** * Run the given runnable in a loop for some number of iterations. Fails if the runnable throws an * exception in any iteration. After the number of iterations has been met, the loop will not * restart the runnable. The running iteration of the Runnable will be cancelled when the * timeout set on the class is reached, regardless of if the number of desired iterations has * been reached. A cancellation will result in a test failure. * @param runnable a Runnable that does not throw an exception and responds to cancellation signal * @param iterations a maximum number of iterations to repeat for */ public void repeatForIterations(Runnable runnable, Integer iterations); /** * Run the given runnable in a loop for a certain duration. Fails if the runnable throws an * exception in any iteration. After the duration has been exceeded, the loop will not restart * the runnable, however the current iteration will not be cancelled until the timeout value for * the class has been reached. A cancellation will result in a test failure. * @param runnable a Runnable that does not throw exceptions and responds to cancellation signal * @param duration a maximum amount of time to repeat for */ public void repeatForDuration(Runnable runnable, Integer duration); /** * Set the timeout for the threads. After the timeout is reached, the threads will be interrupted * and will throw a CancellationException */ public void setTimeout(Integer seconds) { timeout = seconds; } /** * Runs all callables in toRun in parallel and fail if threads' conditions were not met. Runs * until timeout is reached. * @throws InterruptedException if interrupted before timeout */ public void executeInParallel(); /** * Runs all callables in toRun in the order that they were added and fail if threads' conditions * were not met. Runs until timeout is reached. * @throws InterruptedException if interrupted before timeout */ public void executeInSeries(); } // example usage: new ConcurrentTestHelper() .runAndExpectException(runnable, UnsupportedOperationException.class) .runAndExpectNoException(runnable) .runAndExpectValue(callable, result) .repeatUntilAllOtherRunnablesFinish(runnable) .repeatFor(runnable, time) //keep doing this for time amount of time .repeat(runnable, iterations) //keep doing this for N times .setTimeout(seconds) //Throws exception if test takes too long .executeInParallel();