korat.instrumentation
Class FieldInstrumenter

java.lang.Object
  extended by korat.instrumentation.AbstractInstrumenter
      extended by korat.instrumentation.FieldInstrumenter
All Implemented Interfaces:
IInstrumenter
Direct Known Subclasses:
ArrayFieldInstrumenter

 class FieldInstrumenter
extends AbstractInstrumenter

This class does all the instrumentation related to non-array fields. For all declared fields, this instrumenter does the following:

Then, in all methods, all accesses to those fields are replaced with the call to "special getter" method, which, before returning the value of the field informs the Korat search engine about that particular field access. Korat uses this information to prune large amount of the potentially huge state space, thus improving efficiency a lot. For more info see handleFieldDeclaration(CtClass, CtField), handleFieldDeclaration(CtClass, CtField).

Setter classes serve for improving performance when building test case from the candidate vector because this technique does not use (slow) java reflection mechanism. For more info see handleFieldDeclaration(CtClass, CtField) createNestedSetterClass(CtClass, CtField)

Author:
Aleksandar Milicevic
See Also:
AbstractInstrumenter, ArrayFieldInstrumenter, SpecialConstructorInstrumenter

Field Summary
 
Fields inherited from class korat.instrumentation.AbstractInstrumenter
cp
 
Constructor Summary
FieldInstrumenter()
           
 
Method Summary
protected  void addGetSetterMethod(CtClass clz, CtField f)
          Adds getter method for the setter of the given field.
protected  void addGetterMethod(CtClass clz, CtField f)
          Adds special getter method which before returning the value of the field notifies the instance of the ITestCradle about the field access.
protected  void addIdField(CtClass clz, CtField f)
          Just adds one extra int field.
protected  void createNestedSetterClass(CtClass clz, CtField f)
           Nested setter classes are implemented in the following way: static nested classes have constructor that takes one parameter of the type same as type of clz parameter.
protected  String getGetSetterSrc(CtClass clz, String fieldName, String idFieldName, String setterClassName)
          Returns source code for the "get setter" method.
protected  String getGetterSrc(CtClass clz, String fieldName, String idFieldName)
          Returns the source for the "korat getter method".
private  String getSetterSrc(CtField f)
          Source for the setter's set method.
protected  void handleFieldDeclaration(CtClass clz, CtField f)
          For the given field: adds "id field" of type int adds special getter method creates nested setter class adds get setter method For each field, "id filed" is added to store its index in the candidate vector.
protected  void instrument(CtClass clz)
           
protected  void instrumentFieldDeclarations(CtClass clz)
           For each field in the given class adds additional stuff needed for instrumentation (by calling handleFieldDeclaration.
protected  void replaceFieldAccesses(CtClass clz)
           Searches for all read field accesses (GETFIELD instructions) and replaces them with appropriate getter method call (those getter methods that were generated in the addGetterMethod operation).
 
Methods inherited from class korat.instrumentation.AbstractInstrumenter
getBytecode, shouldProcessField, shouldProcessMethod
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

FieldInstrumenter

FieldInstrumenter()
Method Detail

instrument

protected void instrument(CtClass clz)
                   throws CannotCompileException,
                          NotFoundException,
                          IOException
Specified by:
instrument in class AbstractInstrumenter
Throws:
CannotCompileException
NotFoundException
IOException

instrumentFieldDeclarations

protected void instrumentFieldDeclarations(CtClass clz)
                                    throws NotFoundException,
                                           CannotCompileException

For each field in the given class adds additional stuff needed for instrumentation (by calling handleFieldDeclaration. Fields of type array are not handled by this class.

Parameters:
clz -
Throws:
CannotCompileException
NotFoundException

handleFieldDeclaration

protected void handleFieldDeclaration(CtClass clz,
                                      CtField f)
                               throws NotFoundException,
                                      CannotCompileException
For the given field:

For each field, "id filed" is added to store its index in the candidate vector. These indices remain the same during the state space exploration so it is a good idea to calculate them only once at the beginning of the exploration and to keep them for the rest of execution. It is most efficient to do that this way, with one extra "id field" per field.

Special getter method has to inform the instance of the ITestCradle that the field has been accessed before returning the value of the requested field. In order to do that, it first checks if the corresponding "id field" is equal to -1. If it is, it retrieves index in the candidate vector for the requested field (time consuming operation) and stores it in the "id field". After that, notifies ITestCradle that the element with index "id field" has been accessed.

Nested setter classes are used to improve performances. They extend ISetter abstract class and override one appropriate method that the ICandidateBuilder will call in order to build object (test case) from the IStateSpace. This is efficient way to build test case because it avoids using java reflection. Static nested classes can access and set fields directly. It would be more convenient to use inner nested classes, but Javassist doesn't provide support for them.

Get setter method just returns previously created ISetter class for the given field.

Parameters:
clz -
f -
Throws:
CannotCompileException
NotFoundException

addIdField

protected void addIdField(CtClass clz,
                          CtField f)
                   throws CannotCompileException
Just adds one extra int field. It's important to set its initial value to -1 denoting that id is not yet initialized.

Parameters:
clz -
f -
Throws:
CannotCompileException

addGetterMethod

protected void addGetterMethod(CtClass clz,
                               CtField f)
                        throws NotFoundException,
                               CannotCompileException
Adds special getter method which before returning the value of the field notifies the instance of the ITestCradle about the field access.

Parameters:
clz -
f -
Throws:
NotFoundException
CannotCompileException

getGetterSrc

protected String getGetterSrc(CtClass clz,
                              String fieldName,
                              String idFieldName)
Returns the source for the "korat getter method". It looks something like the following:
     public int __korat_get_foo() {
         if (__myTester != null)
             __myTester.notifyFieldAccess(__id_foo);
         return foo;
     }  
 

Parameters:
clz -
fieldName -
idFieldName -
Returns:
the source for the "korat getter method"

replaceFieldAccesses

protected void replaceFieldAccesses(CtClass clz)
                             throws CannotCompileException

Searches for all read field accesses (GETFIELD instructions) and replaces them with appropriate getter method call (those getter methods that were generated in the addGetterMethod operation).

Parameters:
clz -
Throws:
CannotCompileException

createNestedSetterClass

protected void createNestedSetterClass(CtClass clz,
                                       CtField f)
                                throws NotFoundException,
                                       CannotCompileException

Nested setter classes are implemented in the following way:

Parameters:
clz -
f -
Throws:
NotFoundException
CannotCompileException

getSetterSrc

private String getSetterSrc(CtField f)
                     throws NotFoundException
Source for the setter's set method. It looks something like this:
     public void set(Object val) {
         ___this.foo = (Foo)val;
     }
 

Parameters:
f - field that should be set
Returns:
the source code for the setter's set method
Throws:
NotFoundException

addGetSetterMethod

protected void addGetSetterMethod(CtClass clz,
                                  CtField f)
                           throws NotFoundException,
                                  CannotCompileException
Adds getter method for the setter of the given field.

Parameters:
clz -
f -
Throws:
NotFoundException
CannotCompileException

getGetSetterSrc

protected String getGetSetterSrc(CtClass clz,
                                 String fieldName,
                                 String idFieldName,
                                 String setterClassName)
Returns source code for the "get setter" method. It looks something like:
     public ISetter __korat_get_foo_setter(int fieldId) {
         this.__id_foo = fieldId;
         return new Korat_foo_setter(this);
     }
 

Parameters:
clz -
fieldName -
idFieldName -
setterClassName -
Returns:
source code for the "get setter" method