Class MultithreadedTestCase

java.lang.Object
junit.framework.Assert
edu.umd.cs.mtc.MultithreadedTestCase
Direct Known Subclasses:
MultithreadedTest

public abstract class MultithreadedTestCase extends junit.framework.Assert
This is the base class for each test in the MultithreadedTC framework. To create a multithreaded test case, simply extend this class. Any method with a name that starts with "thread", that has no parameters and a void return type is a thread method. Each thread method will be run in a seperate thread. This class also defines initialize() and finish() methods you can override.

A single run of a multithreaded test case consists of:

  1. Running the initialize() method
  2. Running each thread method in a seperate thread
  3. Running the finish() method when all threads are done.

The method TestFramework.runOnce(MultithreadedTestCase) can be used to run a MultithreadedTestCase once. The method TestFramework.runManyTimes(MultithreadedTestCase, int) can be used to run a multithread test case multiple times (to see if different interleavings produce different behaviors).

There are several additional methods you can use in designing test cases. The MultithreadedTestCase maintains a metronome or clock, and ticks off intervals. You can get the current tick with getTick() and you can wait until a particular tick with waitForTick(int). The metronome isn't a free running clock; it only advances to the next tick when all threads are blocked or waiting. Also, when all threads are blocked, if at least one thread isn't waiting for the metronome to advance, the system declares a deadlock to have occurred and terminates the test case (unless one of the threads is in state TIMED_WAITING).

You can set a command line parameter -Dtunit.trace=true to cause tracing messages to be printed by the metronome frame, or invoke setTrace(boolean) to turn tracing on or off.

You can set command line parameter -Dtunit.runLimit=10 to cause a test case to fail if at least one thread stays in a runnable state for more than 10 seconds without becoming blocked or waiting for a metronome tick. Use different values for shorter or longer time limits.

