sofya.ed.structural
Class JUnitEventDispatcher

java.lang.Object
  extended by sofya.ed.structural.AbstractEventDispatcher
      extended by sofya.ed.structural.JUnitEventDispatcher

public final class JUnitEventDispatcher
extends AbstractEventDispatcher

A JUnitEventDispatcher is designed to be used by a specially modified JUnit test runner to dispatch an event stream from JUnit test cases run on instrumented code.

The JUnitEventDispatcher does not provide any mechanism for invoking a subject class in a separate virtual machine, has a restricted set of configuration options, and exposes special methods for controlling the dispatch of distinct event streams. It is expected that an instance of a JUnitEvent Dispatcher class will be created inside a JUnit test runner. Instrumented JUnit test suites and test cases can then be run, using a TestListener (part of the JUnit framework) to handle processing of per-test event streams at the appropriate times (as by writing a trace file, for example). It is strongly recommended that the listener regularly issue calls to the checkError() method to ensure timely termination in the event of a failure. This class requires that the subject classes be instrumented using the 'junit' mode of instrumentation (see cfInstrumentor).

This class cannot be run directly from the command line.

Version:
03/15/2006
Author:
Alex Kinneer

Nested Class Summary
static class JUnitEventDispatcher.InstrumentationMode
          Callback class used to safely transfer the instrumentation mode constant to the processing strategy.
 
Nested classes/interfaces inherited from class sofya.ed.structural.AbstractEventDispatcher
AbstractEventDispatcher.CreateException, AbstractEventDispatcher.ExecException, AbstractEventDispatcher.SetupException, AbstractEventDispatcher.TraceFileException
 
Field Summary
protected static java.lang.String currentMethodSig
          Stores the signature string of the method for which objects are currently being recorded.
protected static gnu.trove.TIntObjectHashMap indexToNameMap
          Maps indices following new method markers to the signature string for that method.
protected static boolean instError
          Flag which indicates if an instrumentation error (wrong mode of instrumentation) has been detected.
protected static int instMode
          Indicates the type of instrumentation present in the subject.
protected static java.util.LinkedList methodSigStack
          Stack which holds the signatures of methods on the call stack.
protected static CoverageTrace methodTrace
          Current trace being recorded.
protected static gnu.trove.TObjectIntHashMap nameToIndexMap
          Maps signature strings for a method to an already assigned index, if any.
protected static int nextMethodIndex
          Holds the next value available for use as an index to a method signature string.
protected static int OBJECT_ARRAY_CACHE_SIZE
          Maximum number of methods for which byte arrays can be cached when handling optimized normal instrumentation.
protected static int SEQUENCE_ARRAY_SIZE
          Size of the array which records object sequence information when handling optimized sequence instrumentation.
static int[] sequenceArray
          Array which stores the executed object IDs sequentially, using special marker/index pairs to indicate entry into new methods.
static int sequenceIndex
          Index pointing to the next open entry in the sequence array.
protected static sofya.ed.structural.JUnitEventDispatcher.LRUTraceMap traceObjArrays
          LRU cache which holds the byte arrays recording which objects have been hit in each method.
 
Fields inherited from class sofya.ed.structural.AbstractEventDispatcher
dispatcherReady, isInstrumented
 
Method Summary
static void checkError()
          Checks whether any exceptions have been raised during processing, and rethrows the exception for handling if so.
 boolean checkInstrumented()
          Checks whether the last test case was instrumented.
static JUnitEventDispatcher createEventDispatcher(JUnitProcessingStrategy strategy)
          Factory method that returns a singleton instance of the event dispatcher.
 void endTest(int testNumber)
          Signals that the current test case has finished executing.
static void finish()
          Ensures that all data currently in the cache is written to the trace, guaranteeing that it will be complete.
static byte[] getBlockArray(java.lang.String mSignature, int blockCount)
          Maps to an equivalent call to getObjectArray(java.lang.String, int); this method is retained for backwards compatibility with previous instrumentation.
 int getInstrumentationMode()
          Reports the instrumentation mode detected in the subject.
static byte[] getObjectArray(java.lang.String mSignature, int objCount)
          Gets the byte array recording which objects have been covered in a given method.
 JUnitProcessingStrategy getProcessingStrategy()
          Gets the processing strategy currently in use by this event dispatcher to receive probes from the subject.
static void markMethodInSequence(java.lang.String mSignature, int objCount)
          Inserts a new method marker and index into the sequence array.
 void newTest(int testNumber)
          Signals that a new test case is executing.
 void register(EventDispatcherConfiguration edc)
          Registers the processing strategy and any attached components.
 void release()
          Releases this event dispatcher, its processing strategy, and any attached components.
protected  void reset()
          Clears instrumentation data structures (for the next test case).
 void setProcessingStrategy(JUnitProcessingStrategy procStrategy)
          Specifies the processing strategy to be used by this event dispatcher to receive probes from the subject.
protected static void setup(int _instMode)
          Initializes the data structures necessary to process the instrumentation detected in the subject.
