Skip to content

Commit

Permalink
Optimize (#397)
Browse files Browse the repository at this point in the history
* remove old class for test runner

* pom: add developers

* optimize loop on input amplification

* optimize: avoid multiple call to same query, add logging

* fix: replacement is done on value and not on the spoon node

* update tests
  • Loading branch information
danglotb authored Apr 13, 2018
1 parent bd4c355 commit 5cb47b2
Show file tree
Hide file tree
Showing 12 changed files with 158 additions and 121 deletions.
40 changes: 20 additions & 20 deletions dspot/src/main/java/fr/inria/diversify/dspot/Amplification.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;


/**
Expand Down Expand Up @@ -176,13 +180,6 @@ private List<CtMethod<?>> amplification(CtType<?> classTest, CtMethod test, int
return amplifiedTests;
}

@Deprecated
private void updateAmplifiedTestList(List<CtMethod<?>> ampTest, List<CtMethod<?>> amplification) {
ampTest.addAll(amplification);
ampTestCount += amplification.size();
LOGGER.info("total amp test: {}, global: {}", amplification.size(), ampTestCount);
}

/**
* Adds new assertions in multiple tests.
*
Expand Down Expand Up @@ -248,32 +245,35 @@ private List<CtMethod<?>> preAmplification(CtType classTest, List<CtMethod<?>> t
*/
private List<CtMethod<?>> inputAmplifyTests(List<CtMethod<?>> tests) {
LOGGER.info("Amplification of inputs...");
List<CtMethod<?>> amplifiedTests = tests.stream()
List<CtMethod<?>> amplifiedTests = tests.parallelStream()
.flatMap(test -> {
DSpotUtils.printProgress(tests.indexOf(test), tests.size());
return inputAmplifyTest(test).stream();
})
.filter(test -> test != null && !test.getBody().getStatements().isEmpty())
.collect(Collectors.toList());
return inputAmplifyTest(test);
}).collect(Collectors.toList());
LOGGER.info("{} new tests generated", amplifiedTests.size());
return amplifiedTests;
}

public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Set<Object> seen = ConcurrentHashMap.newKeySet();
return t -> seen.add(keyExtractor.apply(t));
}

/**
* Input amplification for a single test.
*
* @param test Test method
* @return New generated tests
*/
private List<CtMethod<?>> inputAmplifyTest(CtMethod test) {
return amplifiers.stream()
.flatMap(amplifier -> amplifier.apply(test).stream()).
map(CtMethod::getBody)
.distinct()
.map(body -> body.getParent(CtMethod.class))
private Stream<CtMethod<?>> inputAmplifyTest(CtMethod<?> test) {
final CtMethod topParent = AmplificationHelper.getTopParent(test);
return amplifiers.parallelStream()
.flatMap(amplifier -> amplifier.apply(test).stream())
.filter(amplifiedTest -> amplifiedTest != null && !amplifiedTest.getBody().getStatements().isEmpty())
.filter(distinctByKey(CtMethod::getBody))
.map(amplifiedTest ->
AmplificationHelper.addOriginInComment(amplifiedTest, AmplificationHelper.getTopParent(test))
).collect(Collectors.toList());
AmplificationHelper.addOriginInComment(amplifiedTest, topParent)
);
}

private void resetAmplifiers(CtType parentClass) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@

import fr.inria.diversify.utils.AmplificationChecker;
import fr.inria.diversify.utils.AmplificationHelper;
import fr.inria.diversify.utils.DSpotUtils;
import fr.inria.stamp.Main;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import spoon.reflect.code.*;
import spoon.reflect.declaration.CtAnnotation;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.declaration.CtType;
import spoon.reflect.visitor.filter.TypeFilter;

