refactoring

This commit is contained in:
Sander Hautvast 2015-09-26 17:24:32 +02:00
parent 07021dd9a9
commit a86c365616
25 changed files with 237 additions and 254 deletions

View file

@ -4,17 +4,20 @@ import javassist.ClassPool;
import javassist.NotFoundException; import javassist.NotFoundException;
/** /**
* TODO make configurable
* *
*/ */
public class Configuration { public class Configuration {
public static ClassPool getClassPool() { public static ClassPool getClassPool() {
ClassPool classPool = new ClassPool(); ClassPool classPool = new ClassPool();
try { try {
classPool.appendClassPath("bin"); classPool.appendClassPath(getClasspathSettingOrEclipseDefault());
} catch (NotFoundException e) { } catch (NotFoundException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
return classPool; return classPool;
} }
private static String getClasspathSettingOrEclipseDefault() {
return System.getProperty("autounit.cp", "bin");
}
} }

View file

@ -6,49 +6,50 @@ import java.io.FileOutputStream;
import java.io.PrintStream; import java.io.PrintStream;
import nl.jssl.autounit.classanalyser.ClassAnalyser; import nl.jssl.autounit.classanalyser.ClassAnalyser;
import nl.jssl.autounit.classanalyser.ClassResults;
import nl.jssl.autounit.results.JUnitSourceWriter; import nl.jssl.autounit.results.JUnitSourceWriter;
/** /**
* Creates a Junit source file * Creates a Junit source file
* *
*/ */
public class JUnitTestCreator { public class JUnitTestCreator<T> {
private static final String SOURCEDIRECTORY = "src/outcome/java/"; private static final String SOURCEDIRECTORY = "src/outcome/java/";
private final Class<T> classUnderTest;
private final File packageDirectory;
public void assembleJUnitTest(Class<?> type) { public JUnitTestCreator(Class<T> type) {
this.classUnderTest = type;
packageDirectory = createPackageDirectory();
}
public void create() {
try { try {
tryAssembleJUnitTest(type); writeSourceFile();
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
private void tryAssembleJUnitTest(Class<?> type) throws FileNotFoundException { private void writeSourceFile() throws FileNotFoundException {
writeSourceFile(createPackageDirectory(type), type); ClassResults results = new ClassAnalyser<>(classUnderTest).analyseAndGetResults();
getSourceWriter(packageDirectory).write(results);
} }
private void writeSourceFile(File packageDirectory, Class<?> classUnderTest) throws FileNotFoundException { private JUnitSourceWriter getSourceWriter(File packageDirectory) throws FileNotFoundException {
resultsWriter(packageDirectory, classUnderTest).write(new ClassAnalyser(classUnderTest).analyse()); return new JUnitSourceWriter(new PrintStream(new FileOutputStream(getSourceFile())));
} }
private JUnitSourceWriter resultsWriter(File packageDirectory, Class<?> type) throws FileNotFoundException { private File createPackageDirectory() {
return new JUnitSourceWriter( File packageDirectory = new File(
new PrintStream(new FileOutputStream(toSourceFile(packageDirectory, type)))); SOURCEDIRECTORY + classUnderTest.getPackage().getName().replaceAll("\\.", "/"));
}
private File createPackageDirectory(Class<?> type) {
File packageDirectory = toPackageDirectory(type);
packageDirectory.mkdirs(); packageDirectory.mkdirs();
return packageDirectory; return packageDirectory;
} }
private File toSourceFile(File packageDirectory, Class<?> type) { private File getSourceFile() {
return new File(packageDirectory, type.getName().replaceAll("\\.", "/") + "Tests.java"); return new File(packageDirectory, classUnderTest.getSimpleName() + "Tests.java");
}
private File toPackageDirectory(Class<?> type) {
return new File(SOURCEDIRECTORY + type.getPackage().getName().replaceAll("\\.", "/"));
} }
} }

View file

@ -6,35 +6,36 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import nl.jssl.autounit.inputs.MethodcallArgumentsFactory; import nl.jssl.autounit.inputs.MethodcallArgumentsFactory;
import nl.jssl.autounit.util.Pair; import nl.jssl.autounit.util.LinkedList;
public class ClassAnalyser { public class ClassAnalyser<T> {
private Class<?> testTarget; private Class<T> testTarget;
public ClassAnalyser(Class<?> testTarget) { public ClassAnalyser(Class<T> testTarget) {
this.testTarget = testTarget; this.testTarget = testTarget;
} }
public ClassResults analyse() { public ClassResults analyseAndGetResults() {
List<MethodCallResults> classresults = new ArrayList<>(); List<MethodExecutionResults> classresults = new ArrayList<>();
for (Method m : getPublicMethods()) { for (Method m : getPublicMethods()) {
MethodCallResults methodresults = recordMethod(m); classresults.add(analyseMethod(m));
classresults.add(methodresults);
} }
return new ClassResults(testTarget, classresults); return new ClassResults(testTarget, classresults);
} }
private MethodCallResults recordMethod(Method m) { private MethodExecutionResults analyseMethod(Method method) {
List<Pair> inputSet = new MethodcallArgumentsFactory().getInputs(testTarget, m); List<LinkedList> inputSet = new MethodcallArgumentsFactory(testTarget).getInputs(method);
MethodcallExecutor methodcallExecutor = new MethodcallExecutor(testTarget, m);
methodcallExecutor.execute(inputSet); MethodcallExecutor<T> methodcallExecutor = new MethodcallExecutor<>(testTarget, method);
MethodCallResults mcr = methodcallExecutor.getResult();
return mcr; return methodcallExecutor.executeAndGetResults(inputSet);
} }
List<Method> getPublicMethods() { List<Method> getPublicMethods() {
List<Method> publicMethods = new ArrayList<Method>(); List<Method> publicMethods = new ArrayList<Method>();
for (Method m : testTarget.getDeclaredMethods()) { for (Method m : testTarget.getDeclaredMethods()) {
if (Modifier.isPublic(m.getModifiers())) { if (Modifier.isPublic(m.getModifiers())) {
publicMethods.add(m); publicMethods.add(m);

View file

@ -4,15 +4,15 @@ import java.util.List;
public class ClassResults { public class ClassResults {
private final Class<?> type; private final Class<?> type;
private final List<MethodCallResults> methodCallResults; private final List<MethodExecutionResults> methodCallResults;
public ClassResults(Class<?> type, List<MethodCallResults> methodCallResults) { public ClassResults(Class<?> type, List<MethodExecutionResults> methodCallResults) {
super(); super();
this.type = type; this.type = type;
this.methodCallResults = methodCallResults; this.methodCallResults = methodCallResults;
} }
public List<MethodCallResults> getMethodCallResults() { public List<MethodExecutionResults> getMethodCallResults() {
return methodCallResults; return methodCallResults;
} }

View file

@ -17,37 +17,31 @@ import org.jacoco.core.runtime.RuntimeData;
import nl.jssl.autounit.util.MemoryClassloader; import nl.jssl.autounit.util.MemoryClassloader;
import nl.jssl.autounit.util.SilentObjectCreator; import nl.jssl.autounit.util.SilentObjectCreator;
public class CoverageAnalyser { public class CoverageAnalyser<T> {
private IRuntime runtime; private final IRuntime runtime;
private RuntimeData data = new RuntimeData(); private final RuntimeData data;
private final Class<T> testTarget;
@SuppressWarnings("unchecked")
public <T> T instrument(Class<T> testTarget) {
try {
String targetName = testTarget.getName();
runtime = new LoggerRuntime();
Instrumenter instr = new Instrumenter(runtime);
byte[] instrumented = instr.instrument(getTargetClass(targetName), targetName);
public CoverageAnalyser(Class<T> testTarget) {
this.testTarget = testTarget;
data = new RuntimeData(); data = new RuntimeData();
runtime = new LoggerRuntime();
}
public T instrument() {
try {
runtime.startup(data); runtime.startup(data);
MemoryClassloader memoryClassLoader = new MemoryClassloader(); return getInstrumentedObjectInstance();
memoryClassLoader.addDefinition(targetName, instrumented);
Class<T> targetClass = (Class<T>) memoryClassLoader.loadClass(targetName);
return SilentObjectCreator.create(targetClass);
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new AnalysisFailed(e);
} }
} }
public <T> InvocationResult analyse(T instrumentedTestTarget, Method method, Object[] inputs) { public InvocationResult analyse(T instrumentedTestTarget, Method method, Object[] inputs) {
try { try {
Method instanceMethod = getInstrumentedMethod(instrumentedTestTarget, method); Object output = invokeMethod(instrumentedTestTarget, inputs,
Object output = invoke(instrumentedTestTarget, inputs, instanceMethod); getInstrumentedMethod(instrumentedTestTarget, method));
// jacoco stuff // jacoco stuff
ExecutionDataStore executionData = executionData(); ExecutionDataStore executionData = executionData();
@ -62,6 +56,24 @@ public class CoverageAnalyser {
} }
} }
@SuppressWarnings("unchecked")
private T getInstrumentedObjectInstance() throws IOException, ClassNotFoundException {
MemoryClassloader memoryClassLoader = getMemoryClassLoaderForClass(getInstrumentedByteCode());
Class<T> targetClass = (Class<T>) memoryClassLoader.loadClass(testTarget.getName());
return SilentObjectCreator.create(targetClass);
}
private byte[] getInstrumentedByteCode() throws IOException {
return new Instrumenter(runtime).instrument(getTargetClass(), testTarget.getName());
}
private MemoryClassloader getMemoryClassLoaderForClass(byte[] instrumentedByteCode) {
MemoryClassloader memoryClassLoader = new MemoryClassloader();
memoryClassLoader.addDefinition(testTarget.getName(), instrumentedByteCode);
return memoryClassLoader;
}
private ExecutionDataStore executionData() { private ExecutionDataStore executionData() {
ExecutionDataStore executionData = new ExecutionDataStore(); ExecutionDataStore executionData = new ExecutionDataStore();
SessionInfoStore sessionInfos = new SessionInfoStore(); SessionInfoStore sessionInfos = new SessionInfoStore();
@ -69,20 +81,20 @@ public class CoverageAnalyser {
return executionData; return executionData;
} }
private <T> CoverageBuilder coverageBuilder(T instrumentedTestTarget, ExecutionDataStore executionData) private CoverageBuilder coverageBuilder(T instrumentedTestTarget, ExecutionDataStore executionData)
throws IOException { throws IOException {
CoverageBuilder coverageBuilder = new CoverageBuilder(); CoverageBuilder coverageBuilder = new CoverageBuilder();
Analyzer analyzer = new Analyzer(executionData, coverageBuilder); Analyzer analyzer = new Analyzer(executionData, coverageBuilder);
String targetName = instrumentedTestTarget.getClass().getName(); String targetName = instrumentedTestTarget.getClass().getName();
analyzer.analyzeClass(getTargetClass(targetName), targetName); analyzer.analyzeClass(getTargetClass(), targetName);
return coverageBuilder; return coverageBuilder;
} }
private <T> Method getInstrumentedMethod(T testTarget, Method method) throws NoSuchMethodException { private Method getInstrumentedMethod(T testTarget, Method method) throws NoSuchMethodException {
return testTarget.getClass().getDeclaredMethod(method.getName(), method.getParameterTypes()); return testTarget.getClass().getDeclaredMethod(method.getName(), method.getParameterTypes());
} }
private <T> Object invoke(T testTarget, Object[] inputs, Method newInstanceMethod) throws IllegalAccessException { private Object invokeMethod(T testTarget, Object[] inputs, Method newInstanceMethod) throws IllegalAccessException {
Object output; Object output;
try { try {
output = newInstanceMethod.invoke(testTarget, inputs); output = newInstanceMethod.invoke(testTarget, inputs);
@ -101,8 +113,8 @@ public class CoverageAnalyser {
return output; return output;
} }
private InputStream getTargetClass(String name) { private InputStream getTargetClass() {
String resource = '/' + name.replace('.', '/') + ".class"; String resource = '/' + testTarget.getName().replace('.', '/') + ".class";
return getClass().getResourceAsStream(resource); return getClass().getResourceAsStream(resource);
} }

View file

@ -1,17 +1,17 @@
package nl.jssl.autounit.classanalyser; package nl.jssl.autounit.classanalyser;
import nl.jssl.autounit.util.Pair; import nl.jssl.autounit.util.LinkedList;
public class InAndOutput { public class InAndOutput {
private final Pair input; private final LinkedList input;
private final Object output; private final Object output;
public InAndOutput(Pair input, Object output) { public InAndOutput(LinkedList input, Object output) {
this.input = input; this.input = input;
this.output = output; this.output = output;
} }
public Pair getInput() { public LinkedList getInput() {
return input; return input;
} }

View file

@ -7,21 +7,21 @@ import java.util.List;
import org.jacoco.core.analysis.IClassCoverage; import org.jacoco.core.analysis.IClassCoverage;
import nl.jssl.autounit.util.Pair; import nl.jssl.autounit.util.LinkedList;
public class MethodCallResults implements Comparable<MethodCallResults> { public class MethodExecutionResults implements Comparable<MethodExecutionResults> {
private transient Object testinstance; private transient Object testinstance;
private transient Method executedMethod; private transient Method executedMethod;
private List<InAndOutput> contents = new ArrayList<InAndOutput>(); private List<InAndOutput> contents = new ArrayList<InAndOutput>();
private transient IClassCoverage coverageResult; private transient IClassCoverage coverageResult;
public MethodCallResults(Object testClass, Method m) { public MethodExecutionResults(Object testClass, Method m) {
super(); super();
this.testinstance = testClass; this.testinstance = testClass;
this.executedMethod = m; this.executedMethod = m;
} }
public void addResult(Pair input, Object output) { public void addResult(LinkedList input, Object output) {
contents.add(new InAndOutput(input, output)); contents.add(new InAndOutput(input, output));
} }
@ -86,7 +86,7 @@ public class MethodCallResults implements Comparable<MethodCallResults> {
} }
@Override @Override
public int compareTo(MethodCallResults o) { public int compareTo(MethodExecutionResults o) {
return getMethodName().compareTo(o.getMethodName()); return getMethodName().compareTo(o.getMethodName());
} }
} }

View file

@ -3,30 +3,32 @@ package nl.jssl.autounit.classanalyser;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.List; import java.util.List;
import nl.jssl.autounit.util.Pair; import nl.jssl.autounit.util.LinkedList;
/** /**
* voert 1 methode uit met wisselende input parameters en bewaart het resultaat. * Executes 1 method using alternating input parameters and yields execution
* results.
* *
*/ */
public class MethodcallExecutor { public class MethodcallExecutor<T> {
private Object instrumentedTestTarget; private T instrumentedTestTarget;
private Method methodUnderTest; private Method methodUnderTest;
CoverageAnalyser coverageAnalyser = new CoverageAnalyser(); private MethodExecutionResults result;
private MethodCallResults result; private final CoverageAnalyser<T> coverageAnalyser;
public MethodcallExecutor(Class<T> testClass, Method methodUnderTest) {
coverageAnalyser = new CoverageAnalyser<T>(testClass);
this.instrumentedTestTarget = coverageAnalyser.instrument();
public MethodcallExecutor(Class<?> testClass, Method methodUnderTest) {
super();
this.instrumentedTestTarget = coverageAnalyser.instrument(testClass);
this.methodUnderTest = methodUnderTest; this.methodUnderTest = methodUnderTest;
this.result = new MethodCallResults(instrumentedTestTarget, methodUnderTest); this.result = new MethodExecutionResults(instrumentedTestTarget, methodUnderTest);
} }
public MethodCallResults execute(List<Pair> inputs) { public MethodExecutionResults executeAndGetResults(List<LinkedList> inputs) {
InvocationResult lastInvocationResult = null, previous = null; InvocationResult lastInvocationResult = null, previous = null;
int missedLines = Integer.MAX_VALUE; int missedLines = Integer.MAX_VALUE;
for (Pair input : inputs) { for (LinkedList input : inputs) {
previous = lastInvocationResult; previous = lastInvocationResult;
lastInvocationResult = analyseMethodCall(methodUnderTest, input); lastInvocationResult = analyseMethodCall(methodUnderTest, input);
@ -51,7 +53,7 @@ public class MethodcallExecutor {
} }
private int addInOutputCombinationWhenCoverageIncreases(int missedLines, InvocationResult lastInvocationResult, private int addInOutputCombinationWhenCoverageIncreases(int missedLines, InvocationResult lastInvocationResult,
Pair input, int missedCount) { LinkedList input, int missedCount) {
if (coverageHasIncreased(missedLines, missedCount)) { if (coverageHasIncreased(missedLines, missedCount)) {
missedLines = missedCount; missedLines = missedCount;
addInterestingInAndOutput(input, lastInvocationResult); addInterestingInAndOutput(input, lastInvocationResult);
@ -59,7 +61,7 @@ public class MethodcallExecutor {
return missedLines; return missedLines;
} }
private void addInterestingInAndOutput(Pair input, InvocationResult lastInvocationResult) { private void addInterestingInAndOutput(LinkedList input, InvocationResult lastInvocationResult) {
result.addResult(input, lastInvocationResult.getOutput()); result.addResult(input, lastInvocationResult.getOutput());
} }
@ -71,7 +73,7 @@ public class MethodcallExecutor {
return missedCount < missedLines; return missedCount < missedLines;
} }
private InvocationResult analyseMethodCall(Method methodUnderTest, Pair input) { private InvocationResult analyseMethodCall(Method methodUnderTest, LinkedList input) {
Object[] inputs = replaceNullIndicatorWithNull(input.toArray()); Object[] inputs = replaceNullIndicatorWithNull(input.toArray());
return coverageAnalyser.analyse(instrumentedTestTarget, methodUnderTest, inputs); return coverageAnalyser.analyse(instrumentedTestTarget, methodUnderTest, inputs);
@ -86,7 +88,4 @@ public class MethodcallExecutor {
return argumentarray; return argumentarray;
} }
public MethodCallResults getResult() {
return result;
}
} }

View file

@ -15,22 +15,24 @@ import nl.jssl.autounit.inputs.primitives.ByteArgumentFactory;
import nl.jssl.autounit.inputs.primitives.DoubleArgumentFactory; import nl.jssl.autounit.inputs.primitives.DoubleArgumentFactory;
import nl.jssl.autounit.inputs.primitives.FloatArgumentFactory; import nl.jssl.autounit.inputs.primitives.FloatArgumentFactory;
import nl.jssl.autounit.inputs.primitives.IntegerArgumentFactory; import nl.jssl.autounit.inputs.primitives.IntegerArgumentFactory;
import nl.jssl.autounit.util.Pair; import nl.jssl.autounit.util.LinkedList;
import nl.jssl.autounit.util.Permuter; import nl.jssl.autounit.util.Permuter;
public class MethodcallArgumentsFactory { public class MethodcallArgumentsFactory {
private final Map<Class<?>, ArgumentFactory<?>> primitivesFactories; private final Map<Class<?>, ArgumentFactory<?>> primitivesFactories;
private final Class<?> testTarget;
public MethodcallArgumentsFactory() { public MethodcallArgumentsFactory(Class<?> testTarget) {
this.testTarget = testTarget;
primitivesFactories = new HashMap<Class<?>, ArgumentFactory<?>>(); primitivesFactories = new HashMap<Class<?>, ArgumentFactory<?>>();
populateFactories(); populateFactories();
} }
public List<Pair> getInputs(Class<?> testTarget, Method m) { public List<LinkedList> getInputs(Method method) {
return combine(getArgumentsForAllParameters(testTarget, m)); return combine(getArgumentsForAllParameters(method));
} }
private List<Pair> combine(List<List<?>> inputSetsForAllArguments) { private List<LinkedList> combine(List<List<?>> inputSetsForAllArguments) {
int nrOfParameters = inputSetsForAllArguments.size(); int nrOfParameters = inputSetsForAllArguments.size();
if (nrOfParameters == 0) { if (nrOfParameters == 0) {
return Collections.emptyList(); return Collections.emptyList();
@ -42,25 +44,25 @@ public class MethodcallArgumentsFactory {
} }
} }
private List<Pair> makeArgumentsForSingleParameterCall(List<List<?>> generatedInputSetsForAllArguments) { private List<LinkedList> makeArgumentsForSingleParameterCall(List<List<?>> generatedInputSetsForAllArguments) {
List<Pair> allPossibleArguments = new ArrayList<>(); List<LinkedList> allPossibleArguments = new ArrayList<>();
List<?> generatedInputs = generatedInputSetsForAllArguments.iterator().next(); List<?> generatedInputs = generatedInputSetsForAllArguments.iterator().next();
for (Object variable : generatedInputs) { for (Object variable : generatedInputs) {
Pair argument = new Pair(variable); LinkedList argument = new LinkedList(variable);
allPossibleArguments.add(argument); allPossibleArguments.add(argument);
} }
return allPossibleArguments; return allPossibleArguments;
} }
List<List<?>> getArgumentsForAllParameters(Class<?> testTarget, Method m) { List<List<?>> getArgumentsForAllParameters(Method method) {
List<List<?>> singleInputSets = new ArrayList<List<?>>(); List<List<?>> singleInputSets = new ArrayList<List<?>>();
for (Class<?> parametertype : m.getParameterTypes()) { for (Class<?> parametertype : method.getParameterTypes()) {
List<?> inputs = tryPrimitives(testTarget, parametertype); List<?> inputs = tryPrimitives(parametertype);
if (inputs == null) { if (inputs == null) {
inputs = new ObjectArgumentFactory().getObjectArgument(testTarget, parametertype); inputs = new ObjectArgumentFactory().getObjectArgument(parametertype);
} }
if (inputs != null) { if (inputs != null) {
singleInputSets.add(inputs); singleInputSets.add(inputs);
@ -69,7 +71,7 @@ public class MethodcallArgumentsFactory {
return singleInputSets; return singleInputSets;
} }
private ArgumentsForSingleParameter<?> tryPrimitives(Class<?> testTarget, Class<?> parametertype) { private ArgumentsForSingleParameter<?> tryPrimitives(Class<?> parametertype) {
ArgumentFactory<?> inputsFactory = primitivesFactories.get(parametertype); ArgumentFactory<?> inputsFactory = primitivesFactories.get(parametertype);
if (inputsFactory != null) { if (inputsFactory != null) {
return inputsFactory.getInputs(testTarget); return inputsFactory.getInputs(testTarget);

View file

@ -2,21 +2,20 @@ package nl.jssl.autounit.inputs.objects;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import nl.jssl.autounit.inputs.ArgumentsForSingleParameter;
import nl.jssl.autounit.inputs.MethodcallArgumentsFactory;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock; import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer; import org.mockito.stubbing.Answer;
import nl.jssl.autounit.inputs.ArgumentsForSingleParameter;
/** /**
* Creates arguments if they are objects. Methods that return values are populated like in regular mocking. * Creates arguments if they are objects. Methods that return values are
* populated like in regular mocking.
* *
*/ */
public class ObjectArgumentFactory { public class ObjectArgumentFactory {
private MethodcallArgumentsFactory argumentsFactory;
public ArgumentsForSingleParameter<?> getObjectArgument(Class<?> testTarget, Class<?> parametertype) { public ArgumentsForSingleParameter<?> getObjectArgument(Class<?> parametertype) {
ArgumentsForSingleParameter<Object> inputs = new ArgumentsForSingleParameter<Object>(); ArgumentsForSingleParameter<Object> inputs = new ArgumentsForSingleParameter<Object>();
Object mock = createMock(parametertype); Object mock = createMock(parametertype);
inputs.add(mock); inputs.add(mock);
@ -44,12 +43,9 @@ public class ObjectArgumentFactory {
} }
static boolean returnsVoid(Method m) { static boolean returnsVoid(Method method) {
Class<?> returnType = m.getReturnType(); Class<?> returnType = method.getReturnType();
return returnType != Void.TYPE; return returnType != Void.TYPE;
} }
public void setArgumentsFactory(MethodcallArgumentsFactory argumentsFactory) {
this.argumentsFactory = argumentsFactory;
}
} }

View file

@ -1,25 +1,24 @@
package nl.jssl.autounit.inputs.objects; package nl.jssl.autounit.inputs.objects;
import javassist.ClassPool;
import nl.jssl.autounit.inputs.ArgumentsForSingleParameter; import nl.jssl.autounit.inputs.ArgumentsForSingleParameter;
import nl.jssl.autounit.inputs.primitives.ArgumentFactory; import nl.jssl.autounit.inputs.primitives.ArgumentFactory;
import nl.jssl.autounit.util.ConstantpoolReader; import nl.jssl.autounit.util.ConstantpoolReader;
/** /**
* Creates Strings as arguments for a method call. Uses bytecode analysis to scan the class-under-test for "interesting" * Creates Strings as arguments for a method call. Uses bytecode analysis to
* strings and adds them to the argument set. * scan the class-under-test for "interesting" strings and adds them to the
* argument set.
* *
* Also adds null to check for NPE. //is this feasible? * Also adds null to check for NPE. //is this feasible?
*/ */
public class StringArgumentFactory implements ArgumentFactory<String> { public class StringArgumentFactory implements ArgumentFactory<String> {
private static ConstantpoolReader constantpoolReader = new ConstantpoolReader(ClassPool.getDefault());
@Override @Override
public ArgumentsForSingleParameter<String> getInputs(Class<?> testTarget) { public ArgumentsForSingleParameter<String> getInputs(Class<?> testTarget) {
ArgumentsForSingleParameter<String> inputs = new ArgumentsForSingleParameter<String>(); ArgumentsForSingleParameter<String> inputs = new ArgumentsForSingleParameter<String>();
inputs.add(null); inputs.add(null);
inputs.add("some"); inputs.add("some");
inputs.addAll(constantpoolReader.scanStrings(testTarget)); inputs.addAll(new ConstantpoolReader(testTarget).scanStrings());
return inputs; return inputs;
} }

View file

@ -4,7 +4,7 @@ import java.io.PrintStream;
import nl.jssl.autounit.classanalyser.ClassResults; import nl.jssl.autounit.classanalyser.ClassResults;
import nl.jssl.autounit.classanalyser.InAndOutput; import nl.jssl.autounit.classanalyser.InAndOutput;
import nl.jssl.autounit.classanalyser.MethodCallResults; import nl.jssl.autounit.classanalyser.MethodExecutionResults;
public class JUnitSourceWriter extends ResultsWriter { public class JUnitSourceWriter extends ResultsWriter {
@ -25,7 +25,7 @@ public class JUnitSourceWriter extends ResultsWriter {
out.println(); out.println();
out.println("public class " + results.getType().getSimpleName() + "Tests {"); out.println("public class " + results.getType().getSimpleName() + "Tests {");
Count index = new Count(1); Count index = new Count(1);
for (MethodCallResults mcr : results.getMethodCallResults()) { for (MethodExecutionResults mcr : results.getMethodCallResults()) {
for (InAndOutput inout : mcr.getContents()) { for (InAndOutput inout : mcr.getContents()) {
writeMethod(index, results, mcr, inout); writeMethod(index, results, mcr, inout);
} }
@ -34,7 +34,7 @@ public class JUnitSourceWriter extends ResultsWriter {
out.println("}"); out.println("}");
} }
private void writeMethod(Count index, ClassResults results, MethodCallResults mcr, InAndOutput inout) { private void writeMethod(Count index, ClassResults results, MethodExecutionResults mcr, InAndOutput inout) {
out.println("\t@Test"); out.println("\t@Test");
out.println("\tpublic void " + mcr.getMethodName() + index.getValue() + "(){"); out.println("\tpublic void " + mcr.getMethodName() + index.getValue() + "(){");
index.increment(); index.increment();
@ -54,7 +54,9 @@ public class JUnitSourceWriter extends ResultsWriter {
} }
private String toString(Class<?> type, Object object) { private String toString(Class<?> type, Object object) {
if (type == String.class) { if (type.toString().equals("void")) {
return "void";
} else if (type == String.class) {
return "\"" + object + "\""; return "\"" + object + "\"";
} else if (type == Double.class || type == double.class) { } else if (type == Double.class || type == double.class) {
return object.toString() + "D"; return object.toString() + "D";

View file

@ -1,32 +0,0 @@
package nl.jssl.autounit.results;
import java.io.PrintStream;
import com.thoughtworks.xstream.XStream;
import nl.jssl.autounit.classanalyser.ClassResults;
import nl.jssl.autounit.classanalyser.InAndOutput;
import nl.jssl.autounit.classanalyser.MethodCallResults;
import nl.jssl.autounit.util.Pair;
import nl.jssl.autounit.util.XStreamArgumentsConverter;
public class XStreamResultsWriter extends ResultsWriter {
private XStream xstream = new XStream();
public XStreamResultsWriter(PrintStream out) {
super(out);
setup();
}
@Override
public void write(ClassResults results) {
xstream.toXML(results, out);
}
private void setup() {
xstream.alias("case", InAndOutput.class);
xstream.alias("results", MethodCallResults.class);
xstream.alias("args", Pair.class);
xstream.registerConverter(new XStreamArgumentsConverter());
}
}

View file

@ -9,29 +9,29 @@ import javassist.NotFoundException;
import javassist.bytecode.ConstPool; import javassist.bytecode.ConstPool;
/** /**
* Reads the constantpool of a class (see jvm spec)
*/ */
public class ConstantpoolReader { public class ConstantpoolReader {
private ClassPool pool; private final static ClassPool pool;
private final Class<?> classToRead;
private final List<String> strings = new ArrayList<String>();
public ConstantpoolReader(ClassPool pool) { static {
this.pool = pool; pool = ClassPool.getDefault();
} }
public List<String> scanStrings(Class<?> target) { public ConstantpoolReader(Class<?> classToRead) {
this.classToRead = classToRead;
}
public List<String> scanStrings() {
CtClass ctClass; CtClass ctClass;
try { try {
ctClass = pool.get(target.getName()); ctClass = pool.get(classToRead.getName());
List<String> strings = new ArrayList<String>();
if (isScannable(ctClass)) { if (isScannable(ctClass)) {
ConstPool constPool = ctClass.getClassFile().getConstPool(); ConstPool constPool = ctClass.getClassFile().getConstPool();
int size = constPool.getSize(); doScanStrings(constPool);
for (int i = 1; i < size; i++) {
int tag = constPool.getTag(i);
if (tag == ConstPool.CONST_String) {
strings.add(constPool.getStringInfo(i));
}
}
} }
return strings; return strings;
} catch (NotFoundException e) { } catch (NotFoundException e) {
@ -39,6 +39,16 @@ public class ConstantpoolReader {
} }
} }
private void doScanStrings(ConstPool constPool) {
for (int i = 1; i < constPool.getSize(); i++) {
int tag = constPool.getTag(i);
if (tag == ConstPool.CONST_String) {
strings.add(constPool.getStringInfo(i));
}
}
}
private boolean isScannable(CtClass ctClass) { private boolean isScannable(CtClass ctClass) {
return !ctClass.isFrozen(); return !ctClass.isFrozen();
} }

View file

@ -4,16 +4,16 @@ import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
public class Pair implements Iterable<Object> { public class LinkedList implements Iterable<Object> {
public final Object element1; public final Object element1;
public final Object element2; public final Object element2;
public Pair(Object element1) { public LinkedList(Object element1) {
this.element1 = element1; this.element1 = element1;
this.element2 = null; this.element2 = null;
} }
public Pair(Object element1, Object element2) { public LinkedList(Object element1, Object element2) {
super(); super();
this.element1 = element1; this.element1 = element1;
this.element2 = element2; this.element2 = element2;
@ -22,15 +22,15 @@ public class Pair implements Iterable<Object> {
public int depth() { public int depth() {
int d = 0; int d = 0;
if (element2 != null) { if (element2 != null) {
if (element2 instanceof Pair) { if (element2 instanceof LinkedList) {
d += 1 + ((Pair) element2).depth(); d += 1 + ((LinkedList) element2).depth();
} else { } else {
d += 1; d += 1;
} }
} }
if (element1 != null) { if (element1 != null) {
if (element1 instanceof Pair) { if (element1 instanceof LinkedList) {
d += 1 + ((Pair) element1).depth(); d += 1 + ((LinkedList) element1).depth();
} else { } else {
d += 1; d += 1;
} }
@ -57,8 +57,8 @@ public class Pair implements Iterable<Object> {
} }
private void add(Object element, List<Object> list) { private void add(Object element, List<Object> list) {
if (element instanceof Pair) { if (element instanceof LinkedList) {
Pair pair = (Pair) element; LinkedList pair = (LinkedList) element;
add(pair.element1, list); add(pair.element1, list);
add(pair.element2, list); add(pair.element2, list);
} else { } else {

View file

@ -10,24 +10,30 @@ import java.util.List;
*/ */
public class Permuter { public class Permuter {
public static List<Pair> permute(List<List<?>> elements) { public static List<LinkedList> permute(List<List<?>> elements) {
if (elements.size() >= 2) { if (elements.size() >= 2) {
List<Pair> result = permutePairs(elements.remove(0), elements.remove(0)); List<LinkedList> result = permutePairs(elements.remove(0), elements.remove(0));
result = permuteRest(elements, result);
for (List<?> element : elements) {
result = permutePairs(element, result);
}
return result; return result;
} else { } else {
throw new IllegalArgumentException("need at least 2"); throw new IllegalArgumentException("need at least 2");
} }
} }
private static List<Pair> permutePairs(List<?> list1, List<?> list2) { private static List<LinkedList> permuteRest(List<List<?>> elements, List<LinkedList> result) {
List<Pair> pairs = new ArrayList<Pair>(); for (List<?> element : elements) {
result = permutePairs(element, result);
}
return result;
}
private static List<LinkedList> permutePairs(List<?> list1, List<?> list2) {
List<LinkedList> pairs = new ArrayList<LinkedList>();
for (Object element1 : list1) { for (Object element1 : list1) {
for (Object element2 : list2) { for (Object element2 : list2) {
pairs.add(new Pair(element1, element2)); pairs.add(new LinkedList(element1, element2));
} }
} }
return pairs; return pairs;

View file

@ -1,7 +1,9 @@
package nl.jssl.autounit.util; package nl.jssl.autounit.util;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import nl.jssl.autounit.classanalyser.AnalysisFailed;
import sun.reflect.ReflectionFactory; import sun.reflect.ReflectionFactory;
/** /**
@ -16,14 +18,20 @@ public class SilentObjectCreator {
public static <T> T create(Class<T> clazz, Class<? super T> parent) { public static <T> T create(Class<T> clazz, Class<? super T> parent) {
try { try {
ReflectionFactory rf = ReflectionFactory.getReflectionFactory(); return tryCreateInstance(clazz, parent);
Constructor<?> objDef = parent.getDeclaredConstructor(); } catch (NoSuchMethodException | InstantiationException | IllegalAccessException
Constructor<T> intConstr = (Constructor<T>) rf.newConstructorForSerialization(clazz, objDef); | InvocationTargetException e) {
return clazz.cast(intConstr.newInstance()); throw new AnalysisFailed("Cannot create object", e);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new IllegalStateException("Cannot create object", e);
} }
} }
@SuppressWarnings("unchecked")
private static <T> T tryCreateInstance(Class<T> clazz, Class<? super T> parent)
throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
ReflectionFactory reflectionFactory = ReflectionFactory.getReflectionFactory();
Constructor<?> objDef = parent.getDeclaredConstructor();
Constructor<T> intConstr = (Constructor<T>) reflectionFactory.newConstructorForSerialization(clazz, objDef);
return clazz.cast(intConstr.newInstance());
}
} }

View file

@ -1,31 +0,0 @@
package nl.jssl.autounit.util;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
public class XStreamArgumentsConverter implements Converter {
@SuppressWarnings("rawtypes")
public boolean canConvert(Class clazz) {
return (clazz == Pair.class);
}
public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) {
Pair arguments = (Pair) value;
int index = 1;
for (Object arg : arguments) {
writer.startNode("arg" + index);
writer.setValue(arg.toString());
writer.endNode();
}
}
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
return null;
}
}

View file

@ -17,15 +17,15 @@ import nl.jssl.autounit.testclasses.IntArguments;
public class PrimtiveTypeTests { public class PrimtiveTypeTests {
@Test @Test
public void testGetPublicMethods() throws NoSuchMethodException, SecurityException { public void testGetPublicMethods() throws NoSuchMethodException, SecurityException {
List<Method> publicMethods = new ClassAnalyser(IntArguments.class).getPublicMethods(); List<Method> publicMethods = new ClassAnalyser<>(IntArguments.class).getPublicMethods();
assertEquals(2, publicMethods.size()); assertEquals(2, publicMethods.size());
} }
@Test @Test
public void testIntegerArgument() { public void testIntegerArgument() {
Iterator<MethodCallResults> methodCallResults = new TreeSet<>( Iterator<MethodExecutionResults> methodCallResults = new TreeSet<>(
new ClassAnalyser(IntArguments.class).analyse().getMethodCallResults()).iterator(); new ClassAnalyser<>(IntArguments.class).analyseAndGetResults().getMethodCallResults()).iterator();
assertEquals("public java.lang.String evenOrUneven(int arg1,int arg2)", assertEquals("public java.lang.String evenOrUneven(int arg1,int arg2)",
methodCallResults.next().getMethodSignature()); methodCallResults.next().getMethodSignature());
@ -34,19 +34,22 @@ public class PrimtiveTypeTests {
@Test @Test
public void testBooleanArgument() { public void testBooleanArgument() {
MethodCallResults mcr = new ClassAnalyser(BooleanArguments.class).analyse().getMethodCallResults().get(0); MethodExecutionResults mcr = new ClassAnalyser<>(BooleanArguments.class).analyseAndGetResults()
.getMethodCallResults().get(0);
assertEquals(mcr.getMethodSignature(), "public java.lang.String getText(boolean arg1,boolean arg2)"); assertEquals(mcr.getMethodSignature(), "public java.lang.String getText(boolean arg1,boolean arg2)");
} }
@Test @Test
public void testByteArgument() { public void testByteArgument() {
MethodCallResults mcr = new ClassAnalyser(ByteArguments.class).analyse().getMethodCallResults().get(0); MethodExecutionResults mcr = new ClassAnalyser<>(ByteArguments.class).analyseAndGetResults().getMethodCallResults()
.get(0);
assertEquals(mcr.getMethodSignature(), "public int getDouble(byte arg1)"); assertEquals(mcr.getMethodSignature(), "public int getDouble(byte arg1)");
} }
@Test @Test
public void testFloatArgument() { public void testFloatArgument() {
MethodCallResults mcr = new ClassAnalyser(FloatArguments.class).analyse().getMethodCallResults().get(0); MethodExecutionResults mcr = new ClassAnalyser<>(FloatArguments.class).analyseAndGetResults().getMethodCallResults()
.get(0);
assertEquals(mcr.getMethodSignature(), "public int round(float arg1)"); assertEquals(mcr.getMethodSignature(), "public int round(float arg1)");
} }

View file

@ -12,8 +12,9 @@ public class StringTypeTests {
@Test @Test
public void testStringArgumentShouldBeTjeempie() { public void testStringArgumentShouldBeTjeempie() {
List<MethodCallResults> results = new ClassAnalyser(StringArguments.class).analyse().getMethodCallResults(); List<MethodExecutionResults> results = new ClassAnalyser<>(StringArguments.class).analyseAndGetResults()
MethodCallResults mcr = results.get(0); .getMethodCallResults();
MethodExecutionResults mcr = results.get(0);
String methodSignature = mcr.getMethodSignature(); String methodSignature = mcr.getMethodSignature();
assertEquals("public boolean getBar(java.lang.String arg1)", methodSignature); assertEquals("public boolean getBar(java.lang.String arg1)", methodSignature);
System.out.println(mcr.getCoverageResult().getLineCounter().getMissedCount() + " missed lines"); System.out.println(mcr.getCoverageResult().getLineCounter().getMissedCount() + " missed lines");

View file

@ -7,14 +7,15 @@ import java.util.TreeSet;
import org.junit.Test; import org.junit.Test;
import nl.jssl.autounit.JUnitTestCreator;
import nl.jssl.autounit.classanalyser.ClassAnalyser; import nl.jssl.autounit.classanalyser.ClassAnalyser;
import nl.jssl.autounit.classanalyser.MethodCallResults; import nl.jssl.autounit.classanalyser.MethodExecutionResults;
import nl.jssl.autounit.testclasses.SomeBean; import nl.jssl.autounit.testclasses.SomeBean;
public class JavaBeanTests { public class JavaBeanTests {
@Test @Test
public void testJavaBeanArgument() { public void testJavaBeanArgument() {
Iterator<MethodCallResults> results = getSortedAnalysisResults().iterator(); Iterator<MethodExecutionResults> results = getSortedAnalysisResults().iterator();
assertEquals("public int getBar()", results.next().getMethodSignature()); assertEquals("public int getBar()", results.next().getMethodSignature());
assertEquals("public java.lang.String getFoo()", results.next().getMethodSignature()); assertEquals("public java.lang.String getFoo()", results.next().getMethodSignature());
@ -22,7 +23,12 @@ public class JavaBeanTests {
assertEquals("public void setFoo(java.lang.String arg1)", results.next().getMethodSignature()); assertEquals("public void setFoo(java.lang.String arg1)", results.next().getMethodSignature());
} }
private TreeSet<MethodCallResults> getSortedAnalysisResults() { private TreeSet<MethodExecutionResults> getSortedAnalysisResults() {
return new TreeSet<>(new ClassAnalyser(SomeBean.class).analyse().getMethodCallResults()); return new TreeSet<>(new ClassAnalyser<>(SomeBean.class).analyseAndGetResults().getMethodCallResults());
}
@Test
public void getUnittest() {
new JUnitTestCreator<>(SomeBean.class).create();
} }
} }

View file

@ -1,5 +1,6 @@
package nl.jssl.autounit.inputs.objects; package nl.jssl.autounit.inputs.objects;
import static nl.jssl.autounit.inputs.objects.ObjectArgumentFactory.returnsVoid;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@ -9,12 +10,11 @@ import org.junit.Test;
public class ObjectArgumentFactoryTests { public class ObjectArgumentFactoryTests {
@Test @Test
public void testVoidReturn() throws NoSuchMethodException, SecurityException { public void testVoidReturn() throws NoSuchMethodException, SecurityException {
ObjectArgumentFactory o = new ObjectArgumentFactory();
Method testVoidReturnMethod = ObjectArgumentFactoryTests.class.getMethod("testVoidReturn", new Class<?>[] {}); Method testVoidReturnMethod = ObjectArgumentFactoryTests.class.getMethod("testVoidReturn", new Class<?>[] {});
assertEquals(false, o.returnsVoid(testVoidReturnMethod)); assertEquals(false, returnsVoid(testVoidReturnMethod));
Method getBarMethod = ObjectArgumentFactoryTests.class.getMethod("getBar", new Class<?>[] {}); Method getBarMethod = ObjectArgumentFactoryTests.class.getMethod("getBar", new Class<?>[] {});
assertEquals(true, o.returnsVoid(getBarMethod)); assertEquals(true, returnsVoid(getBarMethod));
} }
public String getBar() { public String getBar() {

View file

@ -4,7 +4,6 @@ import java.util.List;
import org.junit.Test; import org.junit.Test;
import javassist.ClassPool;
import javassist.NotFoundException; import javassist.NotFoundException;
import nl.jssl.autounit.testclasses.IntArguments; import nl.jssl.autounit.testclasses.IntArguments;
import nl.jssl.autounit.util.ConstantpoolReader; import nl.jssl.autounit.util.ConstantpoolReader;
@ -12,10 +11,8 @@ import nl.jssl.autounit.util.ConstantpoolReader;
public class ConstantpoolReaderTest { public class ConstantpoolReaderTest {
@Test @Test
public void test() throws NotFoundException { public void test() throws NotFoundException {
ClassPool classPool = new ClassPool(); ConstantpoolReader reader = new ConstantpoolReader(IntArguments.class);
classPool.appendClassPath("bin"); List<String> strings = reader.scanStrings();
ConstantpoolReader reader = new ConstantpoolReader(classPool);
List<String> strings = reader.scanStrings(IntArguments.class);
for (String string : strings) { for (String string : strings) {
System.out.println(string); System.out.println(string);
} }

View file

@ -7,19 +7,19 @@ import org.junit.Test;
public class PairTests { public class PairTests {
@Test @Test
public void testDepth1() { public void testDepth1() {
Pair p = new Pair("1"); LinkedList p = new LinkedList("1");
assertEquals(1, p.depth()); assertEquals(1, p.depth());
} }
@Test @Test
public void testDepth2() { public void testDepth2() {
Pair p = new Pair(new Pair("1")); LinkedList p = new LinkedList(new LinkedList("1"));
assertEquals(2, p.depth()); assertEquals(2, p.depth());
} }
@Test @Test
public void testDepth3() { public void testDepth3() {
Pair p = new Pair(new Pair(new Pair("1"))); LinkedList p = new LinkedList(new LinkedList(new LinkedList("1")));
assertEquals(3, p.depth()); assertEquals(3, p.depth());
} }
} }

View file

@ -21,7 +21,7 @@ public class PermuterTests {
List<List<?>> outer = new ArrayList<List<?>>(); List<List<?>> outer = new ArrayList<List<?>>();
outer.add(integers); outer.add(integers);
outer.add(strings); outer.add(strings);
List<Pair> permuted = Permuter.permute(outer); List<LinkedList> permuted = Permuter.permute(outer);
assertEquals("1-A-", permuted.get(0).toString()); assertEquals("1-A-", permuted.get(0).toString());
assertEquals("1-B-", permuted.get(1).toString()); assertEquals("1-B-", permuted.get(1).toString());
@ -46,7 +46,7 @@ public class PermuterTests {
outer.add(strings); outer.add(strings);
outer.add(vogons); outer.add(vogons);
List<Pair> permuted = Permuter.permute(outer); List<LinkedList> permuted = Permuter.permute(outer);
assertEquals("Vogon Jeltz-1-A-", permuted.get(0).toString()); assertEquals("Vogon Jeltz-1-A-", permuted.get(0).toString());
assertEquals("Vogon Jeltz-1-B-", permuted.get(1).toString()); assertEquals("Vogon Jeltz-1-B-", permuted.get(1).toString());
assertEquals("Vogon Jeltz-2-A-", permuted.get(2).toString()); assertEquals("Vogon Jeltz-2-A-", permuted.get(2).toString());