static void start(int port, int _instMode, boolean _doTimestamps, boolean _useSignalSocket, int _entityType)
          Checks that the type of instrumentation can be handled by the a JUnit event dispatcher.
 void startDispatcher()
          Initializes the event dispatcher such that it is ready to process instrumentation and dispatch event streams.
static void writeBlockCount(java.lang.String mSignature, int blockCount)
          Notifies the event dispatcher of the number of basic blocks in the current method, to be reported to the processing strategy and any interested listeners.
static void writeObjectCount(java.lang.String mSignature, int objCount)
          Notifies the event dispacher of the number of structural objects in the current method, to be reported to the processing strategy and any interested listeners.
static void writeSequenceData()
          Writes the current contents of the object sequence array to the trace.
static void writeTraceMessage(int bId, java.lang.String mSignature)
          Marks a single object in the trace; used by the compatible mode instrumentation.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

instMode

protected static int instMode
Indicates the type of instrumentation present in the subject. Note that this is automatically detected, and the dispatcher will reject subjects with mixed instrumentation.


OBJECT_ARRAY_CACHE_SIZE

protected static final int OBJECT_ARRAY_CACHE_SIZE
Maximum number of methods for which byte arrays can be cached when handling optimized normal instrumentation.

See Also:
Constant Field Values

SEQUENCE_ARRAY_SIZE

protected static final int SEQUENCE_ARRAY_SIZE
Size of the array which records object sequence information when handling optimized sequence instrumentation.

See Also:
Constant Field Values

traceObjArrays

protected static sofya.ed.structural.JUnitEventDispatcher.LRUTraceMap traceObjArrays
LRU cache which holds the byte arrays recording which objects have been hit in each method. If the cache fills, data is written to the trace before the oldest array is removed from the cache.


methodTrace

protected static CoverageTrace methodTrace
Current trace being recorded.


sequenceArray

public static int[] sequenceArray
Array which stores the executed object IDs sequentially, using special marker/index pairs to indicate entry into new methods. It is public so that the instrumentation is not required to make a method call to retrieve a reference to it.


sequenceIndex

public static int sequenceIndex
Index pointing to the next open entry in the sequence array. Instrumentation is responsible for updating this pointer when recording an object ID, and calling writeSequenceData when the array is filled.


currentMethodSig

protected static java.lang.String currentMethodSig
Stores the signature string of the method for which objects are currently being recorded. This is required when object IDs for a method bridge an array transmit-and-reset event.


indexToNameMap

protected static gnu.trove.TIntObjectHashMap indexToNameMap
Maps indices following new method markers to the signature string for that method.


nameToIndexMap

protected static gnu.trove.TObjectIntHashMap nameToIndexMap
Maps signature strings for a method to an already assigned index, if any.


nextMethodIndex

protected static int nextMethodIndex
Holds the next value available for use as an index to a method signature string.


methodSigStack

protected static java.util.LinkedList methodSigStack
Stack which holds the signatures of methods on the call stack. Used in basic block sequence tracing to ensure that blocks are associated with the correct method after returning from a called method.


instError

protected static boolean instError
Flag which indicates if an instrumentation error (wrong mode of instrumentation) has been detected. It is used to suppress repeat messages.

Method Detail

createEventDispatcher

public static JUnitEventDispatcher createEventDispatcher(JUnitProcessingStrategy strategy)
Factory method that returns a singleton instance of the event dispatcher.

A singleton strategy is enforced because much of the class data is static, and must be to enable the instrumentation to work. If a completely new instance is desired, call release() and then call this method.

Parameters:
strategy - Processing strategy to be used to process probes received from the instrumentation.
Returns:
A new event dispatcher, or a reference to the existing singleton instance if this method has already been called and release() has not yet been called.

getProcessingStrategy

public JUnitProcessingStrategy getProcessingStrategy()
Gets the processing strategy currently in use by this event dispatcher to receive probes from the subject.

Returns:
The processing strategy that this event dispatcher is configured to use to receive probes from the subject.

setProcessingStrategy

public void setProcessingStrategy(JUnitProcessingStrategy procStrategy)
Specifies the processing strategy to be used by this event dispatcher to receive probes from the subject.

Parameters:
procStrategy - The processing strategy to be used by this event dispatcher to receive probes from the subject.

getInstrumentationMode

public int getInstrumentationMode()
Reports the instrumentation mode detected in the subject.

Returns:
The numeric constant for the instrumentation mode detected in the subject (e.g. coverage, sequence, compatibility).

register

public void register(EventDispatcherConfiguration edc)
Registers the processing strategy and any attached components.

Parameters:
edc - The global event dispatcher configuration for this event dispatcher.

release

public void release()
Releases this event dispatcher, its processing strategy, and any attached components.


setup

protected static void setup(int _instMode)
Initializes the data structures necessary to process the instrumentation detected in the subject. All invocations subsequent to the first must specify the same form of instrumentation, or the method will fail. In practice it should only be called once.

Parameters:
_instMode - Type of instrumentation detected in the subject.
Throws:
java.lang.IllegalStateException - If this method has previously been called with a different mode of instrumentation.

