![JAR search and dependency download from the Maven repository](/logo.png)
org.evosuite.testcase.localsearch.ReferenceLocalSearch Maven / Gradle / Ivy
The newest version!
/**
* Copyright (C) 2010-2018 Gordon Fraser, Andrea Arcuri and EvoSuite
* contributors
*
* This file is part of EvoSuite.
*
* EvoSuite is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3.0 of the License, or
* (at your option) any later version.
*
* EvoSuite is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with EvoSuite. If not, see .
*/
/**
*
*/
package org.evosuite.testcase.localsearch;
import java.util.ArrayList;
import java.util.List;
import org.evosuite.Properties;
import org.evosuite.ga.ConstructionFailedException;
import org.evosuite.ga.localsearch.LocalSearchBudget;
import org.evosuite.ga.localsearch.LocalSearchObjective;
import org.evosuite.testcase.statements.Statement;
import org.evosuite.testcase.TestChromosome;
import org.evosuite.testcase.TestFactory;
import org.evosuite.testcase.variable.VariableReference;
import org.evosuite.testcase.statements.ConstructorStatement;
import org.evosuite.testcase.statements.FieldStatement;
import org.evosuite.testcase.statements.MethodStatement;
import org.evosuite.testcase.statements.NullStatement;
import org.evosuite.utils.Randomness;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Gordon Fraser
*
*/
public class ReferenceLocalSearch extends StatementLocalSearch {
private static final Logger logger = LoggerFactory.getLogger(ReferenceLocalSearch.class);
private int positionDelta = 0;
/* (non-Javadoc)
* @see org.evosuite.testcase.LocalSearch#getPositionDelta()
*/
@Override
public int getPositionDelta() {
return positionDelta;
}
private enum Mutations {
REPLACE, PARAMETER, CALL
};
/* (non-Javadoc)
* @see org.evosuite.testcase.LocalSearch#doSearch(org.evosuite.testcase.TestChromosome, int, org.evosuite.ga.LocalSearchObjective)
*/
@Override
public boolean doSearch(TestChromosome test, int statement,
LocalSearchObjective objective) {
boolean hasImproved = false;
int currentProbe = 0;
backup(test);
int oldLength = test.size();
while (currentProbe < Properties.LOCAL_SEARCH_PROBES
&& !LocalSearchBudget.getInstance().isFinished()) {
logger.info("Current probe on statement " + statement + ": " + currentProbe);
List mutations = new ArrayList();
mutations.add(Mutations.REPLACE);
Statement st = test.getTestCase().getStatement(statement);
if (!st.getReturnValue().isPrimitive() && !(st instanceof NullStatement)) {
mutations.add(Mutations.CALL);
}
if (st.getNumParameters() > 0) {
mutations.add(Mutations.PARAMETER);
} else {
mutations.remove(Mutations.PARAMETER);
}
int delta = 0;
Mutations m = Randomness.choice(mutations);
//logger.debug("Test before mutation: {}", test.getTestCase().toCode());
switch (m) {
case REPLACE:
replace(test, statement);
if (test.size() > oldLength)
delta = test.size() - oldLength;
break;
case PARAMETER:
changeParameters(test, statement);
break;
case CALL:
addCall(test, statement);
break;
}
if (test.isChanged()) {
logger.info("Is changed");
// logger.info("Test after mutation: " + test.getTestCase().toCode());
if (objective.hasImproved(test)) {
logger.info("Fitness has improved, keeping");
currentProbe = 0;
hasImproved = true;
backup(test);
statement += delta;
positionDelta += delta;
oldLength = test.size();
} else {
logger.info("Fitness has not improved, reverting");
currentProbe++;
restore(test);
}
} else {
logger.info("Is not changed");
currentProbe++;
}
}
return hasImproved;
}
/**
* Add a method call on the return value of the object at position statement
*
* @param test
* @param statement
*/
private boolean addCall(TestChromosome test, int statement) {
logger.debug("Adding call");
TestFactory factory = TestFactory.getInstance();
Statement theStatement = test.getTestCase().getStatement(statement);
VariableReference var = theStatement.getReturnValue();
int oldLength = test.size();
factory.insertRandomCallOnObjectAt(test.getTestCase(), var, statement + 1);
test.setChanged(test.size() != oldLength);
return false;
}
/**
* Replace the call with a completely different call
*
* @param test
* @param statement
* @return
*/
private boolean replace(TestChromosome test, int statement) {
logger.debug("Replacing call");
TestFactory factory = TestFactory.getInstance();
Statement theStatement = test.getTestCase().getStatement(statement);
VariableReference var = theStatement.getReturnValue();
int oldLength = test.size();
try {
VariableReference replacement = null;
if (Randomness.nextDouble() < Properties.NULL_PROBABILITY) {
NullStatement nullStatement = new NullStatement(test.getTestCase(),
var.getType());
replacement = test.getTestCase().addStatement(nullStatement, statement);
} else if(!var.isPrimitive()) {
// Test cluster does not keep track of generators for primitives
replacement = factory.createObject(test.getTestCase(), var.getType(),
statement, 0, null);
}
if(replacement != null) {
int oldStatement = statement + (test.size() - oldLength);
for (int i = oldStatement + 1; i < test.size(); i++) {
test.getTestCase().getStatement(i).replace(var, replacement);
}
factory.deleteStatement(test.getTestCase(), oldStatement);
test.setChanged(true);
}
} catch (ConstructionFailedException e) {
if (test.size() < oldLength) {
restore(test);
}
test.setChanged(test.size() != oldLength);
}
return false;
}
/**
* Switch parameter/callee variables with other available objects
*
* @param test
* @param statement
* @return
*/
private boolean changeParameters(TestChromosome test, int statement) {
logger.debug("Changing parameters");
Statement stmt = test.getTestCase().getStatement(statement);
if (stmt instanceof MethodStatement) {
return replaceMethodParameter(test, (MethodStatement) stmt);
} else if (stmt instanceof ConstructorStatement) {
return replaceConstructorParameter(test, (ConstructorStatement) stmt);
} else if (stmt instanceof FieldStatement) {
return replaceFieldSource(test, (FieldStatement) stmt);
} else {
return false;
}
}
/**
* Go through parameters of method call and apply local search
*
* @param test
* @param statement
*/
private boolean replaceMethodParameter(TestChromosome test, MethodStatement statement) {
List parameters = statement.getParameterReferences();
if (parameters.isEmpty())
return false;
int max = parameters.size();
if (!statement.isStatic()) {
max++;
}
int numParameter = Randomness.nextInt(max);
if (numParameter == parameters.size()) {
// replace callee
VariableReference callee = statement.getCallee();
List objects = test.getTestCase().getObjects(callee.getType(),
statement.getPosition());
objects.remove(callee);
if (objects.isEmpty())
return false;
VariableReference replacement = Randomness.choice(objects);
statement.setCallee(replacement);
test.setChanged(true);
} else {
VariableReference parameter = parameters.get(numParameter);
List objects = test.getTestCase().getObjects(parameter.getType(),
statement.getPosition());
objects.remove(parameter);
objects.remove(statement.getReturnValue());
NullStatement nullStatement = new NullStatement(test.getTestCase(),
parameter.getType());
if (!parameter.isPrimitive())
objects.add(nullStatement.getReturnValue());
if (objects.isEmpty())
return false;
VariableReference replacement = Randomness.choice(objects);
if (replacement == nullStatement.getReturnValue()) {
test.getTestCase().addStatement(nullStatement, statement.getPosition());
}
statement.replaceParameterReference(replacement, numParameter);
test.setChanged(true);
}
return false;
}
/**
* Go through parameters of constructor call and apply local search
*
* @param test
* @param statement
*/
private boolean replaceConstructorParameter(TestChromosome test,
ConstructorStatement statement) {
List parameters = statement.getParameterReferences();
if (parameters.isEmpty())
return false;
int numParameter = Randomness.nextInt(parameters.size());
VariableReference parameter = parameters.get(numParameter);
List objects = test.getTestCase().getObjects(parameter.getType(),
statement.getPosition());
objects.remove(parameter);
objects.remove(statement.getReturnValue());
NullStatement nullStatement = new NullStatement(test.getTestCase(),
parameter.getType());
if (!parameter.isPrimitive())
objects.add(nullStatement.getReturnValue());
if (objects.isEmpty())
return false;
VariableReference replacement = Randomness.choice(objects);
if (replacement == nullStatement.getReturnValue()) {
test.getTestCase().addStatement(nullStatement, statement.getPosition());
}
statement.replaceParameterReference(replacement, numParameter);
test.setChanged(true);
return false;
}
/**
* Try to replace source of field with all possible choices
*
* @param test
* @param statement
*/
private boolean replaceFieldSource(TestChromosome test, FieldStatement statement) {
if (!statement.isStatic()) {
VariableReference source = statement.getSource();
List objects = test.getTestCase().getObjects(source.getType(),
statement.getPosition());
objects.remove(source);
if (!objects.isEmpty()) {
statement.setSource(Randomness.choice(objects));
test.setChanged(true);
}
}
return false;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy