Skip to content

Commit

Permalink
Working on instrumentation for exceptions
Browse files Browse the repository at this point in the history
  • Loading branch information
arcuri82 committed Jun 2, 2017
1 parent f13ea40 commit 22b5403
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ public class ExecutionTracer {
public static final String FALSE_BRANCH = "_falseBranch";


/**
* Prefix identifier for objectives related to calling methods without exceptions
*/
public static final String SUCCESS_CALL = "Success_Call";


/**
* Key -> the unique id of the coverage objective
* <br>
Expand Down Expand Up @@ -140,6 +146,28 @@ public static void executedLine(String className, int line) {
updateObjective(id, 1d);
}

public static final String EXECUTING_METHOD_METHOD_NAME = "executingMethod";
public static final String EXECUTING_METHOD_DESCRIPTOR = "(Ljava/lang/String;IIZ)V";

/**
* Report on whether method calls have been successfully completed.
* Failures can happen due to thrown exceptions.
*
* @param className
* @param line
* @param index as there can be many method calls on same line, need to differentiate them
* @param completed whether the method call was successfully completed.
*/
public static void executingMethod(String className, int line, int index, boolean completed){
String id = SUCCESS_CALL + "_at_" + ClassName.get(className).getFullNameWithDots() +
"_" + padNumber(line) + "_" + index;
if(completed) {
updateObjective(id, 1d);
} else {
updateObjective(id, 0.5);
}
}


//---- branch-jump methods --------------------------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,7 @@ Methods added by the compiler (eg synthetics and bridges) are

mv = new LineCovMethodVisitor(mv, bytecodeClassName, name, descriptor);
mv = new BranchCovMethodVisitor(mv, bytecodeClassName, name, descriptor);

/*
TODO: we will also need to handle exceptions.
This is tricky: the line that
throws the exception should be marked as 0.5 for
line coverage, and a new objective for thrown
exceptions at that line should be created.
But maybe not needed for a first prototype version...
*/
//mv = new SuccessCallMethodVisitor(mv, bytecodeClassName, name, descriptor);

return mv;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package org.evomaster.clientJava.instrumentation.visitor;

import org.evomaster.clientJava.instrumentation.ClassName;
import org.evomaster.clientJava.instrumentation.Constants;
import org.evomaster.clientJava.instrumentation.staticState.ExecutionTracer;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

/**
* Add test objectives to make sure methods are called without
* throwing an exception.
*
* TODO: should also handle the cases of accessing arrays out
* of bounds.
*/
public class SuccessCallMethodVisitor extends MethodVisitor {

private final String className;
private final String methodName;

private int currentLine;
private int currentIndex;

public SuccessCallMethodVisitor(MethodVisitor mv,
String className,
String methodName,
String descriptor) {
super(Constants.ASM, mv);

this.className = className;
this.methodName = methodName;
currentLine = 0;
}

@Override
public void visitLineNumber(int line, Label start) {
currentLine = line;
currentIndex = 0; //reset it for current line
}

@Override
public void visitMethodInsn(int opcode, String owner, String name,
String desc, boolean itf) {

//don't instrument static initializers
if(methodName.equals(Constants.CLASS_INIT_METHOD)){
super.visitMethodInsn(opcode, owner, name, desc, itf);
return;
}

int index = currentIndex++;

addInstrumentation(index, false);
super.visitMethodInsn(opcode, owner, name, desc, itf);
addInstrumentation(index, true);
}


private void addInstrumentation(int index, boolean covered){

this.visitLdcInsn(className);
this.visitLdcInsn(currentLine);
this.visitLdcInsn(index);
this.visitLdcInsn(covered);

mv.visitMethodInsn(
Opcodes.INVOKESTATIC,
ClassName.get(ExecutionTracer.class).getBytecodeName(),
ExecutionTracer.EXECUTING_METHOD_METHOD_NAME,
ExecutionTracer.EXECUTING_METHOD_DESCRIPTOR,
ExecutionTracer.class.isInterface());
}

@Override
public void visitMaxs(int maxStack, int maxLocals) {
/*
We pushed 4 values on stack before a method call,
so we need to increase maxStack by at least 3
*/
super.visitMaxs(maxStack + 4, maxLocals);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.foo.somedifferentpackage.examples.exceptions;

public class ThrownExcImp {

public String directReturn(Object obj){
return obj.toString();
}

public String directInTry(Object obj){
try{
return obj.toString();
} catch (Exception e){
throw e;
}
}

public String doubleCall(Object x, Object y){
return x.toString() + y.toString();
}

public String callOnArray(Object[] array, int index){
return array[index].toString();
}
}
6 changes: 5 additions & 1 deletion notes.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
Links related to deploy to Maven Central:
- https://maven.apache.org/guides/mini/guide-central-repository-upload.html
- http://central.sonatype.org/pages/ossrh-guide.html
- http://central.sonatype.org/pages/ossrh-guide.html

Useful links:
- Kotlin: https://kotlinlang.org/docs/kotlin-docs.pdf
- ASM: http://download.forge.objectweb.org/asm/asm4-guide.pdf

0 comments on commit 22b5403

Please sign in to comment.