reset

protected void reset()
Clears instrumentation data structures (for the next test case).


startDispatcher

public void startDispatcher()
Initializes the event dispatcher such that it is ready to process instrumentation and dispatch event streams.

Specified by:
startDispatcher in class AbstractEventDispatcher
Throws:
SetupException - If there is an error attempting to set up this event dispatcher to receive instrumentation.

newTest

public void newTest(int testNumber)
Signals that a new test case is executing.

Some event stream observers may need to perform setup before handling a new event stream, such as opening a new trace file.

This method resets the flag indicating whether a test case was instrumented.

Parameters:
testNumber - Number associated with the current test.

endTest

public void endTest(int testNumber)
             throws AbstractEventDispatcher.TraceFileException
Signals that the current test case has finished executing.

Some event stream observers may need to take some kind of action here, such as saving or storing a trace file.

Data structures for handling* instrumentation will be reset for the next test case.

Throws:
AbstractEventDispatcher.TraceFileException

checkInstrumented

public boolean checkInstrumented()
Checks whether the last test case was instrumented.

If the test case executed instrumented code, this method will return true until the next call to newTest(int), otherwise it returns false.

Returns:
true if the last test case executed instrumented code and newTraceFile has not yet been called, false otherwise.

checkError

public static void checkError()
                       throws java.lang.Exception
Checks whether any exceptions have been raised during processing, and rethrows the exception for handling if so. This method returns without action if there are no errors.

Throws:
java.lang.Exception - For any exception that was raised and stored.

start

public static void start(int port,
                         int _instMode,
                         boolean _doTimestamps,
                         boolean _useSignalSocket,
                         int _entityType)
Checks that the type of instrumentation can be handled by the a JUnit event dispatcher. This also makes the instrumentor implementation easier by allowing it to simply change the name of the class the instrumentation related methods are invoked on depending on what type of instrumentation it has been directed to insert.

Note: It is not necessary for a subject to call this method for the event dispatcher to work (assuming the instrumentation is appropriate). This method is merely provided to assist the instrumentor.

Parameters:
port - Ignored.
_instMode - Flag indicating the type of instrumentation present in the subject. All types are supported as long as the instrumentation is targeted for a JUnit event dispatcher.
_doTimestamps - Ignored.
_useSignalSocket - Ignored.
_entityType - Ignored

finish

public static void finish()
Ensures that all data currently in the cache is written to the trace, guaranteeing that it will be complete.


writeBlockCount

public static void writeBlockCount(java.lang.String mSignature,
                                   int blockCount)
Notifies the event dispatcher of the number of basic blocks in the current method, to be reported to the processing strategy and any interested listeners.

This method is retained for compatibility with previous instrumentation.

Parameters:
mSignature - Signature of the method for which the basic block count is being sent.
blockCount - Number of basic blocks in the method.

writeObjectCount

public static void writeObjectCount(java.lang.String mSignature,
                                    int objCount)
Notifies the event dispacher of the number of structural objects in the current method, to be reported to the processing strategy and any interested listeners.

Parameters:
mSignature - Signature of the method for which the object count is being sent.
objCount - Number of objects in the method.

writeTraceMessage

public static void writeTraceMessage(int bId,
                                     java.lang.String mSignature)
Marks a single object in the trace; used by the compatible mode instrumentation.

Parameters:
bId - The ID of the object marked by this instrumentation statement.
mSignature - Signature of the method owning the object.

getBlockArray

public static byte[] getBlockArray(java.lang.String mSignature,
                                   int blockCount)
Maps to an equivalent call to getObjectArray(java.lang.String, int); this method is retained for backwards compatibility with previous instrumentation.

Parameters:
mSignature - Signature of the method for which the byte array is to be retrieved. The signature guarantees uniqueness.
blockCount - Number of basic blocks in the method, used only when the array must be allocated. This value should be determined by the CFG builder and set by the instrumentor.
Returns:
The byte array recording basic blocks covered in the method.

getObjectArray

public static byte[] getObjectArray(java.lang.String mSignature,
                                    int objCount)
Gets the byte array recording which objects have been covered in a given method.

If this is the first time the method has been traced (or the method has been removed from the cache), an array of the necessary size is allocated and initialized. Calls to this method are inserted at the beginning of methods in the subject by the instrumentor.

Parameters:
mSignature - Signature of the method for which the byte array is to be retrieved. The signature guarantees uniqueness.
objCount - Number of objects in the method, used only when the array must be allocated. This value should be determined by the CFG builder and set by the instrumentor.
Returns:
The byte array recording objects covered in the method.

markMethodInSequence

public static void markMethodInSequence(java.lang.String mSignature,
                                        int objCount)
Inserts a new method marker and index into the sequence array. (See SocketProbe.markMethodInSequence(java.lang.String, int)).

Parameters:
mSignature - Signature of the method which has been entered and needs to be marked in the array.
objCount - Number of objects in the method.

writeSequenceData

public static void writeSequenceData()
Writes the current contents of the object sequence array to the trace. (See SocketProbe.writeSequenceData()).