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();

Reply via email to