jconch.testing
Class Assert

java.lang.Object
  extended by jconch.testing.Assert

public class Assert
extends Object

A collection of helpful concurrency based assert methods.

Author:
Hamlet D'Arcy

Method Summary
static void assertSynchronized(Callable<? extends Collection<Callable<Void>>> taskFactory)
          The assertSynchronized method attempts to cause concurrency errors by repeatedly invoking code on seperate threads.
static void assertSynchronized(Callable<? extends Collection<Callable<Void>>> taskFactory, int threadPoolSize, int numIterations)
          This is the same as assertSynchronized(Callable) expect that the thread pool size and the number or iterations can be specified.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Method Detail

assertSynchronized

public static void assertSynchronized(Callable<? extends Collection<Callable<Void>>> taskFactory)
                               throws Exception

The assertSynchronized method attempts to cause concurrency errors by repeatedly invoking code on seperate threads.

To use this assertion, give the method a Callable object that produces a Collection of code fragments which must be synchronized between themselves. This master callable that produces the code fragments is called the "taskFactory", and it will be invoked repeatedly, running all the resulting Callable objects on seperate threads.

As an example, the ArrayList.add(Object) method is not synchronized. So add invocations on multiple threads will eventually result in an ArrayIndexOutOfBoundsException. To test this, pass assertSynchronized a factory for Callables that call add():

 
 Assert.assertSynchronized(
   new Callable<List<Callable<Void>>>() {
     public List<Callable<Void>> call() throws Exception {

       // ArrayList.add(T) is not synchronized
       final ArrayList<Object> unsafeObject = new ArrayList<Object>();
       final Callable<Void> unsafeInvocation = new Callable<Void>() {
         public Void call() throws Exception {
           for (int x = 0; x < 1000; x++) {
             unsafeObject.add(new Object());
           }
           return null;
         }
       };
       return Arrays.asList(
         unsafeInvocation,
         unsafeInvocation
       );
     }
   }
 );

This will fail with an AssertionError as expected. The test will pass if you switch the implementation to a Vector instead of an ArrayList

By default, it creates a thread pool of 10 threads, and attempts to run the code passed in 1000 times. Any errors that occur are collected and reported in an AssertionError.

Parameters:
taskFactory - a Callable that produces a new Collection of Callable objects on each iteration. Expect this Callable to be invoked x number of times, where x is the numIterations value. May not be null.
Throws:
Exception - Any exception raised by the taskFactory will be passed up to the caller
AssertionError - If any of the callables raises an exception, then as AssertionError is thrown. The error will report how many failures occurred and the message of one of the thrown exceptions. The message will usually (but not always) be that of the most recently thrown exception.

assertSynchronized

public static void assertSynchronized(Callable<? extends Collection<Callable<Void>>> taskFactory,
                                      int threadPoolSize,
                                      int numIterations)
                               throws Exception

This is the same as assertSynchronized(Callable) expect that the thread pool size and the number or iterations can be specified.

Parameters:
taskFactory - a Callable that produces a new Collection of Callable objects on each iteration. Expect this Callable to be invoked x number of times, where x is the numIterations value. May not be null.
threadPoolSize - size of the threadpool used during testing, must be positive
numIterations - the number of times to run the test. This number needs to be sufficiently large emough to cause the error condition, whether it be a race condition, phantom data, or anything else. Must be positive.
Throws:
Exception - Any exception raised by the taskFactory will be passed up to the caller
AssertionError - If any of the callables raises an exception, then as AssertionError is thrown. The error will report how many failures occurred and the message of one of the thrown exceptions. The message will usually (but not always) be that of the most recently thrown exception.