Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
1175678
squash constraint model synthesis
AbdullinAM Sep 28, 2022
d69ebc4
squash constraint model synthesis
AbdullinAM Sep 28, 2022
8d68488
resolver fix
AbdullinAM Sep 29, 2022
c6cac8d
model based post condition constructor restored
AbdullinAM Sep 29, 2022
df75f26
very primitive global timeoutfor synthesis
AbdullinAM Oct 11, 2022
e10a50e
Primitive Stream wrappers (no laziness and source mutations support) …
Damtev Sep 28, 2022
80da28b
Avoid summary duplication #985 (#1015)
onewhl Sep 28, 2022
608d56c
Fix bug in filtering Kotlin getters/setters in plugin (#1026)
volivan239 Sep 28, 2022
1f59106
Reordered the test clusters (#991)
amandelpie Sep 30, 2022
f96c118
Fix build directory for classes from Kotlin files (#1019)
volivan239 Sep 30, 2022
40bf31b
Improve choosing between simpleName and canonicalName in rendered cod…
EgorkaKulikov Sep 30, 2022
3380506
Run tests on `push` into release branches (#1045)
viktoriia-fomina Sep 30, 2022
234ace0
Fix utbot-maven compilation (#1049)
dtim Oct 1, 2022
1a0289d
Support AssertionError in SARIF report (#1032)
mmvpm Oct 3, 2022
7b417c9
Render links in the invokes part of JavaDocs (#1051)
onewhl Oct 3, 2022
0cedf7a
Improve fuzzer recursive model providers (#1039)
Markoutte Oct 3, 2022
4293d4f
IndexNotReadyException thrown in IDEA with installed UnitTestBot plug…
Vassiliy-Kudryashov Oct 3, 2022
a5d628c
Publish without workflow run number (#1053)
viktoriia-fomina Oct 3, 2022
ba08cb7
Modificators processing in AssembleModelGenerator and UtBotFieldModif…
EgorkaKulikov Oct 3, 2022
ae5b883
Gradle cache usage added #974 (#998)
bissquit Oct 4, 2022
b6d8a65
Try to fix memory leak in CgComponents (#1057)
EgorkaKulikov Oct 4, 2022
77194a3
Repeating SourceFolder fix (#1073)
Domonion Oct 4, 2022
0ff62da
Include information about triggered recursion to Javadocs (#1084)
onewhl Oct 4, 2022
e5d8b5f
Fix rendering for different IDE versions (#1087)
onewhl Oct 4, 2022
8016349
Fixed unavailable mock classes (#1066)
Damtev Oct 5, 2022
f55c96d
Engine process #2 (#1067)
Domonion Oct 5, 2022
f3af058
Remove unsat states from invokes (#1071)
CaelmBleidd Oct 5, 2022
e298169
Settings revision, 2nd iteration #977 (#1088)
Vassiliy-Kudryashov Oct 5, 2022
5a690b9
Fix soot initialization (#1090)
sergeypospelov Oct 5, 2022
cd3dcd1
Improve verification that static mocking is configured (#1091)
EgorkaKulikov Oct 5, 2022
b067af9
Fix assertions (#1096)
SBOne-Kenobi Oct 5, 2022
43efb96
Cancel test generation if compilation was not successful #1100 (#1103)
volivan239 Oct 5, 2022
bf272b6
Vassiliy kudryashov/1021 plugin support idea 20222 new (#1094)
Vassiliy-Kudryashov Oct 5, 2022
fc61391
Wrap method reference into @link tag only if the invoked method is no…
onewhl Oct 6, 2022
4ce788d
Notify and reason to the user that UtBot can't be run on the class in…
EgorkaKulikov Oct 6, 2022
0abc48b
Make snapshot version calendar-dependant (#1108)
Vassiliy-Kudryashov Oct 6, 2022
a215477
We create temporary files a lot, we have to clean it either (#1089)
Vassiliy-Kudryashov Oct 7, 2022
8280807
Get PsiClass' package by declaration in containingFile and not by its…
volivan239 Oct 7, 2022
8fb3938
Out of process bug fixes (#1109)
Domonion Oct 7, 2022
5fb1e16
Plugin setting to choose Kotlin generation doesn't work #1075 (#1110)
Vassiliy-Kudryashov Oct 7, 2022
ad150ba
Lessen thisInstance creation in parameterized test generation (#1065)
sofurihafe Oct 7, 2022
2f03687
Fix settings persistence: we save IDs, thus we should parse IDs inste…
Vassiliy-Kudryashov Oct 7, 2022
15bdfa8
Support Android Studio in utbot-intellij (#1121)
EgorkaKulikov Oct 10, 2022
166b393
Select Kotlin test src root by default when generating for Kotlin #94…
volivan239 Oct 10, 2022
c7618bb
Filter generated sources in Android Studio projects #692 (#1123)
EgorkaKulikov Oct 10, 2022
5479449
Exclude mocking javax (#1124)
SBOne-Kenobi Oct 10, 2022
06c548e
Linux engine process fix (#1126)
Domonion Oct 10, 2022
7e71d75
Android Studio troubleshooting related to Lombok improved (#1131)
EgorkaKulikov Oct 11, 2022
1a18c53
Other class is not mocked as required #747 (#1033)
Markoutte Oct 11, 2022
d1bea97
Add parameterized test generation in CI (#1114)
sofurihafe Oct 11, 2022
5181cef
Fix static mocking (#1142)
SBOne-Kenobi Oct 12, 2022
4706d1b
Added simple custom JavaDocs for the tests produced by Fuzzer (#1069)
amandelpie Oct 12, 2022
d36b988
Concrete execution fails for a static method using a static field #71…
Markoutte Oct 12, 2022
a55999d
Field assertions fixes (#920)
Damtev Oct 12, 2022
529c10d
Fix dump mode fail (#1146)
Domonion Oct 13, 2022
4470ea8
Refactor Sarif reports (#1152)
mmvpm Oct 13, 2022
d4cb666
Publish plugin and CLI for minor release (#1155)
viktoriia-fomina Oct 14, 2022
cad8133
Fixing long summarization timeouts & mics (#1151)
Domonion Oct 14, 2022
724b794
squash constraint model synthesis
AbdullinAM Sep 28, 2022
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
Next Next commit
Other class is not mocked as required #747 (#1033)
  • Loading branch information
Markoutte authored and AbdullinAM committed Oct 17, 2022
commit 1a18c538fe0e110aab41d8bca06caf79a94420af
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ class UtBotSymbolicEngine(
private val methodUnderTest: SymbolicEngineTarget,
classpath: String,
dependencyPaths: String,
mockStrategy: MockStrategy = NO_MOCKS,
val mockStrategy: MockStrategy = NO_MOCKS,
chosenClassesToMockAlways: Set<ClassId>,
private val solverTimeoutInMillis: Int = checkSolverTimeoutMillis,
private val useSynthesis: Boolean = enableSynthesis,
Expand Down Expand Up @@ -475,6 +475,7 @@ class UtBotSymbolicEngine(
val names = graph.body.method.tags.filterIsInstance<ParamNamesTag>().firstOrNull()?.names
parameterNameMap = { index -> names?.getOrNull(index) }
fuzzerType = { try { toFuzzerType(executableId.executable.genericParameterTypes[it]) } catch (_: Throwable) { null } }
shouldMock = { mockStrategy.eligibleToMock(it, classUnderTest) }
}
val coveredInstructionTracker = Trie(Instruction::id)
val coveredInstructionValues = linkedMapOf<Trie.Node<Instruction>, List<FuzzedValue>>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ class FuzzedMethodDescription(
*/
var fuzzerType: (Int) -> FuzzedType? = { null }

/**
* Returns true if class should be mocked.
*/
var shouldMock: (ClassId) -> Boolean = { false }

/**
* Map class id to indices of this class in parameters list.
*/
Expand Down
27 changes: 12 additions & 15 deletions utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/FuzzedValue.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,19 @@ import org.utbot.framework.plugin.api.UtModel
/**
* Fuzzed Value stores information about concrete UtModel, reference to [ModelProvider]
* and reasons about why this value was generated.
*
* [summary] is a piece of useful information that clarify why this value has a concrete value.
*
* It supports a special character `%var%` that is used as a placeholder for parameter name.
*
* For example:
* 1. `%var% = 2` for a value that have value 2
* 2. `%var% >= 4` for a value that shouldn't be less than 4
* 3. `foo(%var%) returns true` for values that should be passed as a function parameter
* 4. `%var% has special characters` to describe content
*/
open class FuzzedValue(
val model: UtModel,
val createdBy: ModelProvider? = null,
) {

/**
* Summary is a piece of useful information that clarify why this value has a concrete value.
*
* It supports a special character `%var%` that is used as a placeholder for parameter name.
*
* For example:
* 1. `%var% = 2` for a value that have value 2
* 2. `%var% >= 4` for a value that shouldn't be less than 4
* 3. `foo(%var%) returns true` for values that should be passed as a function parameter
* 4. `%var% has special characters` to describe content
*/
var summary: String? = null
}
var summary: String? = null,
)
6 changes: 5 additions & 1 deletion utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/Fuzzer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import org.utbot.framework.plugin.api.util.voidClassId
import org.utbot.fuzzer.mutators.NumberRandomMutator
import org.utbot.fuzzer.mutators.RegexStringModelMutator
import org.utbot.fuzzer.mutators.StringRandomMutator
import org.utbot.fuzzer.objects.replaceWithMock
import org.utbot.fuzzer.providers.ArrayModelProvider
import org.utbot.fuzzer.providers.CharToStringModelProvider
import org.utbot.fuzzer.providers.CollectionWithEmptyStatesModelProvider
Expand Down Expand Up @@ -117,7 +118,10 @@ fun fuzz(description: FuzzedMethodDescription, vararg modelProviders: ModelProvi
val values = List<MutableList<FuzzedValue>>(description.parameters.size) { mutableListOf() }
modelProviders.forEach { fuzzingProvider ->
fuzzingProvider.generate(description).forEach { (index, model) ->
values[index].add(model)
val mock = replaceWithMock(model.model, description.shouldMock)
values[index].add(FuzzedValue(mock, model.createdBy).apply {
summary = model.summary
})
}
}
description.parameters.forEachIndexed { index, classId ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package org.utbot.fuzzer.objects
import org.utbot.framework.plugin.api.ClassId
import org.utbot.framework.plugin.api.ConstructorId
import org.utbot.framework.plugin.api.ExecutableId
import org.utbot.framework.plugin.api.FieldId
import org.utbot.framework.plugin.api.MethodId
import org.utbot.framework.plugin.api.UtAssembleModel
import org.utbot.framework.plugin.api.UtDirectSetFieldModel
import org.utbot.framework.plugin.api.UtExecutableCallModel
import org.utbot.framework.plugin.api.UtModel
import org.utbot.framework.plugin.api.UtStatementModel
Expand Down Expand Up @@ -38,6 +40,7 @@ class AssembleModelDsl internal constructor(
val call = KeyWord.Call
val constructor = KeyWord.Constructor(classId)
val method = KeyWord.Method(classId)
val field = KeyWord.Field(classId)

var id: () -> Int? = { null }
var name: (Int?) -> String = { "<dsl generated model>" }
Expand All @@ -53,10 +56,15 @@ class AssembleModelDsl internal constructor(

infix fun <T : ExecutableId> KeyWord.Call.instance(executableId: T) = CallDsl(executableId, false)

infix fun <T : FieldId> KeyWord.Call.instance(field: T) = FieldDsl(field, false)

infix fun <T : ExecutableId> KeyWord.Using.static(executableId: T) = UsingDsl(executableId)

infix fun <T : ExecutableId> KeyWord.Call.static(executableId: T) = CallDsl(executableId, true)

infix fun <T : FieldId> KeyWord.Call.static(field: T) = FieldDsl(field, true)

@Suppress("UNUSED_PARAMETER")
infix fun KeyWord.Using.empty(ignored: KeyWord.Constructor) {
initialization = { UtExecutableCallModel(null, ConstructorId(classId, emptyList()), emptyList()) }
}
Expand All @@ -73,6 +81,10 @@ class AssembleModelDsl internal constructor(
modChain += { UtExecutableCallModel(it, executableId, models.toList()) }
}

infix fun FieldDsl.with(model: UtModel) {
modChain += { UtDirectSetFieldModel(it, fieldId, model) }
}

internal fun build(): UtAssembleModel {
val objectId = id()
return UtAssembleModel(
Expand Down Expand Up @@ -102,8 +114,14 @@ class AssembleModelDsl internal constructor(
return MethodId(classId, name, returns, params)
}
}
class Field(val classId: ClassId) : KeyWord() {
operator fun invoke(name: String): FieldId {
return FieldId(classId, name)
}
}
}

class UsingDsl(val executableId: ExecutableId)
class CallDsl(val executableId: ExecutableId, val isStatic: Boolean)
class FieldDsl(val fieldId: FieldId, val isStatic: Boolean)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package org.utbot.fuzzer.objects

import org.utbot.framework.plugin.api.ClassId
import org.utbot.framework.plugin.api.ExecutableId
import org.utbot.framework.plugin.api.MethodId
import org.utbot.framework.plugin.api.UtAssembleModel
import org.utbot.framework.plugin.api.UtCompositeModel
import org.utbot.framework.plugin.api.UtDirectSetFieldModel
import org.utbot.framework.plugin.api.UtExecutableCallModel
import org.utbot.framework.plugin.api.UtModel
import org.utbot.framework.plugin.api.UtStatementModel

/**
* Implements [MethodId] but also can supply a mock for this execution.
*
* Simplest example: setter and getter,
* when this methodId is a setter, getter can be used for a mock to supply correct value.
*/
internal class FuzzerMockableMethodId(
classId: ClassId,
name: String,
returnType: ClassId,
parameters: List<ClassId>,
val mock: () -> Map<ExecutableId, List<UtModel>> = { emptyMap() },
) : MethodId(classId, name, returnType, parameters) {

constructor(copyOf: MethodId, mock: () -> Map<ExecutableId, List<UtModel>> = { emptyMap() }) : this(
copyOf.classId, copyOf.name, copyOf.returnType, copyOf.parameters, mock
)

}

internal fun MethodId.toFuzzerMockable(block: suspend SequenceScope<Pair<MethodId, List<UtModel>>>.() -> Unit): FuzzerMockableMethodId {
return FuzzerMockableMethodId(this) {
sequence { block() }.toMap()
}
}

internal fun replaceWithMock(assembleModel: UtModel, shouldMock: (ClassId) -> Boolean): UtModel = when {
assembleModel !is UtAssembleModel -> assembleModel
shouldMock(assembleModel.classId) -> createMockModelFromFuzzerMockable(assembleModel, shouldMock)
else -> updateInnerModels(assembleModel, shouldMock)
}

private fun createMockModelFromFuzzerMockable(model: UtAssembleModel, shouldMock: (ClassId) -> Boolean): UtCompositeModel {
val mock = UtCompositeModel(model.id, model.classId, true)
for (mutator in model.modificationsChain) {
if (mutator is UtDirectSetFieldModel) {
mock.fields[mutator.fieldId] = replaceWithMock(mutator.fieldModel, shouldMock)
}
if (mutator is UtExecutableCallModel && mutator.executable is FuzzerMockableMethodId) {
(mutator.executable as FuzzerMockableMethodId).mock().forEach { (executionId, models) ->
mock.mocks[executionId] = models.map { p -> replaceWithMock(p, shouldMock) }
}
}
}
return mock
}

private fun updateInnerModels(model: UtAssembleModel, shouldMock: (ClassId) -> Boolean): UtAssembleModel {
val models = model.modificationsChain.map { call ->
var mockedStatementModel: UtStatementModel? = null
when (call) {
is UtDirectSetFieldModel -> {
val mock = replaceWithMock(call.fieldModel, shouldMock)
if (mock != call.fieldModel) {
mockedStatementModel = UtDirectSetFieldModel(call.instance, call.fieldId, mock)
}
}
is UtExecutableCallModel -> {
val params = call.params.map { m -> replaceWithMock(m, shouldMock) }
if (params != call.params) {
mockedStatementModel = UtExecutableCallModel(call.instance, call.executable, params)
}
}
}
mockedStatementModel ?: call
}
return with(model) {
UtAssembleModel(id, classId, modelName, instantiationCall, origin) { models }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import org.utbot.fuzzer.FuzzedMethodDescription
import org.utbot.fuzzer.FuzzedType
import org.utbot.fuzzer.FuzzedValue
import org.utbot.fuzzer.IdentityPreservingIdGenerator
import org.utbot.fuzzer.objects.FuzzerMockableMethodId
import org.utbot.fuzzer.objects.assembleModel

/**
Expand Down Expand Up @@ -101,11 +102,22 @@ class ObjectModelProvider(
)
field.setter != null -> UtExecutableCallModel(
fuzzedModel.model,
MethodId(
FuzzerMockableMethodId(
constructorId.classId,
field.setter.name,
field.setter.returnType.id,
listOf(field.classId)
listOf(field.classId),
mock = {
field.getter?.let { g ->
val getterMethodID = MethodId(
classId = constructorId.classId,
name = g.name,
returnType = g.returnType.id,
parameters = emptyList()
)
mapOf(getterMethodID to listOf(value.model))
} ?: emptyMap()
}
),
listOf(value.model)
)
Expand Down Expand Up @@ -144,16 +156,23 @@ class ObjectModelProvider(
private fun findSuitableFields(classId: ClassId, description: FuzzedMethodDescription): List<FieldDescription> {
val jClass = classId.jClass
return jClass.declaredFields.map { field ->
val setterAndGetter = jClass.findPublicSetterGetterIfHasPublicGetter(field, description)
FieldDescription(
field.name,
field.type.id,
isAccessible(field, description.packageName) && !isFinal(field.modifiers) && !isStatic(field.modifiers),
jClass.findPublicSetterIfHasPublicGetter(field, description)
name = field.name,
classId = field.type.id,
canBeSetDirectly = isAccessible(field, description.packageName) && !isFinal(field.modifiers) && !isStatic(field.modifiers),
setter = setterAndGetter?.setter,
getter = setterAndGetter?.getter,
)
}
}

private fun Class<*>.findPublicSetterIfHasPublicGetter(field: Field, description: FuzzedMethodDescription): Method? {
private class PublicSetterGetter(
val setter: Method,
val getter: Method,
)

private fun Class<*>.findPublicSetterGetterIfHasPublicGetter(field: Field, description: FuzzedMethodDescription): PublicSetterGetter? {
val postfixName = field.name.capitalize()
val setterName = "set$postfixName"
val getterName = "get$postfixName"
Expand All @@ -164,7 +183,7 @@ class ObjectModelProvider(
it.name == setterName &&
it.parameterCount == 1 &&
it.parameterTypes[0] == field.type
}
}?.let { PublicSetterGetter(it, getter) }
} else {
null
}
Expand All @@ -184,6 +203,7 @@ class ObjectModelProvider(
val classId: ClassId,
val canBeSetDirectly: Boolean,
val setter: Method?,
val getter: Method?
)
}
}
Loading