Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve json report of coverage selector and comments generated during assertion #956

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,8 @@
import eu.stamp_project.dspot.amplifier.amplifiers.value.ValueCreatorHelper;
import eu.stamp_project.dspot.common.miscellaneous.CloneHelper;
import eu.stamp_project.dspot.amplifier.amplifiers.utils.RandomHelper;
import spoon.reflect.code.CtBlock;
import spoon.reflect.code.CtBodyHolder;
import spoon.reflect.code.CtExpression;
import spoon.reflect.code.CtInvocation;
import spoon.reflect.code.CtLocalVariable;
import spoon.reflect.code.CtStatement;
import spoon.reflect.code.CtStatementList;
import eu.stamp_project.dspot.common.miscellaneous.DSpotUtils;
import spoon.reflect.code.*;
import spoon.reflect.declaration.CtElement;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.declaration.CtParameter;
Expand Down Expand Up @@ -69,7 +64,8 @@ public static CtMethod<?> addInvocation(CtMethod<?> testMethod,
CtMethod<?> methodToInvokeToAdd,
CtExpression<?> target,
CtStatement position,
String suffix) {
String suffix,
String comment) {
final Factory factory = testMethod.getFactory();
CtMethod methodClone = CloneHelper.cloneTestMethodForAmp(testMethod, suffix);

Expand Down Expand Up @@ -99,14 +95,15 @@ public static CtMethod<?> addInvocation(CtMethod<?> testMethod,
localVariable = ValueCreator.createRandomLocalVar(parameter.getType(), parameter.getSimpleName());
}
body.insertBegin(localVariable);
DSpotUtils.addComment(localVariable, comment, CtComment.CommentType.INLINE);
arguments.add(factory.createVariableRead(localVariable.getReference(), false));
} catch (Exception e) {
throw new RuntimeException(e);
}
});
CtExpression targetClone = target.clone();
CtInvocation newInvocation = factory.Code().createInvocation(targetClone, methodToInvokeToAdd.getReference(), arguments);
//DSpotUtils.addComment(newInvocation, "MethodGenerator", CtComment.CommentType.INLINE);
DSpotUtils.addComment(newInvocation, comment, CtComment.CommentType.INLINE);
body.insertEnd(newInvocation);
return methodClone;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ private CtMethod<?> createNumberMutant(CtMethod<?> method, int original_lit_inde
//get the lit_indexth literal of the cloned method
CtLiteral newLiteral = Query.getElements(cloned_method.getBody(), new LiteralToBeMutedFilter())
.get(original_lit_index);
Object oldValue = newLiteral.getValue();

CtElement toReplace = newLiteral;

Expand All @@ -110,7 +111,7 @@ private CtMethod<?> createNumberMutant(CtMethod<?> method, int original_lit_inde
}
toReplace.replace(newLiteral);
Counter.updateInputOf(cloned_method, 1);
DSpotUtils.addComment(toReplace, "FastLiteralAmplifier on numbers", CtComment.CommentType.INLINE);
addComment(toReplace, "number", oldValue, newValue);
return cloned_method;
}

Expand All @@ -132,8 +133,9 @@ private CtMethod<?> createStringMutant(CtMethod<?> method, int original_lit_inde
Counter.updateInputOf(cloned_method, 1);
CtLiteral toReplace = Query.getElements(cloned_method.getBody(), new LiteralToBeMutedFilter())
.get(original_lit_index);
Object oldValue = toReplace.getValue();
toReplace.replace(cloned_method.getFactory().Code().createLiteral(newValue));
DSpotUtils.addComment(toReplace, "FastLiteralAmplifier on strings", CtComment.CommentType.INLINE);
addComment(toReplace, "string", oldValue, newValue);
return cloned_method;
}

Expand All @@ -148,8 +150,9 @@ private CtMethod<?> createCharacterMutant(CtMethod method, int original_lit_inde
Counter.updateInputOf(cloned_method, 1);
CtLiteral toReplace = Query.getElements(cloned_method.getBody(), new LiteralToBeMutedFilter())
.get(original_lit_index);
Object oldValue = toReplace.getValue();
toReplace.replace(cloned_method.getFactory().Code().createLiteral(newValue));
DSpotUtils.addComment(toReplace, "FastLiteralAmplifier on strings", CtComment.CommentType.INLINE);
addComment(toReplace, "char", oldValue, newValue);
return cloned_method;
}

