Skip to content

Commit c1c10ff

Browse files
authored
Fuzzer generates values even when class is private #1635 (#1638)
1 parent fb77613 commit c1c10ff

File tree

3 files changed

+66
-34
lines changed

3 files changed

+66
-34
lines changed

utbot-fuzzers/src/main/kotlin/org/utbot/fuzzing/providers/Objects.kt

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -104,18 +104,6 @@ class ObjectValueProvider(
104104
|| (type.isInner && !type.isStatic)
105105
}
106106

107-
private fun isAccessible(member: Member, packageName: String?): Boolean {
108-
return Modifier.isPublic(member.modifiers) ||
109-
(packageName != null && isPackagePrivate(member.modifiers) && member.declaringClass.`package`?.name == packageName)
110-
}
111-
112-
private fun isPackagePrivate(modifiers: Int): Boolean {
113-
val hasAnyAccessModifier = Modifier.isPrivate(modifiers)
114-
|| Modifier.isProtected(modifiers)
115-
|| Modifier.isProtected(modifiers)
116-
return !hasAnyAccessModifier
117-
}
118-
119107
private fun findTypesOfNonRecursiveConstructor(type: FuzzedType, packageName: String?): List<ConstructorId> {
120108
return type.classId.allConstructors
121109
.filter { isAccessible(it.constructor, packageName) }
@@ -186,16 +174,22 @@ internal fun Class<*>.findPublicSetterGetterIfHasPublicGetter(field: Field, pack
186174
}
187175
}
188176

189-
190-
191177
internal fun isAccessible(member: Member, packageName: String?): Boolean {
178+
var clazz = member.declaringClass
179+
while (clazz != null) {
180+
if (!isAccessible(clazz, packageName)) return false
181+
clazz = clazz.enclosingClass
182+
}
192183
return Modifier.isPublic(member.modifiers) ||
193-
(packageName != null && isPackagePrivate(member.modifiers) && member.declaringClass.`package`?.name == packageName)
184+
(packageName != null && isNotPrivateOrProtected(member.modifiers) && member.declaringClass.`package`?.name == packageName)
185+
}
186+
187+
internal fun isAccessible(clazz: Class<*>, packageName: String?): Boolean {
188+
return Modifier.isPublic(clazz.modifiers) ||
189+
(packageName != null && isNotPrivateOrProtected(clazz.modifiers) && clazz.declaringClass.`package`?.name == packageName)
194190
}
195191

196-
internal fun isPackagePrivate(modifiers: Int): Boolean {
197-
val hasAnyAccessModifier = Modifier.isPrivate(modifiers)
198-
|| Modifier.isProtected(modifiers)
199-
|| Modifier.isProtected(modifiers)
192+
private fun isNotPrivateOrProtected(modifiers: Int): Boolean {
193+
val hasAnyAccessModifier = Modifier.isPrivate(modifiers) || Modifier.isProtected(modifiers)
200194
return !hasAnyAccessModifier
201195
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package org.utbot.fuzzing.samples;
2+
3+
@SuppressWarnings("unused")
4+
public class AccessibleObjects {
5+
6+
public boolean test(Inn.Node n) {
7+
return n.value * n.value == 36;
8+
}
9+
10+
private static class Inn {
11+
static class Node {
12+
public int value;
13+
14+
public Node() {
15+
16+
}
17+
}
18+
}
19+
}

utbot-fuzzers/src/test/kotlin/org/utbot/fuzzing/JavaFuzzingTest.kt

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import org.utbot.framework.plugin.api.util.*
1111
import org.utbot.fuzzer.FuzzedConcreteValue
1212
import org.utbot.fuzzing.samples.DeepNested
1313
import org.utbot.fuzzer.FuzzedType
14+
import org.utbot.fuzzing.samples.AccessibleObjects
1415
import org.utbot.fuzzing.samples.Stubs
1516
import org.utbot.fuzzing.utils.Trie
1617
import java.lang.reflect.GenericArrayType
@@ -22,23 +23,24 @@ class JavaFuzzingTest {
2223

2324
@Test
2425
fun `fuzzing doesn't throw an exception when type is unknown`() {
25-
assertDoesNotThrow {
26-
runBlockingWithContext {
27-
runJavaFuzzing(
28-
TestIdentityPreservingIdGenerator,
29-
methodUnderTest = MethodId(
30-
DeepNested.Nested1.Nested2::class.id,
31-
"f",
32-
intClassId,
33-
listOf(intClassId)
34-
),
35-
constants = emptyList(),
36-
names = emptyList(),
37-
) { _, _, _ ->
38-
fail("This method is never called")
39-
}
26+
var count = 0
27+
runBlockingWithContext {
28+
runJavaFuzzing(
29+
TestIdentityPreservingIdGenerator,
30+
methodUnderTest = MethodId(
31+
DeepNested.Nested1.Nested2::class.id,
32+
"f",
33+
intClassId,
34+
listOf(intClassId)
35+
),
36+
constants = emptyList(),
37+
names = emptyList(),
38+
) { _, _, _ ->
39+
count += 1
40+
BaseFeedback(Trie.emptyNode(), Control.STOP)
4041
}
4142
}
43+
assertEquals(0, count)
4244
}
4345

4446
@Test
@@ -195,6 +197,23 @@ class JavaFuzzingTest {
195197
}
196198
}
197199

200+
@Test
201+
fun `fuzzing should not generate values of private classes`() {
202+
var exec = 0
203+
runBlockingWithContext {
204+
runJavaFuzzing(
205+
TestIdentityPreservingIdGenerator,
206+
methodUnderTest = AccessibleObjects::class.java.declaredMethods.first { it.name == "test" }.executableId,
207+
constants = emptyList(),
208+
names = emptyList(),
209+
) { _, _, _ ->
210+
exec += 1
211+
BaseFeedback(Trie.emptyNode(), Control.STOP)
212+
}
213+
}
214+
assertEquals(0, exec) { "Fuzzer should not create any values of private classes" }
215+
}
216+
198217
private fun <T> runBlockingWithContext(block: suspend () -> T) : T {
199218
return withUtContext(UtContext(this::class.java.classLoader)) {
200219
runBlocking {

0 commit comments

Comments
 (0)