-
Notifications
You must be signed in to change notification settings - Fork 15
Smart Seeding
The function of smart seed allows us to pick up the most relevant seeds for individual branch, which can further expedite the testing efficiency.
Comparing to a global constant pool maintained by Evosuite, we construct a pool for each individual branch. First, we check whether a branch is appropriate to maintain a pool (readers may refer to our to-be-published paper for more reference). If it does, we will check whether we need to maintain a static constant pool, dynamic constant pool, or both. Here, the tricky part is we need to modify the instrumentation for maintaining branchwise dynamic constant pool.
I leave the details here for students to follow the implementation.
First of all, according to the implementation of Evosuite, the dynamic constant pool gain its value via testability transformation.
Specifically, Evosuite will transform a boolean-value method such as boolean String.equals(a, b)
method into a integer-value method int String.equals(a, b)
by replace its return value.
Then, it adds the method operands into dynamic constant pool.
Therefore, in order to link the pool to a branch, we need to additionally instrument branch (or branch instruction) information into the method, e.g., int String.equals(a, b, method, bytecode_id)
.
In Evosuite++, we create a method int org.evosuite.instrumentation.testability.StringHelper.StringEquals(String first, Object second, String methodSig, int index)
to this end.
Here, we copy and paste the original StringEquals()
method, modify its parameters, and let branchwise constant pool to retrieve operands if Properties.APPLY_SMART_SEED
is enabled.
In the method ofStringTransformation.transformStrings(ClassNode cn, MethodNode mn)()
, it defines a lot of testability transformation such as String.equals()
, String.equalsIgnoreCase()
, String.endsWith()
, etc.
Here, we take String.equals()
for example.
In the corresponding code, we instrument the following lines to prepare two more variables:
LdcInsnNode methodSig = new LdcInsnNode(cn.name + "#" + mn.name + mn.desc);
mn.instructions.insertBefore(node, methodSig);
IntInsnNode indexNode = new IntInsnNode(Opcodes.SIPUSH, index-1);
mn.instructions.insertBefore(node, indexNode);
Then, we call the prepared method with the following code:
MethodInsnNode equalCheck = new MethodInsnNode(
Opcodes.INVOKESTATIC,
Type.getInternalName(StringHelper.class),
"StringEquals",
Type.getMethodDescriptor(Type.INT_TYPE,
new Type[] {
Type.getType(String.class),
Type.getType(Object.class),
Type.getType(String.class),
Type.INT_TYPE
}), false);
Finally, we increase the max stack size by 3 in .StringTransformation.transformMethod()
, as:
mn.maxStack = mn.maxStack + 3;