diff --git a/utbot-framework-test/src/test/kotlin/org/utbot/examples/casts/InstanceOfExampleTest.kt b/utbot-framework-test/src/test/kotlin/org/utbot/examples/casts/InstanceOfExampleTest.kt index 2b4561ecf3..ad6a8794c0 100644 --- a/utbot-framework-test/src/test/kotlin/org/utbot/examples/casts/InstanceOfExampleTest.kt +++ b/utbot-framework-test/src/test/kotlin/org/utbot/examples/casts/InstanceOfExampleTest.kt @@ -1,14 +1,14 @@ package org.utbot.examples.casts -import org.utbot.tests.infrastructure.UtValueTestCaseChecker -import org.utbot.tests.infrastructure.DoNotCalculate -import org.utbot.tests.infrastructure.ignoreExecutionsNumber -import org.utbot.framework.plugin.api.CodegenLanguage import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test +import org.utbot.framework.plugin.api.CodegenLanguage import org.utbot.testcheckers.eq import org.utbot.testcheckers.ge import org.utbot.tests.infrastructure.CodeGeneration +import org.utbot.tests.infrastructure.DoNotCalculate +import org.utbot.tests.infrastructure.UtValueTestCaseChecker +import org.utbot.tests.infrastructure.ignoreExecutionsNumber // TODO failed Kotlin compilation SAT-1332 internal class InstanceOfExampleTest : UtValueTestCaseChecker( @@ -404,6 +404,65 @@ internal class InstanceOfExampleTest : UtValueTestCaseChecker( ) } + @Test + fun testStringInstanceOf() { + check( + InstanceOfExample::charSequenceInstanceOf, + eq(2), + { _, r -> r == null }, + { _, r -> r!!::class == String::class } + ) + } + + @Test + fun testListInstanceOf() { + check( + InstanceOfExample::listInstanceOf, + eq(2), + { _, r -> r == null }, + { _, r -> r!!::class == java.util.ArrayList::class } + ) + } + + @Test + fun testDequeInstanceOf() { + check( + InstanceOfExample::dequeInstanceOf, + eq(2), + { _, r -> r == null }, + { _, r -> r!!::class == java.util.LinkedList::class } + ) + } + + @Test + fun testAbstractSeqListInstanceOf() { + check( + InstanceOfExample::abstractSequentialListInstanceOf, + eq(2), + { _, r -> r == null }, + { _, r -> r!!::class == java.util.LinkedList::class } + ) + } + + @Test + fun testSetInstanceOf() { + check( + InstanceOfExample::setInstanceOf, + eq(2), + { _, r -> r == null }, + { _, r -> r!!::class == java.util.LinkedHashSet::class } + ) + } + + @Test + fun testMapInstanceOf() { + check( + InstanceOfExample::mapInstanceOf, + eq(2), + { _, r -> r == null }, + { _, r -> r!!::class == java.util.LinkedHashMap::class } + ) + } private inline fun Any?.isInstanceOfArray() = (this as? Array<*>)?.run { T::class.java.isAssignableFrom(this::class.java.componentType) } == true diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/ArrayObjectWrappers.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/ArrayObjectWrappers.kt index 6671f25ac2..ee39b4804d 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/ArrayObjectWrappers.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/ArrayObjectWrappers.kt @@ -25,7 +25,6 @@ import org.utbot.framework.plugin.api.UtModel import org.utbot.framework.plugin.api.UtNullModel import org.utbot.framework.plugin.api.UtPrimitiveModel import org.utbot.framework.plugin.api.getIdOrThrow -import org.utbot.framework.plugin.api.idOrNull import org.utbot.framework.plugin.api.util.id import org.utbot.framework.plugin.api.util.objectArrayClassId import org.utbot.framework.plugin.api.util.objectClassId @@ -34,6 +33,7 @@ import soot.Scene import soot.SootClass import soot.SootField import soot.SootMethod +import soot.Type val rangeModifiableArrayId: ClassId = RangeModifiableUnlimitedArray::class.id @@ -264,6 +264,13 @@ class RangeModifiableUnlimitedArrayWrapper : WrapperInterface { return resultModel } + override fun getPossibleConcreteTypes(type: Type): Set { + val possibleObjectTypes = Scene.v().classes.map { it.type } + return possibleObjectTypes.mapTo(mutableSetOf()) { + it.arrayType + } + } + companion object { internal val rangeModifiableArrayClass: SootClass get() = Scene.v().getSootClass(rangeModifiableArrayId.name) @@ -415,6 +422,9 @@ class AssociativeArrayWrapper : WrapperInterface { return model } + override fun getPossibleConcreteTypes(type: Type): Set = + setOf(associativeArrayClass.type) + private fun Traverser.getStorageArrayField(addr: UtAddrExpression) = getArrayField(addr, associativeArrayClass, storageField) diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/CollectionWrappers.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/CollectionWrappers.kt index 40add8087f..e149bcd96f 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/CollectionWrappers.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/CollectionWrappers.kt @@ -26,13 +26,13 @@ import org.utbot.framework.plugin.api.UtNullModel import org.utbot.framework.plugin.api.UtStatementModel import org.utbot.framework.plugin.api.classId import org.utbot.framework.plugin.api.getIdOrThrow -import org.utbot.framework.util.graph import org.utbot.framework.plugin.api.id import org.utbot.framework.plugin.api.util.booleanClassId import org.utbot.framework.plugin.api.util.constructorId import org.utbot.framework.plugin.api.util.id import org.utbot.framework.plugin.api.util.methodId import org.utbot.framework.plugin.api.util.objectClassId +import org.utbot.framework.util.graph import org.utbot.framework.util.nextModelName import soot.IntType import soot.RefType @@ -40,6 +40,7 @@ import soot.Scene import soot.SootClass import soot.SootField import soot.SootMethod +import soot.Type abstract class BaseOverriddenWrapper(protected val overriddenClassName: String) : WrapperInterface { val overriddenClass: SootClass = Scene.v().getSootClass(overriddenClassName) @@ -130,6 +131,9 @@ abstract class BaseContainerWrapper(containerClassName: String) : BaseOverridden } } + override fun getPossibleConcreteTypes(type: Type): Set = + setOf(chooseClassIdWithConstructor(type.classId).sootType) + /** * Method returns list of parameter models that will be passed to [modificationMethodId] * while construction modification chain in [UtAssembleModel] for the specified [wrapper] @@ -398,21 +402,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 -val ARRAY_LIST_TYPE: RefType - get() = Scene.v().getSootClass(java.util.ArrayList::class.java.canonicalName).type -val LINKED_LIST_TYPE: RefType - get() = Scene.v().getSootClass(java.util.LinkedList::class.java.canonicalName).type - -val LINKED_HASH_SET_TYPE: RefType - get() = Scene.v().getSootClass(java.util.LinkedHashSet::class.java.canonicalName).type -val HASH_SET_TYPE: RefType - get() = Scene.v().getSootClass(java.util.HashSet::class.java.canonicalName).type - -val LINKED_HASH_MAP_TYPE: RefType - get() = Scene.v().getSootClass(java.util.LinkedHashMap::class.java.canonicalName).type -val HASH_MAP_TYPE: RefType - get() = Scene.v().getSootClass(java.util.HashMap::class.java.canonicalName).type - val STREAM_TYPE: RefType get() = Scene.v().getSootClass(java.util.stream.Stream::class.java.canonicalName).type diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/Extensions.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/Extensions.kt index 1de5fa185a..d3f4a92bb1 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/Extensions.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/Extensions.kt @@ -1,6 +1,14 @@ package org.utbot.engine import com.google.common.collect.BiMap +import java.lang.reflect.ParameterizedType +import java.util.ArrayDeque +import java.util.Deque +import java.util.LinkedList +import java.util.Queue +import java.util.concurrent.ConcurrentHashMap +import kotlinx.collections.immutable.PersistentMap +import kotlinx.collections.immutable.persistentHashMapOf import org.utbot.api.mock.UtMock import org.utbot.engine.pc.UtAddrExpression import org.utbot.engine.pc.UtArraySort @@ -33,8 +41,11 @@ import org.utbot.engine.pc.mkString import org.utbot.engine.pc.toSort import org.utbot.framework.UtSettings.checkNpeInNestedMethods import org.utbot.framework.UtSettings.checkNpeInNestedNotPrivateMethods +import org.utbot.framework.plugin.api.ClassId import org.utbot.framework.plugin.api.FieldId import org.utbot.framework.plugin.api.id +import org.utbot.framework.plugin.api.util.isArray +import org.utbot.framework.plugin.api.util.isPrimitive import soot.ArrayType import soot.PrimType import soot.RefLikeType @@ -60,14 +71,6 @@ import soot.jimple.internal.JStaticInvokeExpr import soot.jimple.internal.JVirtualInvokeExpr import soot.jimple.internal.JimpleLocal import soot.tagkit.ArtificialEntityTag -import java.lang.reflect.ParameterizedType -import java.util.ArrayDeque -import java.util.Deque -import java.util.LinkedList -import java.util.Queue -import java.util.concurrent.ConcurrentHashMap -import kotlinx.collections.immutable.PersistentMap -import kotlinx.collections.immutable.persistentHashMapOf val JIdentityStmt.lines: String get() = tags.joinToString { "$it" } @@ -424,3 +427,10 @@ val SootMethod.isUtMockAssumeOrExecuteConcretely */ val SootMethod.isPreconditionCheckMethod get() = declaringClass.isOverridden && name == "preconditionCheck" + +val ClassId.sootType: Type + get() = when { + isPrimitive -> Scene.v().getType(name) + isArray -> elementClassId!!.sootType.arrayType + else -> Scene.v().getSootClass(canonicalName).type + } diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/Mocks.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/Mocks.kt index 83690318cf..33be279fc4 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/Mocks.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/Mocks.kt @@ -1,11 +1,15 @@ package org.utbot.engine +import java.util.concurrent.atomic.AtomicInteger +import kotlin.reflect.KFunction2 +import kotlin.reflect.KFunction5 +import kotlinx.collections.immutable.persistentListOf import org.utbot.api.mock.UtMock -import org.utbot.common.packageName import org.utbot.engine.overrides.UtArrayMock import org.utbot.engine.overrides.UtLogicMock import org.utbot.engine.overrides.UtOverrideMock import org.utbot.engine.pc.UtAddrExpression +import org.utbot.engine.util.mockListeners.MockListenerController import org.utbot.framework.plugin.api.ClassId import org.utbot.framework.plugin.api.FieldId import org.utbot.framework.plugin.api.MethodId @@ -14,17 +18,13 @@ import org.utbot.framework.plugin.api.id import org.utbot.framework.plugin.api.util.id import org.utbot.framework.plugin.api.util.isRefType import org.utbot.framework.util.executableId -import java.util.concurrent.atomic.AtomicInteger -import kotlin.reflect.KFunction2 -import kotlin.reflect.KFunction5 -import kotlinx.collections.immutable.persistentListOf -import org.utbot.engine.util.mockListeners.MockListenerController import org.utbot.framework.util.isInaccessibleViaReflection import soot.BooleanType import soot.RefType import soot.Scene import soot.SootClass import soot.SootMethod +import soot.Type /** * Generates mock with address provided. @@ -307,6 +307,9 @@ class UtMockWrapper( override fun value(resolver: Resolver, wrapper: ObjectValue): UtModel = TODO("value on mock called: $this") + override fun getPossibleConcreteTypes(type: Type): Set = + setOf(this.type) + override fun toString() = "UtMock(type=$type, target=$mockInfo)" } diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/ObjectWrappers.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/ObjectWrappers.kt index 87e7470496..b5348201f0 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/ObjectWrappers.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/ObjectWrappers.kt @@ -1,5 +1,11 @@ package org.utbot.engine +import java.util.Optional +import java.util.OptionalDouble +import java.util.OptionalInt +import java.util.OptionalLong +import java.util.concurrent.CopyOnWriteArrayList +import kotlin.reflect.KClass import org.utbot.common.WorkaroundReason.MAKE_SYMBOLIC import org.utbot.common.workaround import org.utbot.engine.UtListClass.UT_ARRAY_LIST @@ -34,12 +40,7 @@ import soot.RefType import soot.Scene import soot.SootClass import soot.SootMethod -import java.util.Optional -import java.util.OptionalDouble -import java.util.OptionalInt -import java.util.OptionalLong -import java.util.concurrent.CopyOnWriteArrayList -import kotlin.reflect.KClass +import soot.Type typealias TypeToBeWrapped = RefType typealias WrapperType = RefType @@ -151,15 +152,15 @@ private val wrappers = mapOf( }, // list wrappers - wrap(java.util.List::class) { _, addr -> objectValue(ARRAY_LIST_TYPE, addr, ListWrapper(UT_ARRAY_LIST)) }, - wrap(java.util.AbstractList::class) { _, addr -> objectValue(ARRAY_LIST_TYPE, addr, ListWrapper(UT_ARRAY_LIST)) }, - wrap(java.util.ArrayList::class) { _, addr -> objectValue(ARRAY_LIST_TYPE, addr, ListWrapper(UT_ARRAY_LIST)) }, + wrap(java.util.List::class) { type, addr -> objectValue(type, addr, ListWrapper(UT_ARRAY_LIST)) }, + wrap(java.util.AbstractList::class) { type, addr -> objectValue(type, addr, ListWrapper(UT_ARRAY_LIST)) }, + wrap(java.util.ArrayList::class) { type, addr -> objectValue(type, addr, ListWrapper(UT_ARRAY_LIST)) }, wrap(CopyOnWriteArrayList::class) { type, addr -> objectValue(type, addr, ListWrapper(UT_ARRAY_LIST)) }, - wrap(java.util.LinkedList::class) { _, addr -> objectValue(LINKED_LIST_TYPE, addr, ListWrapper(UT_LINKED_LIST)) }, - wrap(java.util.AbstractSequentialList::class) { _, addr -> objectValue(LINKED_LIST_TYPE, addr, ListWrapper(UT_LINKED_LIST)) }, + wrap(java.util.LinkedList::class) { type, addr -> objectValue(type, addr, ListWrapper(UT_LINKED_LIST)) }, + wrap(java.util.AbstractSequentialList::class) { type, addr -> objectValue(type, addr, ListWrapper(UT_LINKED_LIST)) }, // queue, deque wrappers wrap(java.util.ArrayDeque::class) { type, addr -> @@ -179,17 +180,17 @@ private val wrappers = mapOf( }, // set wrappers - wrap(java.util.Set::class) { _, addr -> objectValue(LINKED_HASH_SET_TYPE, addr, SetWrapper()) }, - wrap(java.util.AbstractSet::class) { _, addr -> objectValue(LINKED_HASH_SET_TYPE, addr, SetWrapper()) }, - wrap(java.util.HashSet::class) { _, addr -> objectValue(HASH_SET_TYPE, addr, SetWrapper()) }, - wrap(java.util.LinkedHashSet::class) { _, addr -> objectValue(LINKED_HASH_SET_TYPE, addr, SetWrapper()) }, + wrap(java.util.Set::class) { type, addr -> objectValue(type, addr, SetWrapper()) }, + wrap(java.util.AbstractSet::class) { type, addr -> objectValue(type, addr, SetWrapper()) }, + wrap(java.util.HashSet::class) { type, addr -> objectValue(type, addr, SetWrapper()) }, + wrap(java.util.LinkedHashSet::class) { type, addr -> objectValue(type, addr, SetWrapper()) }, // map wrappers - wrap(java.util.Map::class) { _, addr -> objectValue(LINKED_HASH_MAP_TYPE, addr, MapWrapper()) }, - wrap(java.util.AbstractMap::class) { _, addr -> objectValue(LINKED_HASH_MAP_TYPE, addr, MapWrapper()) }, - wrap(java.util.LinkedHashMap::class) { _, addr -> objectValue(LINKED_HASH_MAP_TYPE, addr, MapWrapper()) }, - wrap(java.util.HashMap::class) { _, addr -> objectValue(HASH_MAP_TYPE, addr, MapWrapper()) }, - wrap(java.util.concurrent.ConcurrentHashMap::class) { _, addr -> objectValue(HASH_MAP_TYPE, addr, MapWrapper()) }, + wrap(java.util.Map::class) { type, addr -> objectValue(type, addr, MapWrapper()) }, + wrap(java.util.AbstractMap::class) { type, addr -> objectValue(type, addr, MapWrapper()) }, + wrap(java.util.LinkedHashMap::class) { type, addr -> objectValue(type, addr, MapWrapper()) }, + wrap(java.util.HashMap::class) { type, addr -> objectValue(type, addr, MapWrapper()) }, + wrap(java.util.concurrent.ConcurrentHashMap::class) { type, addr -> objectValue(type, addr, MapWrapper()) }, // stream wrappers wrap(java.util.stream.BaseStream::class) { _, addr -> objectValue(STREAM_TYPE, addr, CommonStreamWrapper()) }, @@ -222,6 +223,14 @@ interface WrapperInterface { ): List fun value(resolver: Resolver, wrapper: ObjectValue): UtModel + + /** + * Returns list of possible concrete types that can be produced by [value] method. + * Used for wrapper initialization. + * + * @param type target type to wrap + */ + fun getPossibleConcreteTypes(type: Type): Set } // TODO: perhaps we have to have wrapper around concrete value here @@ -252,4 +261,7 @@ data class ThrowableWrapper(val throwable: Throwable) : WrapperInterface { return UtAssembleModel(addr, classId, modelName, instantiationCall) } + + override fun getPossibleConcreteTypes(type: Type): Set = + setOf(throwable.javaClass.id.sootType) } \ No newline at end of file diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/OptionalWrapper.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/OptionalWrapper.kt index 7fc3930ba5..9d2a3b72d8 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/OptionalWrapper.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/OptionalWrapper.kt @@ -16,7 +16,6 @@ import org.utbot.framework.plugin.api.UtAssembleModel import org.utbot.framework.plugin.api.UtExecutableCallModel import org.utbot.framework.plugin.api.UtNullModel import org.utbot.framework.plugin.api.UtPrimitiveModel -import org.utbot.framework.plugin.api.UtStatementModel import org.utbot.framework.plugin.api.classId import org.utbot.framework.plugin.api.id import org.utbot.framework.plugin.api.util.defaultValueModel @@ -27,6 +26,7 @@ import org.utbot.framework.plugin.api.util.objectClassId import org.utbot.framework.util.nextModelName import soot.Scene import soot.SootMethod +import soot.Type /** * Auxiliary enum class for specifying an implementation for [OptionalWrapper], that it will use. @@ -94,6 +94,9 @@ class OptionalWrapper(private val utOptionalClass: UtOptionalClass) : BaseOverri return UtAssembleModel(addr, classId, modelName, instantiationCall) } + override fun getPossibleConcreteTypes(type: Type): Set = + setOf(type) + private fun Resolver.instantiationFactoryCallModel(classId: ClassId, wrapper: ObjectValue) : UtExecutableCallModel { val valueField = FieldId(overriddenClass.id, "value") val isPresentFieldId = FieldId(overriddenClass.id, "isPresent") diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/SecurityManagerWrapper.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/SecurityManagerWrapper.kt index 33f8511dfa..04b76a0726 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/SecurityManagerWrapper.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/SecurityManagerWrapper.kt @@ -10,6 +10,7 @@ import org.utbot.framework.util.nextModelName import soot.Scene import soot.SootClass import soot.SootMethod +import soot.Type class SecurityManagerWrapper : BaseOverriddenWrapper(utSecurityManagerClass.name) { private val baseModelName: String = "securityManager" @@ -37,6 +38,9 @@ class SecurityManagerWrapper : BaseOverriddenWrapper(utSecurityManagerClass.name return UtAssembleModel(addr, classId, modelName, instantiationCall) } + override fun getPossibleConcreteTypes(type: Type): Set = + setOf(type) + companion object { val utSecurityManagerClass: SootClass get() = Scene.v().getSootClass(UtSecurityManager::class.qualifiedName) diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/StreamWrappers.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/StreamWrappers.kt index 992e3ac694..fa3abbdb45 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/StreamWrappers.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/StreamWrappers.kt @@ -16,6 +16,7 @@ import org.utbot.framework.plugin.api.util.objectClassId import org.utbot.framework.util.nextModelName import soot.RefType import soot.Scene +import soot.Type /** * Auxiliary enum class for specifying an implementation for [CommonStreamWrapper], that it will use. @@ -76,6 +77,9 @@ abstract class StreamWrapper( UtAssembleModel(addr, utStreamClass.overriddenStreamClassId, modelName, instantiationCall) } + override fun getPossibleConcreteTypes(type: Type): Set = + setOf(utStreamClass.overriddenStreamClassId.sootType) + override fun chooseClassIdWithConstructor(classId: ClassId): ClassId = error("No constructor for Stream") override val modificationMethodId: MethodId diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/Strings.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/Strings.kt index 08a6083c36..08b74685ce 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/Strings.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/Strings.kt @@ -1,6 +1,9 @@ package org.utbot.engine import com.github.curiousoddman.rgxgen.RgxGen +import kotlin.math.max +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.persistentSetOf import org.utbot.common.unreachableBranch import org.utbot.engine.overrides.strings.UtNativeString import org.utbot.engine.overrides.strings.UtString @@ -43,15 +46,13 @@ import org.utbot.framework.plugin.api.util.charClassId import org.utbot.framework.plugin.api.util.constructorId import org.utbot.framework.plugin.api.util.defaultValueModel import org.utbot.framework.util.nextModelName -import kotlin.math.max -import kotlinx.collections.immutable.persistentListOf -import kotlinx.collections.immutable.persistentSetOf import soot.CharType import soot.IntType import soot.Scene import soot.SootClass import soot.SootField import soot.SootMethod +import soot.Type val utStringClass: SootClass get() = Scene.v().getSootClass(UtString::class.qualifiedName) @@ -186,6 +187,9 @@ class StringWrapper : BaseOverriddenWrapper(utStringClass.name) { ) return UtAssembleModel(addr, classId, modelName, instantiationCall) } + + override fun getPossibleConcreteTypes(type: Type): Set = + setOf(STRING_TYPE) } internal val utNativeStringClass = Scene.v().getSootClass(UtNativeString::class.qualifiedName) @@ -281,6 +285,9 @@ class UtNativeStringWrapper : WrapperInterface { } override fun value(resolver: Resolver, wrapper: ObjectValue): UtModel = UtNullModel(STRING_TYPE.classId) + + override fun getPossibleConcreteTypes(type: Type): Set = + setOf(STRING_TYPE) } sealed class UtAbstractStringBuilderWrapper(className: String) : BaseOverriddenWrapper(className) { @@ -337,6 +344,9 @@ sealed class UtAbstractStringBuilderWrapper(className: String) : BaseOverriddenW return UtAssembleModel(addr, wrapper.type.classId, modelName, instantiationCall) } + override fun getPossibleConcreteTypes(type: Type): Set = + setOf(type) + private val SootClass.valueField: SootField get() = getField("value", CharType.v().arrayType) diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/SymbolicValue.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/SymbolicValue.kt index 808ea96eee..0fec0da061 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/SymbolicValue.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/SymbolicValue.kt @@ -1,5 +1,6 @@ package org.utbot.engine +import java.util.Objects import org.utbot.engine.pc.UtAddrExpression import org.utbot.engine.pc.UtExpression import org.utbot.engine.pc.isConcrete @@ -12,7 +13,6 @@ import org.utbot.engine.pc.mkInt import org.utbot.engine.pc.mkLong import org.utbot.engine.pc.mkShort import org.utbot.engine.pc.toConcrete -import java.util.Objects import soot.ArrayType import soot.BooleanType import soot.ByteType @@ -179,7 +179,10 @@ fun SymbolicValue.toConcrete(): Any = when (this) { // TODO: one more constructor? fun objectValue(type: RefType, addr: UtAddrExpression, implementation: WrapperInterface) = - ObjectValue(TypeStorage(type), addr, Concrete(implementation)) + ObjectValue( + TypeStorage(type, implementation.getPossibleConcreteTypes(type)), + addr, Concrete(implementation) + ) val voidValue get() = PrimitiveValue(VoidType.v(), nullObjectAddr) diff --git a/utbot-sample/src/main/java/org/utbot/examples/casts/InstanceOfExample.java b/utbot-sample/src/main/java/org/utbot/examples/casts/InstanceOfExample.java index 0ad14f3a82..e41af60e0b 100644 --- a/utbot-sample/src/main/java/org/utbot/examples/casts/InstanceOfExample.java +++ b/utbot-sample/src/main/java/org/utbot/examples/casts/InstanceOfExample.java @@ -1,8 +1,7 @@ package org.utbot.examples.casts; +import java.util.*; import org.utbot.api.mock.UtMock; -import java.util.HashMap; -import java.util.Map; public class InstanceOfExample { public CastClassFirstSucc simpleInstanceOf(CastClass objectExample) { @@ -322,4 +321,59 @@ public Object[] instanceOfObjectArray(Object[] array) { return array; } + + public CharSequence charSequenceInstanceOf(CharSequence cs) { + if (cs instanceof String) { + return cs; + } + return cs; + } + + public List listInstanceOf(List list) { + if (list instanceof AbstractList) { + if (list instanceof ArrayList) { + return list; + } + } + return list; + } + + public Deque dequeInstanceOf(Deque deque) { + if (deque instanceof LinkedList) { + return deque; + } + return deque; + } + + public AbstractSequentialList abstractSequentialListInstanceOf(AbstractSequentialList list) { + if (list instanceof LinkedList) { + return list; + } + return list; + } + + public Set setInstanceOf(Set set) { + if (set instanceof AbstractSet) { + if (set instanceof HashSet) { + if (set instanceof LinkedHashSet) { + return set; + } + // TODO: we have wrapper of HashSet and this branch must be covered, but now it's not truth + } + } + return set; + } + + public Map mapInstanceOf(Map map) { + if (map instanceof AbstractMap) { + if (map instanceof HashMap) { + if (map instanceof LinkedHashMap) { + return map; + } + // TODO: we have wrapper of HashMap and this branch must be covered, but now it's not truth + } + } + return map; + } + }