Expand Down Expand Up @@ -223,7 +226,7 @@ public boolean matches(CtLiteral element) {
newValue.setValue(!value);
newValue.setTypeCasts(booleanLiteral.getTypeCasts());
Counter.updateInputOf(cloned_method, 1);
DSpotUtils.addComment(newValue, "FastLiteralAmplifier on boolean", CtComment.CommentType.INLINE);
addComment(newValue, "boolean", value, !value);
return cloned_method;
}

Expand All @@ -243,4 +246,8 @@ private Set<Object> getLiterals(CtType type) {
}
return literalByClass.get(type);
}

private void addComment(CtElement element, String kind, Object oldValue, Object newValue) {
DSpotUtils.addComment(element, "FastLiteralAmplifier: change " + kind + " from '" + oldValue + "' to '" + newValue + "'", CtComment.CommentType.INLINE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ public Stream<CtMethod<?>> amplify(CtMethod<?> testMethod, int iteration) {
methodToBeAdd,
AmplifierHelper.createLocalVarRef(existingObject),
existingObject,
"_mg")
"_mg",
"MethodAdderOnExistingObjectsAmplifier: added method on existing object")
).map(amplifiedTestMethod -> {
Counter.updateInputOf(amplifiedTestMethod, 1);
return amplifiedTestMethod;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package eu.stamp_project.dspot.amplifier.amplifiers;

import eu.stamp_project.dspot.common.miscellaneous.DSpotUtils;
import eu.stamp_project.dspot.common.test_framework.TestFramework;
import eu.stamp_project.dspot.amplifier.amplifiers.utils.AmplificationChecker;
import eu.stamp_project.dspot.common.miscellaneous.AmplificationHelper;
import eu.stamp_project.dspot.common.miscellaneous.CloneHelper;
import eu.stamp_project.dspot.common.miscellaneous.Counter;
import spoon.reflect.code.CtBlock;
import spoon.reflect.code.CtExpression;
import spoon.reflect.code.CtInvocation;
import spoon.reflect.code.CtStatement;
import spoon.reflect.code.*;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.declaration.CtType;
import spoon.reflect.visitor.filter.TypeFilter;
Expand Down Expand Up @@ -53,6 +51,7 @@ private CtMethod<?> apply(CtMethod<?> method, CtInvocation<?> invocation) {
removeAllTypeCast(invocationToBeInserted);
final CtStatement insertionPoint = this.getRightInsertionPoint(invocation);
insertionPoint.insertBefore(invocationToBeInserted);
DSpotUtils.addComment(invocationToBeInserted, "MethodDuplicationAmplifier: duplicated method call", CtComment.CommentType.INLINE);
final CtMethod<?> clone = CloneHelper.cloneTestMethodForAmp(method, "_add");
AmplifierHelper.getParent(invocationToBeInserted).getStatements().remove(invocationToBeInserted);
Counter.updateInputOf(clone, 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public Stream<CtMethod<?>> amplify(CtMethod<?> testMethod, int iteration) {
);
DSpotUtils.addComment(localVar, "StatementAdd: generate variable from return value", CtComment.CommentType.INLINE);
ampMethods.addAll(methodsWithTargetType.stream()
.map(addMth -> AmplifierHelper.addInvocation(methodClone, addMth, target, localVar, "_rv"))
.map(addMth -> AmplifierHelper.addInvocation(methodClone, addMth, target, localVar, "_rv", "ReturnValueAmplifier: add method call"))
.collect(Collectors.toList()));
Counter.updateInputOf(methodClone, 1);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,8 @@
import spoon.reflect.factory.Factory;
import spoon.reflect.visitor.Query;
import spoon.reflect.visitor.filter.TypeFilter;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

import java.util.*;
import java.util.stream.Collectors;

/**
Expand Down Expand Up @@ -120,23 +118,23 @@ private CtMethod<?> buildTestWithAssert(CtMethod test, Map<String, Observation>
an assertion identical to the last assertion put into the test method */
if (assertStatements.stream()
.map(Object::toString)
.map("// AssertionGenerator add assertion\n"::concat)
.map("// AssertionGenerator: add assertion\n"::concat)
.anyMatch(testWithAssert.getBody().getLastStatement().toString()::equals)) {
continue;
}
goThroughAssertionStatements(assertStatements,id,statements,numberOfAddedAssertion);
numberOfAddedAssertion = goThroughAssertionStatements(assertStatements,id,statements,numberOfAddedAssertion);
}
Counter.updateAssertionOf(testWithAssert, numberOfAddedAssertion);
return decideReturn(testWithAssert,test);
}

private void goThroughAssertionStatements(List<CtStatement> assertStatements,String id,
List<CtStatement> statements,Integer numberOfAddedAssertion){
private int goThroughAssertionStatements(List<CtStatement> assertStatements,String id,
List<CtStatement> statements, int numberOfAddedAssertion){
int line = Integer.parseInt(id.split("__")[1]);
CtStatement lastStmt = null;
for (CtStatement assertStatement : assertStatements) {
DSpotUtils.addComment(assertStatement,
"AssertionGenerator add assertion",
"AssertionGenerator: add assertion",
CtComment.CommentType.INLINE);
try {
CtStatement statementToBeAsserted = statements.get(line);
Expand All @@ -153,6 +151,7 @@ private void goThroughAssertionStatements(List<CtStatement> assertStatements,Str
throw new RuntimeException(e);
}
}
return numberOfAddedAssertion;
}

private void decideInvocationReplacement(CtStatement statementToBeAsserted,String id,CtStatement assertStatement,
Expand Down Expand Up @@ -184,8 +183,15 @@ private void replaceInvocation(CtStatement statementToBeAsserted,String id,CtSta

// put the new local variable into the assertion and the assertion into the test method
statementToBeAsserted.replace(localVariable);
// move comments from invocation to new variable statement
List<CtComment> invocationComments = new ArrayList<>(statementToBeAsserted.getComments());
invocationComments.forEach(comment -> {
invocationToBeReplaced.removeComment(comment);
localVariable.addComment(comment);
});

DSpotUtils.addComment(localVariable,
"AssertionGenerator create local variable with return value of invocation",
"AssertionGenerator: create local variable with return value of invocation",
CtComment.CommentType.INLINE);
localVariable.setParent(statementToBeAsserted.getParent());
addAtCorrectPlace(id, localVariable, assertStatement, statementToBeAsserted);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,21 +64,24 @@ public static Integer getAssertionOfSinceOrigin(CtMethod method) {
CtMethod<?> parent;
int countAssertion = getAssertionOf(currentMethod);
while ((parent = AmplificationHelper.getAmpTestParent(currentMethod)) != null) {
if (!parent.getSimpleName().equals(currentMethod.getSimpleName())) {
countAssertion += getAssertionOf(parent);
}
currentMethod = parent;
countAssertion += getAssertionOf(currentMethod);
}
return countAssertion;
}

public static Integer getInputOfSinceOrigin(CtMethod method) {
CtMethod currentMethod = method;
CtMethod parent;
int countAssertion = 0;
int countAssertion = getInputOf(currentMethod);
while ((parent = AmplificationHelper.getAmpTestParent(currentMethod)) != null) {
countAssertion += getInputOf(currentMethod);
if (!parent.getSimpleName().equals(currentMethod.getSimpleName())) {
countAssertion += getInputOf(parent);
}
currentMethod = parent;
}
countAssertion += getInputOf(currentMethod);
return countAssertion;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
import spoon.Launcher;
import spoon.compiler.Environment;
import spoon.reflect.code.CtComment;
import spoon.reflect.code.CtLiteral;
import spoon.reflect.declaration.*;
import spoon.reflect.reference.CtTypeReference;
import spoon.reflect.visitor.filter.LineFilter;
import spoon.support.JavaOutputProcessor;

import java.io.*;
Expand Down Expand Up @@ -175,6 +177,17 @@ private static CtClass<?> getExistingClass(CtType<?> type, String pathname) {
}

public static void addComment(CtElement element, String content, CtComment.CommentType type) {
if (element instanceof CtLiteral) {
try {
CtElement parentLine = element.getParent(new LineFilter());
if (parentLine != null) {
element = parentLine;
}
} catch (ParentNotInitializedException ignored) {

}
}

CtComment comment = element.getFactory().createComment(content, type);
if (!element.getComments().contains(comment)) {
element.addComment(comment);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,10 @@ private void outputSeedTestClassWithSuccessTestMethods(CtType<?> testClassToBeAm
.distinct()
.forEach(clone::addMethod);
final File outputDirectory = new File(this.outputPathDirectory + "/original/");
DSpotState.GLOBAL_REPORT.addNumberAmplifiedTestMethodsToTotal(amplifiedTestMethods.size());
DSpotState.GLOBAL_REPORT.addPrintedTestClasses(
String.format("Print %s with %d amplified test cases in %s",
String.format("Print %s with %d original test cases in %s",
clone.getQualifiedName() + ".java",
amplifiedTestMethods.size(),
clone.getMethods().size(),
this.outputPathDirectory + "/original/"
)
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,24 @@ public TestCaseJSON(String name, int nbAssertionAdded, int nbInputAdded, int ins
this.instructionCovered = instructionCovered;
this.instructionTotal = instructionTotal;
}

public String getName() {
return name;
}

public int getNbAssertionAdded() {
return nbAssertionAdded;
}

public int getNbInputAdded() {
return nbInputAdded;
}

public int getInstructionCovered() {
return instructionCovered;
}

public int getInstructionTotal() {
return instructionTotal;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,40 @@ public String toString() {
String jsonString = new JSONObject().put(this.name,subJson).toString();
return jsonString;
}

public String getName() {
return name;
}

public long getNbOriginalTestCases() {
return nbOriginalTestCases;
}

public long getInitialInstructionCovered() {
return initialInstructionCovered;
}

public long getInitialInstructionTotal() {
return initialInstructionTotal;
}

public double getPercentageinitialInstructionCovered() {
return percentageinitialInstructionCovered;
}

public long getAmplifiedInstructionCovered() {
return amplifiedInstructionCovered;
}

public long getAmplifiedInstructionTotal() {
return amplifiedInstructionTotal;
}

public double getPercentageamplifiedInstructionCovered() {
return percentageamplifiedInstructionCovered;
}

public List<TestCaseJSON> getTestCases() {
return testCases;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -242,12 +242,12 @@ private TestClassJSON jsonReport(Coverage coverageResults) {
);
}
this.selectedAmplifiedTest.forEach(ctMethod ->
new TestCaseJSON(ctMethod.getSimpleName(),
Counter.getInputOfSinceOrigin(ctMethod),
testClassJSON.addTestCase(new TestCaseJSON(ctMethod.getSimpleName(),
Counter.getAssertionOfSinceOrigin(ctMethod),
Counter.getInputOfSinceOrigin(ctMethod),
this.selectedToBeAmplifiedCoverageResultsMap.get(ctMethod.getSimpleName()).getInstructionsCovered(),
this.selectedToBeAmplifiedCoverageResultsMap.get(ctMethod.getSimpleName()).getInstructionsTotal()
)
))
);
// TODO
// CollectorConfig.getInstance().getInformationCollector().reportSelectorInformation(testClassJSON.toString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ public void testMethodCallAddAll() throws Exception {
for (int i = 0; i < amplifiedMethods.size(); i++) {
CtMethod amplifiedMethod = amplifiedMethods.get(i);
assertEquals(originalMethod.getBody().getStatements().size() + 1, amplifiedMethod.getBody().getStatements().size());
CtStatement expectedStatement = originalMethod.getBody().getStatements().get(i + 1);//+1 to skip the construction statement.
assertEquals(expectedStatement.toString(),
CtStatement expectedStatement =originalMethod.getBody().getStatements().get(i + 1);//+1 to skip the construction statement.
assertEquals( "// MethodDuplicationAmplifier: duplicated method call\n" + expectedStatement.toString(),
amplifiedMethod.getBody().getStatements().get(i + 1).toString());
assertEquals(expectedStatement.toString(),
amplifiedMethod.getBody().getStatements().get(i + 2).toString());
Expand Down