|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Objectorg.apache.qpid.junit.concurrency.TestRunnable
public abstract class TestRunnable
TestRunnable is an extension of java.util.Runnable that adds some features to make it easier to coordinate the activities of threads in such a way as to expose bugs in multi threaded code.
Sometimes several threads will run in a particular order so that a bug is not revealed. Other times the ordering of the threads will expose a bug. Such bugs can be hard to replicate as the exact execution ordering of threads is not usually controlled. This class adds some methods that allow threads to synchronize other threads, either allowing them to run, or waiting for them to allow this thread to run. It also provides convenience methods to gather error messages and exceptions from threads, which will often be reported in unit testing code. Coordination between threads is handled by theThreadTestCoordinator
. It is called through the convenience
methods allow(int[])
and waitFor(int[], boolean)
. Threads to be coordinated must be set up with the coordinator and assigned
integer ids. It is then possible to call the coordinator with an array of thread ids requesting that those threads
be allowed to continue, or to wait until one of them allows this thread to continue. The otherwise non-deterministic
execution order of threads can be controlled into a carefully determined sequence using these methods in order
to reproduce race conditions, dead locks, live locks, dirty reads, phantom reads, non repeatable reads and so on.
When waiting for another thread to give a signal to continue it is sometimes the case that the other thread has
become blocked by the code under test. For example in testing for a dirty read (for example in database code),
thread 1 lets thread 2 perform a write but not commit it, then thread 2 lets thread 1 run and attempt to perform a
dirty read on its uncommitted write. Transaction synchronization code being tested against the possibility of a dirty
write may make use of snapshots in which case both threads should be able to read and write without blocking. It may
make use of explicit keys in which case thread 2 may become blocked on its write attempt because thread 1 holds a
read lock and it must wait until thread 1 completes its transaction before it can acquire this lock. The
waitFor(int[], boolean)
method accepts a boolean parameter to indicate that threads being blocked (other than on the
coordinator) can be interpreted the same as if the thread explicitly allows the thread calling waitFor to continue.
Using this technique a dirty read test could be written that works against either the snapshot or the locking
implementation, allowing both approaches to pass the test yet arranging for multiple threads to run against the
implementation in such a way that a potential dirty read bug is exposed.
Responsibilities | Collaborations |
---|---|
Wait for another thread to allow this one to continue. | |
Allow another thread to continue. | |
Accumulate error messages. | |
Record exceptions from thread run. | |
Maintain link to thread coordinator. | |
Explicitly mark a thread with an integer id. | |
Maintian a flag to indicate whether or not this thread is waiting on the coordinator. |
Constructor Summary | |
---|---|
TestRunnable()
|
Method Summary | |
---|---|
protected void |
addErrorMessage(String message)
Keeps the error message for later reporting by the coordinator. |
protected void |
allow(int[] threads)
Produces allow events on each of the specified threads. |
(package private) String |
getErrorMessage()
Reports any accumulated error messages. |
(package private) Exception |
getException()
Reports any exception thrown by the runWithExceptions() method. |
(package private) Thread |
getThread()
Gets the Java thread under which this runs. |
(package private) boolean |
isWaitingOnCoordinator()
Reports whether or not this thread is waiting on the coordinator. |
void |
run()
Provides a default implementation of the run method that allows exceptions to be thrown and keeps a record of those exceptions. |
abstract void |
runWithExceptions()
Implementations override this to perform coordinated thread sequencing. |
(package private) void |
setCoordinator(ThreadTestCoordinator coordinator)
Sets the coordinator for this thread. |
(package private) void |
setId(int id)
Sets up the explicit int id for this thread. |
(package private) void |
setThread(Thread thread)
Sets the Java thread under which this runs. |
(package private) void |
setWaitingOnCoordinator(boolean waiting)
Sets the value of the waiting on coordinator flag. |
String |
toString()
Provides a string summary of this test threads status. |
protected boolean |
waitFor(int[] threads,
boolean otherWaitIsAllow)
Attempt to consume an allow event from one of the specified threads and blocks until such an event occurrs. |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait |
Constructor Detail |
---|
public TestRunnable()
Method Detail |
---|
public abstract void runWithExceptions() throws Exception
Exception
- Any exception raised by the implementation will be caught by the default run()
implementation for later querying by the getException()
method.public void run()
runWithExceptions()
method to provide the thread body implementation
and catches any exceptions thrown by it.
run
in interface Runnable
protected boolean waitFor(int[] threads, boolean otherWaitIsAllow)
threads
- The set of threads that can allow this one to continue.otherWaitIsAllow
- If set to true if the threads being waited on are blocked other than on
the coordinator itself then this is to be interpreted as allowing this thread to
continue.
protected void allow(int[] threads)
threads
- The set of threads that are to be allowed to continue.protected void addErrorMessage(String message)
message
- The error message to keep.void setCoordinator(ThreadTestCoordinator coordinator)
coordinator
- The coordinator for this thread.boolean isWaitingOnCoordinator()
void setWaitingOnCoordinator(boolean waiting)
waiting
- The value of the waiting on coordinator flag.void setId(int id)
id
- The integer id.String getErrorMessage()
Exception getException()
runWithExceptions()
method.
runWithExceptions()
method.void setThread(Thread thread)
thread
- The Java thread under which this runs.Thread getThread()
public String toString()
toString
in class Object
|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |