Skip to content

Commit 01f2181

Browse files
committed
Fuzzing doesn't generate test for package-private parameters
1 parent acc590b commit 01f2181

File tree

5 files changed

+81
-14
lines changed

5 files changed

+81
-14
lines changed

utbot-framework/src/main/kotlin/org/utbot/engine/UtBotSymbolicEngine.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,8 @@ class UtBotSymbolicEngine(
406406

407407
val methodUnderTestDescription = FuzzedMethodDescription(executableId, collectConstantsForFuzzer(graph)).apply {
408408
compilableName = if (methodUnderTest.isMethod) executableId.name else null
409+
className = executableId.classId.simpleName
410+
packageName = executableId.classId.packageName
409411
val names = graph.body.method.tags.filterIsInstance<ParamNamesTag>().firstOrNull()?.names
410412
parameterNameMap = { index -> names?.getOrNull(index) }
411413
}

utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/FuzzedMethodDescription.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@ class FuzzedMethodDescription(
2525
*/
2626
var compilableName: String? = null
2727

28+
/**
29+
* Class Name
30+
*/
31+
var className: String? = null
32+
33+
/**
34+
* Package Name
35+
*/
36+
var packageName: String? = null
37+
2838
/**
2939
* Returns parameter name by its index in the signature
3040
*/

utbot-fuzzers/src/main/kotlin/org/utbot/fuzzer/providers/ObjectModelProvider.kt

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class ObjectModelProvider : ModelProvider {
6767
.filterNot { it == stringClassId || it.isPrimitiveWrapper }
6868
.flatMap { classId ->
6969
collectConstructors(classId) { javaConstructor ->
70-
isPublic(javaConstructor)
70+
isPublic(javaConstructor) || isPackagePrivateAndSameMethodPackage(javaConstructor, description)
7171
}.sortedWith(
7272
primitiveParameterizedConstructorsFirstAndThenByParameterCount
7373
).take(limit)
@@ -81,7 +81,7 @@ class ObjectModelProvider : ModelProvider {
8181
.flatMap { (constructorId, fuzzedParameters) ->
8282
if (constructorId.parameters.isEmpty()) {
8383
sequenceOf(assembleModel(idGenerator.asInt, constructorId, emptyList())) +
84-
generateModelsWithFieldsInitialization(constructorId, concreteValues)
84+
generateModelsWithFieldsInitialization(constructorId, description, concreteValues)
8585
}
8686
else {
8787
fuzzedParameters.map { params ->
@@ -98,8 +98,8 @@ class ObjectModelProvider : ModelProvider {
9898
}
9999
}
100100

101-
private fun generateModelsWithFieldsInitialization(constructorId: ConstructorId, concreteValues: Collection<FuzzedConcreteValue>): Sequence<FuzzedValue> {
102-
val fields = findSuitableFields(constructorId.classId)
101+
private fun generateModelsWithFieldsInitialization(constructorId: ConstructorId, description: FuzzedMethodDescription, concreteValues: Collection<FuzzedConcreteValue>): Sequence<FuzzedValue> {
102+
val fields = findSuitableFields(constructorId.classId, description)
103103
val syntheticClassFieldsSetterMethodDescription = FuzzedMethodDescription(
104104
"${constructorId.classId.simpleName}<syntheticClassFieldSetter>",
105105
voidClassId,
@@ -115,16 +115,16 @@ class ObjectModelProvider : ModelProvider {
115115
fieldValues.asSequence().mapIndexedNotNull { index, value ->
116116
val field = fields[index]
117117
when {
118-
field.setter != null -> UtExecutableCallModel(
119-
fuzzedModel.model,
120-
MethodId(constructorId.classId, field.setter.name, field.setter.returnType.id, listOf(field.classId)),
121-
listOf(value.model)
122-
)
123118
field.canBeSetDirectly -> UtDirectSetFieldModel(
124119
fuzzedModel.model,
125120
FieldId(constructorId.classId, field.name),
126121
value.model
127122
)
123+
field.setter != null -> UtExecutableCallModel(
124+
fuzzedModel.model,
125+
MethodId(constructorId.classId, field.setter.name, field.setter.returnType.id, listOf(field.classId)),
126+
listOf(value.model)
127+
)
128128
else -> null
129129
}
130130
}.forEach(modificationChain::add)
@@ -145,6 +145,14 @@ class ObjectModelProvider : ModelProvider {
145145
return javaConstructor.modifiers and Modifier.PUBLIC != 0
146146
}
147147

148+
private fun isPackagePrivateAndSameMethodPackage(javaConstructor: Constructor<*>, description: FuzzedMethodDescription): Boolean {
149+
return javaConstructor.modifiers == 0 && javaConstructor.declaringClass.`package`.name == description.packageName
150+
}
151+
152+
private fun isPackagePrivateAndSameMethodPackage(field: Field, description: FuzzedMethodDescription): Boolean {
153+
return field.modifiers == 0 && field.declaringClass.`package`.name == description.packageName
154+
}
155+
148156
private fun FuzzedMethodDescription.fuzzParameters(constructorId: ConstructorId, vararg modelProviders: ModelProvider): Sequence<List<FuzzedValue>> {
149157
val fuzzedMethod = FuzzedMethodDescription(
150158
executableId = constructorId,
@@ -168,13 +176,13 @@ class ObjectModelProvider : ModelProvider {
168176
}
169177
}
170178

171-
private fun findSuitableFields(classId: ClassId): List<FieldDescription> {
179+
private fun findSuitableFields(classId: ClassId, description: FuzzedMethodDescription): List<FieldDescription> {
172180
val jClass = classId.jClass
173181
return jClass.declaredFields.map { field ->
174182
FieldDescription(
175183
field.name,
176184
field.type.id,
177-
field.isPublic && !field.isFinal && !field.isStatic,
185+
(field.isPublic || isPackagePrivateAndSameMethodPackage(field, description)) && !field.isFinal && !field.isStatic,
178186
jClass.findPublicSetterIfHasPublicGetter(field)
179187
)
180188
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package org.utbot.framework.plugin.api.samples;
2+
3+
@SuppressWarnings("All")
4+
public class PackagePrivateFieldAndClass {
5+
6+
int pkgField = 0;
7+
8+
PackagePrivateFieldAndClass() {
9+
10+
}
11+
12+
PackagePrivateFieldAndClass(int value) {
13+
pkgField = value;
14+
}
15+
16+
}

utbot-fuzzers/src/test/kotlin/org/utbot/framework/plugin/api/ModelProviderTest.kt

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import org.utbot.fuzzer.providers.StringConstantModelProvider
2424
import org.junit.jupiter.api.Assertions.*
2525
import org.junit.jupiter.api.Test
2626
import org.utbot.framework.plugin.api.samples.FieldSetterClass
27+
import org.utbot.framework.plugin.api.samples.PackagePrivateFieldAndClass
2728
import org.utbot.framework.plugin.api.util.primitiveByWrapper
2829
import org.utbot.framework.plugin.api.util.primitiveWrappers
2930
import org.utbot.framework.plugin.api.util.voidWrapperClassId
@@ -469,20 +470,50 @@ class ModelProviderTest {
469470
assertEquals(expectedModificationSize, actualModificationSize) { "In target class there's only $expectedModificationSize fields that can be changed, but generated $actualModificationSize modifications" }
470471

471472
assertEquals("pubField", (modificationsChain[0] as UtDirectSetFieldModel).fieldId.name)
472-
assertEquals("setPubFieldWithSetter", (modificationsChain[1] as UtExecutableCallModel).executable.name)
473+
assertEquals("pubFieldWithSetter", (modificationsChain[1] as UtDirectSetFieldModel).fieldId.name)
473474
assertEquals("setPrvFieldWithSetter", (modificationsChain[2] as UtExecutableCallModel).executable.name)
474475
}
475476
}
476477

478+
@Test
479+
fun `test complex object is created with setters and package private field and constructor`() {
480+
val j = PackagePrivateFieldAndClass::class.java
481+
assertEquals(1, j.declaredFields.size)
482+
assertTrue(
483+
setOf(
484+
"pkgField",
485+
).containsAll(j.declaredFields.map { it.name })
486+
)
487+
488+
withUtContext(UtContext(this::class.java.classLoader)) {
489+
val result = collect(ObjectModelProvider { 0 }.apply {
490+
modelProvider = PrimitiveDefaultsModelProvider
491+
}, parameters = listOf(PackagePrivateFieldAndClass::class.java.id)) {
492+
packageName = PackagePrivateFieldAndClass::class.java.`package`.name
493+
}
494+
assertEquals(1, result.size)
495+
assertEquals(3, result[0]!!.size)
496+
assertEquals(0, (result[0]!![0] as UtAssembleModel).modificationsChain.size) { "One of models must be without any modifications" }
497+
assertEquals(0, (result[0]!![2] as UtAssembleModel).modificationsChain.size) { "Modification by constructor doesn't change fields" }
498+
val expectedModificationSize = 1
499+
val modificationsChain = (result[0]!![1] as UtAssembleModel).modificationsChain
500+
val actualModificationSize = modificationsChain.size
501+
assertEquals(expectedModificationSize, actualModificationSize) { "In target class there's only $expectedModificationSize fields that can be changed, but generated $actualModificationSize modifications" }
502+
503+
assertEquals("pkgField", (modificationsChain[0] as UtDirectSetFieldModel).fieldId.name)
504+
}
505+
}
506+
477507
private fun collect(
478508
modelProvider: ModelProvider,
479509
name: String = "testMethod",
480510
returnType: ClassId = voidClassId,
481511
parameters: List<ClassId>,
482-
constants: List<FuzzedConcreteValue> = emptyList()
512+
constants: List<FuzzedConcreteValue> = emptyList(),
513+
block: FuzzedMethodDescription.() -> Unit = {}
483514
): Map<Int, List<UtModel>> {
484515
return mutableMapOf<Int, MutableList<UtModel>>().apply {
485-
modelProvider.generate(FuzzedMethodDescription(name, returnType, parameters, constants)) { i, m ->
516+
modelProvider.generate(FuzzedMethodDescription(name, returnType, parameters, constants).apply(block)) { i, m ->
486517
computeIfAbsent(i) { mutableListOf() }.add(m.model)
487518
}
488519
}

0 commit comments

Comments
 (0)