From ae2cd39e36152de6add62ec2fe092355596c2077 Mon Sep 17 00:00:00 2001 From: Maksim Pelevin Date: Fri, 15 Jul 2022 09:37:22 +0300 Subject: [PATCH] Remove obsolete fuzzing code and update readme.md #467 --- utbot-fuzzers/readme.md | 172 +++++++++- .../fuzzer/baseline/generator/Generator.java | 48 --- .../baseline/generator/TestMethodGen.java | 71 ----- .../baseline/generator/TypeChooser.java | 26 -- .../utbot/fuzzer/baseline/generator/Util.java | 89 ------ .../fuzzer/baseline/generator/ValueGen.java | 299 ------------------ .../utbot/fuzzer/ObsoleteTestCaseGenerator.kt | 9 - .../utbot/fuzzer/baseline/BaselineFuzzer.kt | 22 -- .../utbot/fuzzer/primitive/PrimitiveFuzzer.kt | 48 --- .../plugin/api/FuzzerTestCaseGeneratorTest.kt | 51 --- 10 files changed, 158 insertions(+), 677 deletions(-) delete mode 100644 utbot-fuzzers/src/main/java/org/utbot/fuzzer/baseline/generator/Generator.java delete mode 100644 utbot-fuzzers/src/main/java/org/utbot/fuzzer/baseline/generator/TestMethodGen.java delete mode 100644 utbot-fuzzers/src/main/java/org/utbot/fuzzer/baseline/generator/TypeChooser.java delete mode 100644 utbot-fuzzers/src/main/java/org/utbot/fuzzer/baseline/generator/Util.java delete mode 100644 utbot-fuzzers/src/main/java/org/utbot/fuzzer/baseline/generator/ValueGen.java delete mode 100644 utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/ObsoleteTestCaseGenerator.kt delete mode 100644 utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/baseline/BaselineFuzzer.kt delete mode 100644 utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/primitive/PrimitiveFuzzer.kt delete mode 100644 utbot-fuzzers/src/test/kotlin/org/utbot/framework/plugin/api/FuzzerTestCaseGeneratorTest.kt diff --git a/utbot-fuzzers/readme.md b/utbot-fuzzers/readme.md index 14327ea259..f15cb0b06f 100644 --- a/utbot-fuzzers/readme.md +++ b/utbot-fuzzers/readme.md @@ -1,28 +1,58 @@ # UTBot Fuzzer -Fuzzer generates method input values to improve method coverage or find unexpected errors. In UTBot next strategies can be used to find those values: +Fuzzer generates method input values to improve method coverage or find unexpected errors. In UTBot next strategies can be used to find values like: * **Default values** for objects, e.g. 0, 0.0, empty string or null values. -* **Bound values** of primitives types, e.g. Integer.MAX_VALUE, Double.POSITIVE_INFINITY, etc. +* **Corner case values** of primitives types, e.g. Integer.MAX_VALUE, Double.POSITIVE_INFINITY, etc. * **Method constants and their simple mutations** of primitive types. -* **Simple objects** created via its constructors. +* **Objects** created via its constructors or field mutators. + +After values are found fuzzer creates all its possible combinations and runs methods with these combinations. + +For example, if a method has two parameters of types `boolean` and `int` the follow values can be found: +``` +boolean = [false, true] +int = [0, MAX_VALUE, MIN_VALUE] +``` + +Now, fuzzer creates `2 * 3 = 6` combinations of them: + +``` +[false, 0], [false, MAX_VALUE], [false, MIN_VALUE], [true, 0], [true, MAX_VALUE], [true, MIN_VALUE] +``` + +To find more branches of execution as fast as possible fuzzer also shuffles +combinations and supplies them for the running. ## Design -Fuzzer requires model providers which are a simple functions to create a set of `UtModel` for a given `ClassId`. Fuzzer iterates through these providers and creates models, which are used for generating all possible combinations. Each combination contains values for the method. For example, if a method has `String, double, int` as parameters then fuzzer can create combination `"sometext", Double.POSITIVE_INFINITY, 0`. +Fuzzer requires model providers that create a set of `UtModel` for a given `ClassId`. +Fuzzer iterates through these providers and creates models, which are used for generating combinations later. +Each combination contains concrete values that can be accepted by the method. +For example, if a method has signature with `String, double, int` as parameters then fuzzer can create combination `"sometext", Double.POSITIVE_INFINITY, 0`. Fuzzer's entry point is: ```kotlin // org.utbot.fuzzer.FuzzerKt -fun fuzz(method: FuzzedMethodDescription, vararg models: ModelProvider): Sequence> +fun fuzz(method: FuzzedMethodDescription, vararg models: ModelProvider): Sequence> ``` +`FuzzedMethodDescription` stores comprehensive information about a method: +* signature (parameters and return types) +* name/package/class (optional) +* constants found in the method body (should be replaced with CGF when possible) + +`ModelProvider` provides models for a give parameters set as described below. + +Fuzz method returns a sequence of acceptable values for the method in random order. The sequence is lazy. + Model provider should implement ```kotlin -fun generate(description: FuzzedMethodDescription, consumer: BiConsumer) +fun generate(description: FuzzedMethodDescription): Sequence ``` -where consumer accepts 2 values: index of a parameter for the method and model for this parameter. For every parameter should exist at least one `UtModel`. `ModelProvider.withFallback` can be used to process those classes which cannot be processed by provider. Several providers can be combined into one by using `ModelProvider.with(anotherModel: ModelProvider)`. +For every parameter should exist at least one `UtModel`. `ModelProvider.withFallback` can be used to process those classes which cannot be processed by provider. +Several providers can be combined into one by using `ModelProvider.with(anotherModel: ModelProvider)`. Common way to generate all combinations is: @@ -30,7 +60,7 @@ Common way to generate all combinations is: ObjectModelProvider() .with(PrimitiveModelProvider) // ... - .with(NullModelProvider) + .with(ObjectModelProvider) .withFallback { classId -> createDefaultModelByClass(classID) } @@ -39,24 +69,138 @@ or ```kotlin // org.utbot.fuzzer.FuzzerKt -fun defaultModelProviders(idGenerator: ToIntFunction) +fun defaultModelProviders(idGenerator: IntSupplier) ``` -## List of builtin Providers +## List of builtin providers + +### PrimitiveDefaultsModelProvider + +Creates default values for every primitive types: + +``` +boolean: false +byte: 0 +short: 0 +int: 0 +long: 0 +float: 0.0 +double: 0.0 +char: \u0000 +string: "" +``` ### PrimitiveModelProvider Creates default values and some corner case values such as Integer.MAX_VALUE, 0.0, Double.NaN, empty string, etc. +``` +boolean: false, true +byte: 0, 1, -1, Byte.MIN_VALUE, Byte.MAX_VALUE +short: 0, 1, -1, Short.MIN_VALUE, Short.MAX_VALUE +int: 0, 1, -1, Integer.MIN_VALUE, Integer.MAX_VALUE +long: 0, 1, -1, Long.MIN_VALUE, Long.MAX_VALUE +float: 0.0, 1.1, -1.1, Float.MIN_VALUE, Float.MAX_VALUE, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY, Float.NaN +double: 0.0, 1.1, -1.1, Double.MIN_VALUE, Double.MAX_VALUE, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Double.NaN +char: Char.MIN_VALUE, Char.MAX_VALUE +string: "", " ", "string", "\n\t\r" +``` + +### PrimitiveWrapperModelProvider + +Creates primitive models for boxed types: `Boolean`, `Byte`, `Short`, `Integer`, `Long`, `Double`, `Float`, `Character`, `String` + ### ConstantsModelProvider Uses information about concrete values from `FuzzedMethodDescription#concreteValues` to generate simple values. -At the moment, only primitive values are supported. +Only primitive values are supported. + +### NullModelProvider + +Creates `UtNullModel` for every reference class. + +### EnumModelProvider + +Creates models for any enum type. + +### CollectionModelProvider + +Creates concrete collections for collection interfaces: `List`, `Set`, `Map`, `Collection`, `Iterable`, `Iterator` + +### ArrayModelProvider + +Creates an empty and non-empty for any type. ### ObjectModelProvider -Creates models of class that has public constructor with primitives as parameters only. +ObjectModelProvider is the most sophisticated provider. It creates model of class that has public constructors +and public mutators (fields or setters/getters). If class has constructor that accepts another object within an argument that value +is created recursively. Depth of recursion is limited to 1. Thus, for inner object fuzzing doesn't try to use every +constructor but find the one with the least number of parameters and, if it is possible, only +constructor with primitives values. If there is available only constructor with another object as a parameter then +`null` is passed to it. + +Let's look at this example: + +```java +class A { + private int a; + private Object object; + + public A(int a, A o) { + this.a = a; + this.o = o; + } +} +``` -### NullModelProvider +For it fuzzing create these models: +``` +new Object(0, new A(0, null)); +new Object(Integer.MIN_VALUE, new A(0, null)); +new Object(Integer.MAX_VALUE, new A(0, null)); +new Object(0, new A(Integer.MIN_VALUE, null)); +new Object(Integer.MIN_VALUE, new A(Integer.MIN_VALUE, null)); +new Object(Integer.MAX_VALUE, new A(Integer.MIN_VALUE, null)); +new Object(0, new A(Integer.MAX_VALUE, null)); +new Object(Integer.MIN_VALUE, new A(Integer.MAX_VALUE, null)); +new Object(Integer.MAX_VALUE, new A(Integer.MAX_VALUE, null)); +``` + +For classes that have empty public constructor and field mutators all those mutators will be fuzzed as well. +Field mutators are listed below: +* public or package-private (and accessible) non-final non-static fields +* pairs of setter/getter that satisfy the common agreement: + * setter/getter is public or package-private (and accessible) + * have field name as a postfix, e.g.: `int myField -> * setMyField(int v)/int getMyField()`, where * means any returned type + +For example, fields _a_, _b_ and _d_ will be fuzzed, but _c_ and _e_ will not: + +```java +class A { + int a; + public char b; + public final int c = 0; + private String d; + private boolean e; + + public A setD(String s) { + this.d = s; + return this; + } + + public String getD() { + return d; + } + + public boolean getE() { + return e; + } +} +``` + +### Other providers -Creates `UtNullModel` for every reference class. \ No newline at end of file +There are several other providers that can find some values, using addition information, +like `CharToStringModelProvider` that takes all chars found in `charAt(i) == c` statement +and merge them into several strings. \ No newline at end of file diff --git a/utbot-fuzzers/src/main/java/org/utbot/fuzzer/baseline/generator/Generator.java b/utbot-fuzzers/src/main/java/org/utbot/fuzzer/baseline/generator/Generator.java deleted file mode 100644 index 86cd17e7e4..0000000000 --- a/utbot-fuzzers/src/main/java/org/utbot/fuzzer/baseline/generator/Generator.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.utbot.fuzzer.baseline.generator; - -import org.utbot.framework.plugin.api.UtMethod; -import org.utbot.framework.plugin.api.UtValueExecution; -import org.utbot.framework.plugin.api.UtMethodValueTestSet; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import kotlin.jvm.JvmClassMappingKt; -import kotlin.reflect.KCallable; -import kotlin.reflect.KClass; -import kotlin.reflect.KFunction; -import kotlin.reflect.jvm.ReflectJvmMapping; - -import static java.util.Collections.emptyMap; - -public class Generator { - public static List> executions(UtMethod utMethod, Class clazz, Object caller) { - return Arrays.stream(clazz.getDeclaredMethods()) - .filter(method -> isSameMethod(utMethod, method)) - .filter(method -> !Modifier.isPrivate(method.getModifiers())) - .map(method -> new TestMethodGen(method, caller).gen()) - .findFirst().orElseGet(Collections::emptyList); - } - - private static boolean isSameMethod(UtMethod utMethod, Method method) { - KCallable utCallable = utMethod.getCallable(); - if (!(utCallable instanceof KFunction)) { - return false; - } - KFunction utKFunction = (KFunction) utCallable; - Method utJavaMethod = ReflectJvmMapping.getJavaMethod(utKFunction); - if (utJavaMethod == null) { - return false; - } - return utJavaMethod.equals(method); - } - - public static UtMethodValueTestSet generateTests(UtMethod method) throws IllegalAccessException, InstantiationException { - KClass kClass = method.getClazz(); - Class clazz = JvmClassMappingKt.getJavaClass(kClass); - // TODO: newInstance() is deprecated, need to create an instance in another way - Object object = clazz.newInstance(); - return new UtMethodValueTestSet<>(method, executions(method, clazz, object), emptyMap()); - } -} diff --git a/utbot-fuzzers/src/main/java/org/utbot/fuzzer/baseline/generator/TestMethodGen.java b/utbot-fuzzers/src/main/java/org/utbot/fuzzer/baseline/generator/TestMethodGen.java deleted file mode 100644 index ae06530b7e..0000000000 --- a/utbot-fuzzers/src/main/java/org/utbot/fuzzer/baseline/generator/TestMethodGen.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.utbot.fuzzer.baseline.generator; - -import org.utbot.framework.plugin.api.UtConcreteValue; -import org.utbot.framework.plugin.api.UtValueExecution; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.util.ArrayList; -import java.util.List; - -import static org.utbot.fuzzer.baseline.BaselineFuzzerKt.failedUtExecution; -import static org.utbot.fuzzer.baseline.BaselineFuzzerKt.successfulUtExecution; - - -/** - * - */ -public class TestMethodGen { - // TODO: add selection of test cases number to the plugin - private final int TEST_CASES_NUMBER = 5; - - private final Method method; - private final Object caller; - - private final TypeVariable[] typeParameters; - private final Type[] typeValues; - - public TestMethodGen(Method method, Object caller) { - this.method = method; - this.caller = caller; - typeParameters = method.getTypeParameters(); - typeValues = TypeChooser.chooseTypeParameterValues(typeParameters); - } - - public List> gen() { - List> executions = new ArrayList<>(); - for (int i = 0; i < TEST_CASES_NUMBER; i++) { - UtValueExecution execution = generateExecution(); - if (execution != null) { - executions.add(generateExecution()); - } - } - return executions; - } - - private UtValueExecution generateExecution() { - List> params = new ArrayList<>(); - for (int i = 0; i < method.getParameters().length; i++) { - Type parType = method.getGenericParameterTypes()[i]; - ValueGen valueGen = new ValueGen(parType, typeParameters, typeValues); - Object value = valueGen.generate(); - params.add(UtConcreteValue.invoke(value)); - } - Object[] arguments = params.stream() - .map(UtConcreteValue::getValue).toArray(); - - UtValueExecution execution; - try { - Object result = method.invoke(caller, arguments); - execution = successfulUtExecution(params, result); - } catch (IllegalAccessException | InvocationTargetException e) { - // TODO: what if these exceptions were thrown by the method under test? - return null; - } catch (Exception e) { - execution = failedUtExecution(params, e); - } - - return execution; - } -} diff --git a/utbot-fuzzers/src/main/java/org/utbot/fuzzer/baseline/generator/TypeChooser.java b/utbot-fuzzers/src/main/java/org/utbot/fuzzer/baseline/generator/TypeChooser.java deleted file mode 100644 index d28cbd2e81..0000000000 --- a/utbot-fuzzers/src/main/java/org/utbot/fuzzer/baseline/generator/TypeChooser.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.utbot.fuzzer.baseline.generator; - -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; - -/** - * - */ -public class TypeChooser { - private static Type chooseType(TypeVariable typeVariable) { - Type[] bounds = typeVariable.getBounds(); - if (bounds.length <= 0) { - return null; - } - Type bound = bounds[0]; - return bound; - } - - public static Type[] chooseTypeParameterValues(TypeVariable[] typeParameters) { - Type[] typeValues = new Type[typeParameters.length]; - for (int i = 0; i < typeParameters.length; i++) { - typeValues[i] = chooseType(typeParameters[i]); - } - return typeValues; - } -} diff --git a/utbot-fuzzers/src/main/java/org/utbot/fuzzer/baseline/generator/Util.java b/utbot-fuzzers/src/main/java/org/utbot/fuzzer/baseline/generator/Util.java deleted file mode 100644 index 0655329c59..0000000000 --- a/utbot-fuzzers/src/main/java/org/utbot/fuzzer/baseline/generator/Util.java +++ /dev/null @@ -1,89 +0,0 @@ -package org.utbot.fuzzer.baseline.generator; - -import java.lang.reflect.GenericArrayType; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.util.LinkedList; -import java.util.List; -import java.util.Random; -import java.util.regex.Pattern; - -/** - * - */ -public class Util { - private static final Random rnd = new Random(); - - public static List addTabs(List src, int count) { - List res = new LinkedList(); - for (String line : src) { - String tabs = ""; - for (int i = 0; i < count; i++) { - tabs += "\t"; - } - res.add(tabs + line); - } - return res; - } - - public static int findType(TypeVariable[] typeVariables, TypeVariable findThis) { - String typeName = findThis.getName(); - for (int i = 0; i < typeVariables.length; i++) { - if (typeVariables[i].getName().equals(typeName)) { - return i; - } - } - return -1; - } - - public static String getTypeName(Type t, TypeVariable[] typeVariables, Type[] typeValues) { - String res = t.getTypeName(); - if (typeVariables != null && typeValues != null - && typeVariables.length > 0 && typeValues.length == typeVariables.length) { - for (int i = 0; i < typeVariables.length; i++) { - String pattern = "\\b" + Pattern.quote(typeVariables[i].getName()) + "\\b"; - String value = typeValues[i].getTypeName(); - res = res.replaceAll(pattern, value); - } - } - return res; - } - - public static int rndRange(int min, int max) { - return rnd.nextInt(max - min + 1) + min; - } - - public static int getArrayDepth(Type t) { - int count = 0; - while ((t instanceof GenericArrayType) - || (t instanceof Class && ((Class) t).isArray())) { - count++; - if (t instanceof GenericArrayType) { - t = ((GenericArrayType) t).getGenericComponentType(); - } else { - t = ((Class) t).getComponentType(); - } - } - return count; - } - - public static Type getArrayChildType(Type t) { - while ((t instanceof GenericArrayType) - || (t instanceof Class && ((Class) t).isArray())) { - if (t instanceof GenericArrayType) { - t = ((GenericArrayType) t).getGenericComponentType(); - } else { - t = ((Class) t).getComponentType(); - } - } - return t; - } - - public static String repeat(String str, int count) { - String res = ""; - for (int i = 0; i < count; i++) { - res += str; - } - return res; - } -} diff --git a/utbot-fuzzers/src/main/java/org/utbot/fuzzer/baseline/generator/ValueGen.java b/utbot-fuzzers/src/main/java/org/utbot/fuzzer/baseline/generator/ValueGen.java deleted file mode 100644 index fe7794607f..0000000000 --- a/utbot-fuzzers/src/main/java/org/utbot/fuzzer/baseline/generator/ValueGen.java +++ /dev/null @@ -1,299 +0,0 @@ -package org.utbot.fuzzer.baseline.generator; - -import java.lang.reflect.Constructor; -import java.lang.reflect.GenericArrayType; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Random; -import java.util.Set; - -/** - * - */ -public class ValueGen { - private final static Random rnd = new Random(); - - private Type type; - private TypeVariable[] methodTypeParameters; - private Type[] methodTypeValues; - - private final String LIST_TYPE = "java.util.List"; - private final String ARRAY_LIST_TYPE = "java.util.ArrayList"; - private final String LINKED_LIST_TYPE = "java.util.LinkedList"; - - private final Set LIST_TYPES = new HashSet<>( - Arrays.asList( - LIST_TYPE, - ARRAY_LIST_TYPE, - LINKED_LIST_TYPE - ) - ); - - public ValueGen(Type type, TypeVariable[] methodTypeParameters, - Type[] methodTypeValues) { - this.type = type; - this.methodTypeParameters = methodTypeParameters; - this.methodTypeValues = methodTypeValues; - } - - private Object genPrimitive(Class clazz) { - String dataType = getTypeName(clazz); - switch (dataType) { - case "boolean": - case "java.lang.Boolean": - return rnd.nextInt(2) == 1; - case "byte": - case "java.lang.Byte": - return (byte) (-128 + rnd.nextInt(256)); - case "char": - case "java.lang.Character": - return (char) (rnd.nextInt(127 - 32) + 32); - case "double": - case "java.lang.Double": - return rnd.nextDouble(); - case "float": - case "java.lang.Float": - return rnd.nextFloat(); - case "int": - case "java.lang.Integer": - return rnd.nextInt(); - case "long": - case "java.lang.Long": - return rnd.nextLong(); - case "short": - case "java.lang.Short": - return (short) (-32768 + rnd.nextInt(65536)); - default: - return null; - } - } - - private String genString() { - int len = Util.rndRange(1, 4); - String str = ""; - for (int i = 0; i < len; i++) { - char rndChar = (char) (rnd.nextInt(123 - 97) + 97); - str += rndChar; - } - return str; - } - -// TODO: rewrite so that it can be used with our plugin's API - /*private String genArrayInitializer(Type t) throws IOException, ClassNotFoundException { - boolean noBraces = false; - int elementsCount = Util.rndRange(1, 3); - Type subtype; - if (t instanceof GenericArrayType) { - // e.g. t is "List[][]" or "List[]" - GenericArrayType gat = (GenericArrayType) t; - // e.g. subtype is "List[]" or "List" respectively - subtype = gat.getGenericComponentType(); - } else { - // e.g. t is "String[][]" or "int[]" - Class c = (Class) t; - // e.g. subtype is "String[]" or "int" - subtype = c.getComponentType(); - } - List values = new LinkedList(); - for (int i = 0; i < elementsCount; i++) { - values.add(genValue(subtype)); - } - String result = String.join(", ", values); - if (noBraces) { - return result; - } - return "{ " + result + " }"; - }*/ - - private boolean isListType(String typeName) { - return LIST_TYPES.contains(typeName); - } - - private List emptyList(String listTypeName) { - switch (listTypeName) { - case LINKED_LIST_TYPE: - return new LinkedList<>(); - case LIST_TYPE: - case ARRAY_LIST_TYPE: - return new ArrayList<>(); - default: - throw new RuntimeException("Unknown list type: " + listTypeName); - } - } - - // "Class, Type" - private boolean isType(ParameterizedType pt) { - Type baseType = pt.getRawType(); - if (baseType == null) { - return false; - } - String baseTypeName = getTypeName(baseType); - return baseTypeName.equals("java.lang.reflect.Type") - || baseTypeName.equals("java.lang.Class"); - } - -// TODO: rewrite so that it can be used with our plugin's API - // "Class, Type" -// private String genValueForType(ParameterizedType pt) { -// Type baseType = pt.getRawType(); -// if (baseType == null) { -// return "?"; -// } -// String baseTypeName = getTypeName(baseType); -// String className = "?"; -// if (baseTypeName.equals("java.lang.reflect.Type")) { -// className = "java.lang.Object"; -// } else if (baseTypeName.equals("java.lang.Class")) { -// className = getTypeName(pt.getActualTypeArguments()[0]); -// } -// return "(" + getTypeName(pt) + ") java.lang.Class.forName(\"" + className + "\")"; -// } - -// TODO: rewrite so that it can be used with our plugin's API -// @SneakyThrows -// private String genArrayValue(Type t) { -// if (t instanceof GenericArrayType) { -// int arrayDepth = Util.getArrayDepth(t); -// Type childType = Util.getArrayChildType(t); -// Type rawType = childType; -// if (childType instanceof ParameterizedType) { -// rawType = ((ParameterizedType)childType).getRawType(); -// } -// String castingPart = "(" + getTypeName(t) + ") "; -// String mainPart = "new " + getTypeName(rawType) + Util.repeat("[]", arrayDepth); -// return castingPart + mainPart + genArrayInitializer(t); -// } -// return "new " + getTypeName(t) + genArrayInitializer(t); -// } - - private Constructor getPublicConstructor(Class c) { - Constructor[] constructorArray = c.getConstructors(); - for (int i = 0; i < constructorArray.length; i++) { - int modifiers = constructorArray[i].getModifiers(); - if (Modifier.isPublic(modifiers)) { - return constructorArray[i]; - } - } - return null; - } - - - private Object genClassValue(Class c) { - if (c.isInterface()) { - return null; // interface cannot be instantiated - } - if (Modifier.isAbstract(c.getModifiers())) { - return null; //abstract classes cannot be instantiated - } - List arguments = new LinkedList<>(); - Constructor ctor = getPublicConstructor(c); - if (ctor == null) { - return null; //no public constructor available - } - TypeVariable[] typeParameters = ctor.getTypeParameters(); - Type[] typeValues = TypeChooser.chooseTypeParameterValues(typeParameters); - int parCnt = ctor.getParameterCount(); - for (int i = 0; i < parCnt; i++) { - Type parType = ctor.getGenericParameterTypes()[i]; - ValueGen gen = new ValueGen(parType, typeParameters, typeValues); - Object value = gen.generate(); - arguments.add(value); - } - try { - return ctor.newInstance(arguments.toArray()); - } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException("Could not instantiate class " + c.getName()); - } - } - - private boolean isPrimitive(Class c) { - return c.isPrimitive() || - c.getTypeName().equals("java.lang.Short") || - c.getTypeName().equals("java.lang.Boolean") || - c.getTypeName().equals("java.lang.Byte") || - c.getTypeName().equals("java.lang.Character") || - c.getTypeName().equals("java.lang.Double") || - c.getTypeName().equals("java.lang.Float") || - c.getTypeName().equals("java.lang.Integer") || - c.getTypeName().equals("java.lang.Long") || - c.getTypeName().equals("java.lang.Short"); - } - - private Object genValue(Type t) { - if (t instanceof TypeVariable) { - // e.g. T for: " void foo(List some) {}" - TypeVariable tv = (TypeVariable) t; - int typeIndex = Util.findType(methodTypeParameters, tv); - return genValue(methodTypeValues[typeIndex]); - } else if (t instanceof ParameterizedType) { - // e.g. List, Foo" - ParameterizedType pt = (ParameterizedType) t; - Type rawType = pt.getRawType(); - String rawTypeName = getTypeName(rawType); - if (isListType(rawTypeName)) { - Type childType = pt.getActualTypeArguments()[0]; - List list = emptyList(rawTypeName); - int elemCnt = Util.rndRange(1, 3); - for (int i = 0; i < elemCnt; i++) { - list.add(genValue(childType)); - } - return list; - } - if (isType(pt)) { - // TODO - return null; // genValueForType(pt); - } - Type theRawType = pt.getRawType(); - if (theRawType instanceof Class) { - Class cc = (Class) theRawType; - Constructor pc = getPublicConstructor(cc); - if (pc == null || cc.isInterface() || Modifier.isAbstract(cc.getModifiers())) { - return null; // abstract generic class/interface cannot be instantiated - } - // TODO - return null; // genClassValue(cc, true); - } - return null; // failed to instantiate complex generic class or interface - } else if (t instanceof GenericArrayType) { - // TODO - return null; // genArrayValue(t); - } else if (t instanceof Class) { - Class c = (Class) t; - if (isPrimitive(c)) { - if (getTypeName(c).equals("void")) { - throw new RuntimeException("Cannot generate value for void-type"); - } - return genPrimitive(c); - } - if (getTypeName(c).equals("java.lang.String")) { - return genString(); - } - if (c.isArray()) { - // It's important to use "t" here, because array can be "List[]", - // which is GenericArrayType - // TODO - return null; //genArrayValue(t); - } - // Usual class - return genClassValue(c); - } - return null; // unknown instance type - } - - public Object generate() { - return genValue(type); - } - - private String getTypeName(Type t) { - return Util.getTypeName(t, methodTypeParameters, methodTypeValues); - } -} diff --git a/utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/ObsoleteTestCaseGenerator.kt b/utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/ObsoleteTestCaseGenerator.kt deleted file mode 100644 index cbc24439c4..0000000000 --- a/utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/ObsoleteTestCaseGenerator.kt +++ /dev/null @@ -1,9 +0,0 @@ -package org.utbot.fuzzer - -import org.utbot.framework.plugin.api.MockStrategyApi -import org.utbot.framework.plugin.api.UtMethod -import org.utbot.framework.plugin.api.UtMethodValueTestSet - -interface ObsoleteTestCaseGenerator { - fun generate(method: UtMethod<*>, mockStrategy: MockStrategyApi): UtMethodValueTestSet<*> -} \ No newline at end of file diff --git a/utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/baseline/BaselineFuzzer.kt b/utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/baseline/BaselineFuzzer.kt deleted file mode 100644 index 402941bf2b..0000000000 --- a/utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/baseline/BaselineFuzzer.kt +++ /dev/null @@ -1,22 +0,0 @@ -package org.utbot.fuzzer.baseline - -import org.utbot.framework.plugin.api.MockStrategyApi -import org.utbot.framework.plugin.api.UtConcreteValue -import org.utbot.framework.plugin.api.UtMethod -import org.utbot.framework.plugin.api.UtValueExecution -import org.utbot.framework.plugin.api.UtMethodValueTestSet -import org.utbot.fuzzer.ObsoleteTestCaseGenerator -import org.utbot.fuzzer.baseline.generator.Generator -import kotlin.Result.Companion.failure -import kotlin.Result.Companion.success - -object BaselineFuzzer : ObsoleteTestCaseGenerator { - override fun generate(method: UtMethod<*>, mockStrategy: MockStrategyApi): UtMethodValueTestSet<*> = - Generator.generateTests(method) -} - -fun successfulUtExecution(params: List>, result: Any): UtValueExecution<*> = - UtValueExecution(params, success(result)) - -fun failedUtExecution(params: List>, exception: Throwable): UtValueExecution = - UtValueExecution(params, failure(exception)) diff --git a/utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/primitive/PrimitiveFuzzer.kt b/utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/primitive/PrimitiveFuzzer.kt deleted file mode 100644 index 8e987f7d5c..0000000000 --- a/utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/primitive/PrimitiveFuzzer.kt +++ /dev/null @@ -1,48 +0,0 @@ -package org.utbot.fuzzer.primitive - -import org.utbot.framework.plugin.api.MockStrategyApi -import org.utbot.framework.plugin.api.UtConcreteValue -import org.utbot.framework.plugin.api.UtMethod -import org.utbot.framework.plugin.api.UtValueExecution -import org.utbot.framework.plugin.api.UtMethodValueTestSet -import org.utbot.fuzzer.ObsoleteTestCaseGenerator -import kotlin.Result.Companion.success -import kotlin.reflect.KCallable -import kotlin.reflect.KClass -import kotlin.reflect.KParameter.Kind -import kotlin.reflect.KType - -object PrimitiveFuzzer : ObsoleteTestCaseGenerator { - override fun generate(method: UtMethod<*>, mockStrategy: MockStrategyApi): UtMethodValueTestSet<*> = - UtMethodValueTestSet(method, executions(method.callable)) -} - -private fun executions(method: KCallable) = listOf(execution(method)) - -private fun execution(method: KCallable): UtValueExecution { - val params = method.parameters.filter { it.kind == Kind.VALUE }.map { it.type.utValue() } - val returnValue = success(method.returnType.utValue().value) - return UtValueExecution(params, returnValue) -} - -// TODO: we don't cover String and nullable versions of wrappers for primitive types, for instance java.lang.Integer -private fun KType.utValue(): UtConcreteValue = - when (val kClass = this.classifier as KClass<*>) { - Byte::class -> UtConcreteValue(0.toByte()) - Short::class -> UtConcreteValue(0.toShort()) - Char::class -> UtConcreteValue(0.toChar()) - Int::class -> UtConcreteValue(0) - Long::class -> UtConcreteValue(0L) - Float::class -> UtConcreteValue(0.0f) - Double::class -> UtConcreteValue(0.0) - Boolean::class -> UtConcreteValue(false) - ByteArray::class -> UtConcreteValue(byteArrayOf()) - ShortArray::class -> UtConcreteValue(shortArrayOf()) - CharArray::class -> UtConcreteValue(charArrayOf()) - IntArray::class -> UtConcreteValue(intArrayOf()) - LongArray::class -> UtConcreteValue(longArrayOf()) - FloatArray::class -> UtConcreteValue(floatArrayOf()) - DoubleArray::class -> UtConcreteValue(doubleArrayOf()) - BooleanArray::class -> UtConcreteValue(booleanArrayOf()) - else -> UtConcreteValue(null, kClass.java) - } \ No newline at end of file diff --git a/utbot-fuzzers/src/test/kotlin/org/utbot/framework/plugin/api/FuzzerTestCaseGeneratorTest.kt b/utbot-fuzzers/src/test/kotlin/org/utbot/framework/plugin/api/FuzzerTestCaseGeneratorTest.kt deleted file mode 100644 index 7ed6c46ab1..0000000000 --- a/utbot-fuzzers/src/test/kotlin/org/utbot/framework/plugin/api/FuzzerTestCaseGeneratorTest.kt +++ /dev/null @@ -1,51 +0,0 @@ -package org.utbot.framework.plugin.api - -import org.utbot.fuzzer.primitive.PrimitiveFuzzer -import kotlin.reflect.KClass -import kotlin.reflect.KFunction -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertNotNull -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.Arguments.arguments -import org.junit.jupiter.params.provider.MethodSource - -// TODO: no support for String -internal class FuzzerTestCaseGeneratorTest { - @ParameterizedTest - @MethodSource("manyMethods") - fun testManyMethods(method: KFunction<*>, returnType: KClass<*>, vararg paramTypes: KClass<*>) { - val valueTestSet = generate(method) - valueTestSet.executions.forEach { execution -> - assertEquals(paramTypes.toList(), execution.stateBefore.params.map { it.type }) { "$method" } - assertTrue(execution.returnValue.isSuccess) { "$method" } - val value = execution.returnValue.getOrNull() - assertNotNull(value) { "$method" } - assertEquals(returnType, value!!::class) { "$method" } - } - } - - companion object { - /** - * Arguments for generated types checks. - * - * Each line contains: - * - method - * - parameter types - * - return type - */ - @Suppress("unused") - @JvmStatic - fun manyMethods() = listOf( - args(Object::equals, Any::class, returnType = Boolean::class), - args(Object::hashCode, returnType = Int::class), - args(Math::copySign, Double::class, Double::class, returnType = Double::class) - ) - - private fun args(method: KFunction<*>, vararg paramTypes: KClass<*>, returnType: KClass<*>) = - arguments(method, returnType, paramTypes) - } -} - -private fun generate(method: KFunction<*>) = - PrimitiveFuzzer.generate(UtMethod.from(method), MockStrategyApi.NO_MOCKS) \ No newline at end of file