import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
Expand All @@ -19,6 +24,8 @@
*/
public abstract class AbstractLiteralAmplifier<T> implements Amplifier {

private static final Logger LOGGER = LoggerFactory.getLogger(AbstractLiteralAmplifier.class);

protected CtType<?> testClassToBeAmplified;

private final TypeFilter<CtLiteral<T>> LITERAL_TYPE_FILTER = new TypeFilter<CtLiteral<T>>(CtLiteral.class) {
Expand Down Expand Up @@ -71,13 +78,25 @@ public boolean matches(CtLiteral<T> literal) {
@Override
public List<CtMethod> apply(CtMethod testMethod) {
List<CtLiteral<T>> literals = testMethod.getElements(LITERAL_TYPE_FILTER);
if (literals.isEmpty()) {
return Collections.emptyList();
}
if (Main.verbose) {
LOGGER.info("Applying {} on {} literals", this.toString(), literals.size());
}
return literals.stream()
.flatMap(literal ->
this.amplify(literal).stream().map(newValue -> {
CtMethod clone = AmplificationHelper.cloneTestMethodForAmp(testMethod, getSuffix());
clone.getElements(LITERAL_TYPE_FILTER).get(literals.indexOf(literal)).replace(newValue);
return clone;
})
.flatMap(literal -> {
if (Main.verbose) {
DSpotUtils.printProgress(literals.indexOf(literal), literals.size());
}
return this.amplify(literal).stream().map(newValue -> {
final T originalValue = literal.getValue();
literal.setValue(newValue);
CtMethod clone = AmplificationHelper.cloneTestMethodForAmp(testMethod, getSuffix());
literal.setValue(originalValue);
return clone;
});
}
).collect(Collectors.toList());
}

Expand All @@ -87,10 +106,15 @@ public void reset(CtType testClass) {
this.testClassToBeAmplified = testClass;
}

protected abstract Set<CtLiteral<T>> amplify(CtLiteral<T> existingLiteral);
protected abstract Set<T> amplify(CtLiteral<T> existingLiteral);

protected abstract String getSuffix();

protected abstract Class<?> getTargetedClass();

@Override
public String toString() {
return this.getClass().getName();
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package fr.inria.diversify.dspot.amplifier;

import fr.inria.stamp.Main;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.declaration.CtType;

Expand All @@ -14,6 +17,8 @@
*/
public class AllLiteralAmplifiers implements Amplifier {

private static final Logger LOGGER = LoggerFactory.getLogger(AllLiteralAmplifiers.class);

private List<Amplifier> literalAmplifiers;

public AllLiteralAmplifiers() {
Expand All @@ -28,7 +33,12 @@ public AllLiteralAmplifiers() {
@Override
public List<CtMethod> apply(CtMethod testMethod) {
return this.literalAmplifiers.stream()
.flatMap(amplifier -> amplifier.apply(testMethod).stream())
.flatMap(amplifier -> {
if (Main.verbose) {
LOGGER.info("Applying {}", amplifier.toString());
}
return amplifier.apply(testMethod).stream();
})
.collect(Collectors.toList());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

public class BooleanLiteralAmplifier extends AbstractLiteralAmplifier<Boolean> {
@Override
protected Set<CtLiteral<Boolean>> amplify(CtLiteral<Boolean> existingLiteral) {
return Collections.singleton(existingLiteral.getFactory().createLiteral(!existingLiteral.getValue()));
protected Set<Boolean> amplify(CtLiteral<Boolean> existingLiteral) {
return Collections.singleton(!existingLiteral.getValue());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,13 @@
public class CharLiteralAmplifier extends AbstractLiteralAmplifier<Character> {

@Override
protected Set<CtLiteral<Character>> amplify(CtLiteral<Character> existingLiteral) {
protected Set<Character> amplify(CtLiteral<Character> existingLiteral) {
final Character value = existingLiteral.getValue();
return Stream.of('\0', ' ', AmplificationHelper.getRandomChar(),
(char) (value + 1),
(char) (value - 1),
System.getProperty("line.separator").charAt(0)
).map(existingLiteral.getFactory()::createLiteral)
.collect(Collectors.toSet());
).collect(Collectors.toSet());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,10 @@
public class NumberLiteralAmplifier extends AbstractLiteralAmplifier<Number> {

@Override
protected Set<CtLiteral<Number>> amplify(CtLiteral<Number> literal) {
Set<CtLiteral<Number>> values = new HashSet<>();
protected Set<Number> amplify(CtLiteral<Number> literal) {
Set<Number> values = new HashSet<>();
Double value = ((Number) literal.getValue()).doubleValue();

//TODO asking myself if such transformation are useful...
// values.add(literal.getFactory().createLiteral(value / 2));
// values.add(literal.getFactory().createLiteral(value * 2));

Class<?> classOfLiteral;
if (! literal.getTypeCasts().isEmpty()){
classOfLiteral = literal.getTypeCasts().get(0).getActualClass();
Expand All @@ -24,54 +20,54 @@ protected Set<CtLiteral<Number>> amplify(CtLiteral<Number> literal) {
}

if (classOfLiteral == Byte.class || classOfLiteral == byte.class) {
values.add(literal.getFactory().createLiteral((byte)(value.byteValue() + 1)));
values.add(literal.getFactory().createLiteral((byte)(value.byteValue() - 1)));
values.add(literal.getFactory().createLiteral(Byte.MAX_VALUE));
values.add(literal.getFactory().createLiteral(Byte.MIN_VALUE));
values.add(literal.getFactory().createLiteral((byte)0));
values.add((byte)(value.byteValue() + 1));
values.add((byte)(value.byteValue() - 1));
values.add(Byte.MAX_VALUE);
values.add(Byte.MIN_VALUE);
values.add((byte)0);
}
if (classOfLiteral == Short.class || classOfLiteral == short.class) {
values.add(literal.getFactory().createLiteral((short)(value.shortValue() + 1)));
values.add(literal.getFactory().createLiteral((short)(value.shortValue() - 1)));
values.add(literal.getFactory().createLiteral(Short.MAX_VALUE));
values.add(literal.getFactory().createLiteral(Short.MIN_VALUE));
values.add(literal.getFactory().createLiteral((short)0));
values.add((short)(value.shortValue() + 1));
values.add((short)(value.shortValue() - 1));
values.add(Short.MAX_VALUE);
values.add(Short.MIN_VALUE);
values.add((short)0);
}
if (classOfLiteral == Integer.class || classOfLiteral == int.class) {
values.add(literal.getFactory().createLiteral(value.intValue() + 1));
values.add(literal.getFactory().createLiteral(value.intValue() - 1));
values.add(literal.getFactory().createLiteral(Integer.MAX_VALUE));
values.add(literal.getFactory().createLiteral(Integer.MIN_VALUE));
values.add(literal.getFactory().createLiteral(0));
values.add(value.intValue() + 1);
values.add(value.intValue() - 1);
values.add(Integer.MAX_VALUE);
values.add(Integer.MIN_VALUE);
values.add(0);
}
if (classOfLiteral == Long.class || classOfLiteral == long.class) {
values.add(literal.getFactory().createLiteral((long)(value.longValue() + 1)));
values.add(literal.getFactory().createLiteral((long)(value.longValue() - 1)));
values.add(literal.getFactory().createLiteral(Long.MAX_VALUE));
values.add(literal.getFactory().createLiteral(Long.MIN_VALUE));
values.add(literal.getFactory().createLiteral(0L));
values.add((long)(value.longValue() + 1));
values.add((long)(value.longValue() - 1));
values.add(Long.MAX_VALUE);
values.add(Long.MIN_VALUE);
values.add(0L);
}
if (classOfLiteral == Float.class || classOfLiteral == float.class) {
values.add(literal.getFactory().createLiteral(value.floatValue() + 1.0F));
values.add(literal.getFactory().createLiteral(value.floatValue() - 1.0F));
values.add(literal.getFactory().createLiteral(Float.NaN));
values.add(literal.getFactory().createLiteral(Float.POSITIVE_INFINITY));
values.add(literal.getFactory().createLiteral(Float.NEGATIVE_INFINITY));
values.add(literal.getFactory().createLiteral(Float.MIN_NORMAL));
values.add(literal.getFactory().createLiteral(Float.MAX_VALUE));
values.add(literal.getFactory().createLiteral(Float.MIN_VALUE));
values.add(literal.getFactory().createLiteral(0.0F));
values.add(value.floatValue() + 1.0F);
values.add(value.floatValue() - 1.0F);
values.add(Float.NaN);
values.add(Float.POSITIVE_INFINITY);
values.add(Float.NEGATIVE_INFINITY);
values.add(Float.MIN_NORMAL);
values.add(Float.MAX_VALUE);
values.add(Float.MIN_VALUE);
values.add(0.0F);
}
if (classOfLiteral == Double.class || classOfLiteral == double.class) {
values.add(literal.getFactory().createLiteral(value + 1.0D));
values.add(literal.getFactory().createLiteral(value - 1.0D));
values.add(literal.getFactory().createLiteral(Double.NaN));
values.add(literal.getFactory().createLiteral(Double.POSITIVE_INFINITY));
values.add(literal.getFactory().createLiteral(Double.NEGATIVE_INFINITY));
values.add(literal.getFactory().createLiteral(Double.MIN_NORMAL));
values.add(literal.getFactory().createLiteral(Double.MAX_VALUE));
values.add(literal.getFactory().createLiteral(Double.MIN_VALUE));
values.add(literal.getFactory().createLiteral(0.0D));
values.add(value + 1.0D);
values.add(value - 1.0D);
values.add(Double.NaN);
values.add(Double.POSITIVE_INFINITY);
values.add(Double.NEGATIVE_INFINITY);
values.add(Double.MIN_NORMAL);
values.add(Double.MAX_VALUE);
values.add(Double.MIN_VALUE);
values.add(0.0D);
}
return values;
}
Expand Down
Loading

0 comments on commit 5cb47b2

Please sign in to comment.