Since:
1.0
See Also:
  • Constructor Summary

    Constructors
    Constructor
    Description
     
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    assertTick(int tick)
    Assert that the clock is in tick tick
    static void
    This method is a replacement for Condition.await().
    void
    This method is invoked in a test after after all test threads have finished.
    void
    When the clock is frozen, it will not advance even when all threads are blocked.
    getThread(int index)
    Get a thread corresponding to the method whose name is formed using the prefix "thread" followed by an integer (represented by index.
    getThreadByName(String methodName)
    Get a thread given the method name that it corresponds to.
    int
    Gets the current value of the thread metronome.
    boolean
     
    void
    This method is invoked in a test run before any test threads have started.
    boolean
    Check if the clock has been frozen by any threads.
    void
    Calling this method from one of the test threads may cause the thread to yield.
    void
    mayYield(double probability)
    Calling this method from one of the test threads may cause the thread to yield.
    putThread(String methodName, Thread t)
    Associates a thread with given method name.
    void
    setTrace(boolean trace)
     
    static void
    When this method is called from a thread, the next call to waitOn(Object) or awaitOn(Condition) will return immediately without blocking.
    void
    Unfreeze a clock that has been frozen by freezeClock().
    void
    waitForTick(int c)
    Force this thread to block until the thread metronome reaches the specified value, at which point the thread is unblocked.
    void
    An Enum-based version of waitForTick.
    static void
    This method is a replacement for Object.wait().

    Methods inherited from class junit.framework.Assert

    assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertFalse, assertFalse, assertNotNull, assertNotNull, assertNotSame, assertNotSame, assertNull, assertNull, assertSame, assertSame, assertTrue, assertTrue, fail, fail, failNotEquals, failNotSame, failSame, format

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Constructor Details

    • MultithreadedTestCase

      public MultithreadedTestCase()
  • Method Details

    • initialize

      public void initialize()
      This method is invoked in a test run before any test threads have started.
    • finish

      public void finish()
      This method is invoked in a test after after all test threads have finished.
    • setTrace

      public void setTrace(boolean trace)
      Parameters:
      trace - the trace to set
    • getTrace

      public boolean getTrace()
      Returns:
      the trace
    • getThreadByName

      public Thread getThreadByName(String methodName)
      Get a thread given the method name that it corresponds to. E.g. to get the thread running the contents of the method thread1(), call getThreadByName("thread1")

      NOTE: initialize() is called before threads are created, so this method returns null if called from initialize() (but not from finish()).

      Parameters:
      methodName - the name of the method corresponding to the thread requested
      Returns:
      the thread corresponding to methodName
      See Also:
    • getThread

      public Thread getThread(int index)
      Get a thread corresponding to the method whose name is formed using the prefix "thread" followed by an integer (represented by index. e.g. getThread(1) returns the thread that thread1() is running in.

      NOTE: initialize() is called before threads are created, so this method returns null if called from initialize() (but not from finish()).

      Parameters:
      index - an integer following "thread" in the name of the method
      Returns:
      the Thread corresponding to this method
      See Also:
    • putThread

      public Thread putThread(String methodName, Thread t)
      Associates a thread with given method name. If the method name is already associated with a Thread, the old thread is returned, otherwise null is returned
    • waitForTick

      public void waitForTick(int c)
      Force this thread to block until the thread metronome reaches the specified value, at which point the thread is unblocked.
      Parameters:
      c - the tick value to wait for
    • waitForTick

      public void waitForTick(Enum e)
      An Enum-based version of waitForTick. It simply looks up the ordinal and adds 1 to determine the clock tick to wait for.
      Parameters:
      e - An Enum representing the tick to wait for. The first enumeration constant represents tick 1, the second is tick 2, etc.
      See Also:
    • getTick

      public int getTick()
      Gets the current value of the thread metronome. Primarily useful in assert statements.
      Returns:
      the current tick value
      See Also:
    • assertTick

      public void assertTick(int tick)
      Assert that the clock is in tick tick
      Parameters:
      tick - a number >= 0
    • freezeClock

      public void freezeClock()
      When the clock is frozen, it will not advance even when all threads are blocked. Use this to block the current thread with a time limit, but prevent the clock from advancing due to a waitForTick(int) in another thread. This statements that occur when clock is frozen should be followed by unfreezeClock() in the same thread.
    • unfreezeClock

      public void unfreezeClock()
      Unfreeze a clock that has been frozen by freezeClock(). Both methods must be called from the same thread.
    • isClockFrozen

      public boolean isClockFrozen()
      Check if the clock has been frozen by any threads.
    • skipNextWait

      public static void skipNextWait()
      When this method is called from a thread, the next call to waitOn(Object) or awaitOn(Condition) will return immediately without blocking. Use this to make tests more robust.
    • waitOn

      public static void waitOn(Object o)
      This method is a replacement for Object.wait(). It suppresses the InterruptedException that you would otherwise have to deal with, and allows automated skipping of the next wait. The method skipNextWait() will force that thread to immediately return from the next call to this method. Designing your tests so that they work even if Object.wait() occasionally returns immediately will make your code much more robust in face of several potential threading issues.
      Parameters:
      o - the object to wait on
    • awaitOn

      public static void awaitOn(Condition c)
      This method is a replacement for Condition.await(). It suppresses the InterruptedException that you would otherwise have to deal with, and allows automated skipping of the next wait. The method skipNextWait() will force that thread to immediately return from the next call to this method. Designing your tests so that they work even if Condition.await() occasionally returns immediately will make your code much more robust in face of several potential threading issues.
      Parameters:
      c - the condition to await on
    • mayYield

      public void mayYield()
      Calling this method from one of the test threads may cause the thread to yield. Use this between statements to generate more interleavings.
    • mayYield

      public void mayYield(double probability)
      Calling this method from one of the test threads may cause the thread to yield. Use this between statements to generate more interleavings.
      Parameters:
      probability - (a number between 0 and 1) the likelihood that Thread.yield() is called