Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Fixed review issues
  • Loading branch information
Kamenev Yury authored and Damtev committed Jun 21, 2022
commit 37305cc74aa5c5e55b2508ae2988e505efee3de6
Original file line number Diff line number Diff line change
Expand Up @@ -8,42 +8,42 @@

import static org.utbot.engine.overrides.UtOverrideMock.executeConcretely;

@SuppressWarnings({"UnnecessaryInterfaceModifier", "unused"})
@SuppressWarnings("unused")
@UtClassMock(target = java.util.stream.Stream.class, internalUsage = true)
public interface Stream<E> extends BaseStream<E, Stream<E>> {
@SuppressWarnings("unchecked")
public static <E> java.util.stream.Stream<E> of(E element) {
static <E> java.util.stream.Stream<E> of(E element) {
Object[] data = new Object[1];
data[0] = element;

return new UtStream<>((E[]) data, 1);
}

@SuppressWarnings("unchecked")
public static <E> java.util.stream.Stream<E> of(E... elements) {
static <E> java.util.stream.Stream<E> of(E... elements) {
int size = elements.length;

return new UtStream<>(elements, size);
}

@SuppressWarnings("unchecked")
public static <E> java.util.stream.Stream<E> empty() {
static <E> java.util.stream.Stream<E> empty() {
return new UtStream<>((E[]) new Object[]{}, 0);
}

public static <E> java.util.stream.Stream<E> generate(Supplier<E> s) {
static <E> java.util.stream.Stream<E> generate(Supplier<E> s) {
// as "generate" method produces an infinite stream, we cannot analyze it symbolically
executeConcretely();
return null;
}

public static <E> java.util.stream.Stream<E> iterate(final E seed, final UnaryOperator<E> f) {
static <E> java.util.stream.Stream<E> iterate(final E seed, final UnaryOperator<E> f) {
// as "iterate" method produces an infinite stream, we cannot analyze it symbolically
executeConcretely();
return null;
}

public static <E> java.util.stream.Stream<E> concat(
static <E> java.util.stream.Stream<E> concat(
java.util.stream.Stream<? extends E> a,
java.util.stream.Stream<? extends E> b
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@
import org.utbot.engine.overrides.collections.RangeModifiableUnlimitedArray;
import org.utbot.engine.overrides.collections.UtGenericStorage;

import java.util.*;
import java.util.Comparator;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
Expand All @@ -24,6 +29,7 @@
import org.jetbrains.annotations.NotNull;

import static org.utbot.api.mock.UtMock.assume;
import static org.utbot.api.mock.UtMock.assumeOrExecuteConcretely;
import static org.utbot.engine.ResolverKt.HARD_MAX_ARRAY_SIZE;
import static org.utbot.engine.overrides.UtOverrideMock.alreadyVisited;
import static org.utbot.engine.overrides.UtOverrideMock.executeConcretely;
Expand Down Expand Up @@ -313,7 +319,8 @@ public Stream<E> limit(long maxSize) {
throw new IllegalArgumentException();
}

// TODO how to process long value correctly - assumeOrExecuteConcretely?
assumeOrExecuteConcretely(maxSize <= Integer.MAX_VALUE);

int newSize = (int) maxSize;
int curSize = elementData.end;

Expand Down Expand Up @@ -346,7 +353,7 @@ public Stream<E> skip(long n) {
return new UtStream<>();
}

// TODO how to process long value correctly - assumeOrExecuteConcretely?
// n is 1...Integer.MAX_VALUE here
int newSize = (int) (curSize - n);

return new UtStream<>((E[]) elementData.toArray((int) n, newSize), newSize);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@ import soot.Scene
import soot.SootClass
import soot.SootField
import soot.SootMethod
import sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
import sun.reflect.generics.reflectiveObjects.TypeVariableImpl
import sun.reflect.generics.reflectiveObjects.WildcardTypeImpl

val rangeModifiableArrayId: ClassId = RangeModifiableUnlimitedArray::class.id

Expand Down Expand Up @@ -250,8 +246,7 @@ class RangeModifiableUnlimitedArrayWrapper : WrapperInterface {

// try to retrieve type storage for the single type parameter
val typeStorage =
resolver.typeRegistry.getObjectParameterTypeStorages(wrapper.addr)?.singleOrNull() ?: TypeStorage(OBJECT_TYPE)

resolver.typeRegistry.getTypeStoragesForObjectTypeParameters(wrapper.addr)?.singleOrNull() ?: TypeRegistry.objectTypeStorage

(0 until sizeValue).associateWithTo(resultModel.stores) { i ->
val addr = UtAddrExpression(arrayExpression.select(mkInt(i + firstValue)))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,15 @@
package org.utbot.engine

import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.persistentSetOf
import org.utbot.common.unreachableBranch
import org.utbot.engine.CommonStreamWrapper.Companion.isClosedStreamFieldId
import org.utbot.engine.CommonStreamWrapper.Companion.isParallelStreamFieldId
import org.utbot.engine.CommonStreamWrapper.Companion.utStreamType
import org.utbot.engine.overrides.collections.AssociativeArray
import org.utbot.engine.overrides.collections.RangeModifiableUnlimitedArray
import org.utbot.engine.overrides.collections.UtArrayList
import org.utbot.engine.overrides.collections.UtGenericAssociative
import org.utbot.engine.overrides.collections.UtGenericStorage
import org.utbot.engine.overrides.collections.UtHashMap
import org.utbot.engine.overrides.collections.UtHashSet
import org.utbot.engine.overrides.collections.UtLinkedList
import org.utbot.engine.overrides.stream.UtStream
import org.utbot.engine.pc.UtAddrExpression
import org.utbot.engine.pc.UtExpression
import org.utbot.engine.pc.mkEq
import org.utbot.engine.pc.mkFalse
import org.utbot.engine.pc.select
import org.utbot.engine.symbolic.asHardConstraint
import org.utbot.engine.z3.intValue
Expand Down Expand Up @@ -58,8 +49,7 @@ abstract class BaseOverriddenWrapper(protected val overriddenClassName: String)
*
* @see invoke
*/
protected abstract fun overrideInvoke(
engine: UtBotSymbolicEngine,
protected abstract fun UtBotSymbolicEngine.overrideInvoke(
wrapper: ObjectValue,
method: SootMethod,
parameters: List<SymbolicValue>
Expand All @@ -83,7 +73,7 @@ abstract class BaseOverriddenWrapper(protected val overriddenClassName: String)
method: SootMethod,
parameters: List<SymbolicValue>
): List<InvokeResult> {
val methodResults = overrideInvoke(this, wrapper, method, parameters)
val methodResults = overrideInvoke(wrapper, method, parameters)
if (methodResults != null) {
return methodResults
}
Expand Down Expand Up @@ -159,28 +149,25 @@ abstract class BaseContainerWrapper(containerClassName: String) : BaseOverridden
}

abstract class BaseGenericStorageBasedContainerWrapper(containerClassName: String) : BaseContainerWrapper(containerClassName) {
override fun overrideInvoke(
engine: UtBotSymbolicEngine,
override fun UtBotSymbolicEngine.overrideInvoke(
wrapper: ObjectValue,
method: SootMethod,
parameters: List<SymbolicValue>
): List<InvokeResult>? =
with(engine) {
when (method.signature) {
UT_GENERIC_STORAGE_SET_EQUAL_GENERIC_TYPE_SIGNATURE -> {
val equalGenericTypeConstraint = typeRegistry
.eqGenericSingleTypeParameterConstraint(parameters[0].addr, wrapper.addr)
.asHardConstraint()

val methodResult = MethodResult(
SymbolicSuccess(voidValue),
equalGenericTypeConstraint
)
when (method.signature) {
UT_GENERIC_STORAGE_SET_EQUAL_GENERIC_TYPE_SIGNATURE -> {
val equalGenericTypeConstraint = typeRegistry
.eqGenericSingleTypeParameterConstraint(parameters[0].addr, wrapper.addr)
.asHardConstraint()

val methodResult = MethodResult(
SymbolicSuccess(voidValue),
equalGenericTypeConstraint
)

listOf(methodResult)
}
else -> null
listOf(methodResult)
}
else -> null
}

override fun Resolver.resolveValueModels(wrapper: ObjectValue): List<List<UtModel>> {
Expand Down Expand Up @@ -283,34 +270,32 @@ class SetWrapper : BaseGenericStorageBasedContainerWrapper(UtHashSet::class.qual
* entries, then real behavior of generated test can differ from expected and undefined.
*/
class MapWrapper : BaseContainerWrapper(UtHashMap::class.qualifiedName!!) {
override fun overrideInvoke(
engine: UtBotSymbolicEngine,
override fun UtBotSymbolicEngine.overrideInvoke(
wrapper: ObjectValue,
method: SootMethod,
parameters: List<SymbolicValue>
): List<InvokeResult>? =
with(engine) {
when (method.signature) {
UT_GENERIC_STORAGE_SET_EQUAL_GENERIC_TYPE_SIGNATURE -> listOf(
MethodResult(
SymbolicSuccess(voidValue),
typeRegistry.eqGenericSingleTypeParameterConstraint(parameters[0].addr, wrapper.addr)
.asHardConstraint()
)
when (method.signature) {
UT_GENERIC_STORAGE_SET_EQUAL_GENERIC_TYPE_SIGNATURE -> listOf(
MethodResult(
SymbolicSuccess(voidValue),
typeRegistry.eqGenericSingleTypeParameterConstraint(parameters[0].addr, wrapper.addr)
.asHardConstraint()
)
UT_GENERIC_ASSOCIATIVE_SET_EQUAL_GENERIC_TYPE_SIGNATURE -> listOf(
MethodResult(
SymbolicSuccess(voidValue),
typeRegistry.eqGenericTypeParametersConstraint(
parameters[0].addr,
wrapper.addr,
parameterSize = 2
).asHardConstraint()
)
)
UT_GENERIC_ASSOCIATIVE_SET_EQUAL_GENERIC_TYPE_SIGNATURE -> listOf(
MethodResult(
SymbolicSuccess(voidValue),
typeRegistry.eqGenericTypeParametersConstraint(
parameters[0].addr,
wrapper.addr,
parameterSize = 2
).asHardConstraint()
)
else -> null
}
)
else -> null
}

override fun Resolver.resolveValueModels(wrapper: ObjectValue): List<List<UtModel>> {
val fieldModels = collectFieldModels(wrapper.addr, overriddenClass.type)
val keyModels = fieldModels[overriddenClass.getFieldByName("keys").fieldId] as? UtArrayModel
Expand Down Expand Up @@ -402,12 +387,6 @@ private val UT_GENERIC_ASSOCIATIVE_CLASS
private val UT_GENERIC_ASSOCIATIVE_SET_EQUAL_GENERIC_TYPE_SIGNATURE =
UT_GENERIC_ASSOCIATIVE_CLASS.getMethodByName(UtGenericAssociative<*, *>::setEqualGenericType.name).signature

private val COLLECTION_CLASS: SootClass
get() = Scene.v().getSootClass(java.util.Collection::class.java.canonicalName)

private val UT_COLLECTION_STREAM_SIGNATURE: String =
COLLECTION_CLASS.getMethodByName("stream").signature

val ARRAY_LIST_TYPE: RefType
get() = Scene.v().getSootClass(java.util.ArrayList::class.java.canonicalName).type
val LINKED_LIST_TYPE: RefType
Expand Down
26 changes: 13 additions & 13 deletions utbot-framework/src/main/kotlin/org/utbot/engine/Memory.kt
Original file line number Diff line number Diff line change
Expand Up @@ -722,7 +722,7 @@ class TypeRegistry {
secondAddr: UtAddrExpression,
parameterSize: Int
) : UtEqGenericTypeParametersExpression {
val injections = (0 until parameterSize).associateWith { it }.toList().toTypedArray()
val injections = Array(parameterSize) { it to it }

return eqGenericTypeParametersConstraint(firstAddr, secondAddr, *injections)
}
Expand All @@ -745,7 +745,7 @@ class TypeRegistry {
/**
* Retrieves parameter type storages of an object with the given [addr] if present, or null otherwise.
*/
fun getObjectParameterTypeStorages(addr: UtAddrExpression): List<TypeStorage>? = genericTypeStorageByAddr[addr]
fun getTypeStoragesForObjectTypeParameters(addr: UtAddrExpression): List<TypeStorage>? = genericTypeStorageByAddr[addr]

/**
* Set types storages for [firstAddr]'s type parameters equal to type storages for [secondAddr]'s type parameters
Expand All @@ -756,22 +756,22 @@ class TypeRegistry {
secondAddr: UtAddrExpression,
indexInjection: Array<out Pair<Int, Int>>
) {
genericTypeStorageByAddr[secondAddr]?.let { existingGenericTypes ->
val currentGenericTypes = mutableMapOf<Int, TypeStorage>()
val existingGenericTypes = genericTypeStorageByAddr[secondAddr] ?: return

indexInjection.forEach { (from, to) ->
require(from >= 0 && from < existingGenericTypes.size) {
"Type injection is out of bounds: should be in [0; ${existingGenericTypes.size}) but is $from"
}
val currentGenericTypes = mutableMapOf<Int, TypeStorage>()

currentGenericTypes[to] = existingGenericTypes[from]
indexInjection.forEach { (from, to) ->
require(from >= 0 && from < existingGenericTypes.size) {
"Type injection is out of bounds: should be in [0; ${existingGenericTypes.size}) but is $from"
}

genericTypeStorageByAddr[firstAddr] = currentGenericTypes
.entries
.sortedBy { it.key }
.mapTo(mutableListOf()) { it.value }
currentGenericTypes[to] = existingGenericTypes[from]
}

genericTypeStorageByAddr[firstAddr] = currentGenericTypes
.entries
.sortedBy { it.key }
.mapTo(mutableListOf()) { it.value }
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ class OptionalWrapper(private val utOptionalClass: UtOptionalClass) : BaseOverri
private val AS_OPTIONAL_METHOD_SIGNATURE =
overriddenClass.getMethodByName(UtOptional<*>::asOptional.name).signature

override fun overrideInvoke(
engine: UtBotSymbolicEngine,
override fun UtBotSymbolicEngine.overrideInvoke(
wrapper: ObjectValue,
method: SootMethod,
parameters: List<SymbolicValue>
Expand All @@ -72,7 +71,7 @@ class OptionalWrapper(private val utOptionalClass: UtOptionalClass) : BaseOverri
return listOf(
MethodResult(
parameters.first(),
engine.typeRegistry.typeConstraintToGenericTypeParameter(
typeRegistry.typeConstraintToGenericTypeParameter(
parameters.first().addr,
wrapper.addr,
i = 0
Expand All @@ -82,6 +81,7 @@ class OptionalWrapper(private val utOptionalClass: UtOptionalClass) : BaseOverri
}

}

return null
}

Expand Down
18 changes: 4 additions & 14 deletions utbot-framework/src/main/kotlin/org/utbot/engine/StreamWrappers.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,8 @@ import org.utbot.framework.plugin.api.util.methodId
import org.utbot.framework.plugin.api.util.objectArrayClassId
import org.utbot.framework.plugin.api.util.objectClassId
import org.utbot.framework.util.nextModelName
import soot.BooleanType
import soot.RefType
import soot.Scene
import soot.SootField
import soot.Type

/**
* Auxiliary enum class for specifying an implementation for [CommonStreamWrapper], that it will use.
Expand Down Expand Up @@ -62,14 +59,14 @@ abstract class StreamWrapper(
override fun value(resolver: Resolver, wrapper: ObjectValue): UtAssembleModel = resolver.run {
val addr = holder.concreteAddr(wrapper.addr)
val modelName = nextModelName(baseModelName)
val parametersArrayModel = resolveElementAsArrayModel(wrapper)
val parametersArrayModel = resolveElementsAsArrayModel(wrapper)

val instantiationChain = mutableListOf<UtStatementModel>()
val modificationsChain = emptyList<UtStatementModel>()

UtAssembleModel(addr, utStreamClass.overriddenStreamClassId, modelName, instantiationChain, modificationsChain)
.apply {
val (builder, params) = if (parametersArrayModel.length == 0) {
val (builder, params) = if (parametersArrayModel == null || parametersArrayModel.length == 0) {
streamEmptyMethodId to emptyList()
} else {
streamOfMethodId to listOf(parametersArrayModel)
Expand All @@ -89,10 +86,10 @@ abstract class StreamWrapper(
override val modificationMethodId: MethodId
get() = error("No modification method for Stream")

private fun Resolver.resolveElementAsArrayModel(wrapper: ObjectValue): UtArrayModel {
private fun Resolver.resolveElementsAsArrayModel(wrapper: ObjectValue): UtArrayModel? {
val elementDataFieldId = FieldId(overriddenClass.type.classId, "elementData")

return collectFieldModels(wrapper.addr, overriddenClass.type)[elementDataFieldId] as UtArrayModel
return collectFieldModels(wrapper.addr, overriddenClass.type)[elementDataFieldId] as? UtArrayModel
}

private val streamOfMethodId: MethodId = methodId(
Expand All @@ -116,12 +113,5 @@ class CommonStreamWrapper : StreamWrapper(UtStreamClass.UT_STREAM) {
companion object {
internal val utStreamType: RefType
get() = Scene.v().getSootClass(UtStream::class.java.canonicalName).type
private val booleanType: Type
get() = BooleanType.v()

internal val isParallelStreamFieldId: SootField
get() = SootField("isParallel", booleanType)
internal val isClosedStreamFieldId: SootField
get() = SootField("isClosed", booleanType)
}
}
Loading