1
+ package org.utbot.fuzzing.spring.unit
2
+
3
+ import mu.KotlinLogging
4
+ import org.utbot.framework.plugin.api.ClassId
5
+ import org.utbot.framework.plugin.api.MethodId
6
+ import org.utbot.framework.plugin.api.UtCompositeModel
7
+ import org.utbot.framework.plugin.api.util.executableId
8
+ import org.utbot.framework.plugin.api.util.jClass
9
+ import org.utbot.framework.plugin.api.util.method
10
+ import org.utbot.fuzzer.FuzzedType
11
+ import org.utbot.fuzzer.FuzzedValue
12
+ import org.utbot.fuzzer.IdGenerator
13
+ import org.utbot.fuzzer.fuzzed
14
+ import org.utbot.fuzzing.FuzzedDescription
15
+ import org.utbot.fuzzing.JavaValueProvider
16
+ import org.utbot.fuzzing.Routine
17
+ import org.utbot.fuzzing.Scope
18
+ import org.utbot.fuzzing.ScopeProperty
19
+ import org.utbot.fuzzing.Seed
20
+ import org.utbot.fuzzing.toFuzzerType
21
+
22
+ val methodsToMockProperty = ScopeProperty <Set <MethodId >>(
23
+ description = " Method ids that can be mocked by `MockValueProvider`"
24
+ )
25
+
26
+ // TODO shouldn't be used for primitives and other "easy" to create types
27
+ class MockValueProvider (private val idGenerator : IdGenerator <Int >) : JavaValueProvider {
28
+ companion object {
29
+ private val logger = KotlinLogging .logger {}
30
+ private val loggedMockedMethods = mutableSetOf<MethodId >()
31
+ }
32
+
33
+ private val methodsToMock = mutableSetOf<MethodId >()
34
+
35
+ override fun enrich (description : FuzzedDescription , type : FuzzedType , scope : Scope ) {
36
+ val publicMethods = type.classId.jClass.methods.map { it.executableId }
37
+ publicMethods.intersect(methodsToMock).takeIf { it.isNotEmpty() }?.let {
38
+ scope.putProperty(methodsToMockProperty, it)
39
+ }
40
+ }
41
+
42
+ override fun generate (description : FuzzedDescription , type : FuzzedType ): Sequence <Seed <FuzzedType , FuzzedValue >> =
43
+ sequenceOf(Seed .Recursive (
44
+ construct = Routine .Create (types = emptyList()) { emptyMockFuzzedValue(type.classId) },
45
+ empty = Routine .Empty { emptyMockFuzzedValue(type.classId) },
46
+ modify = (description.scope?.getProperty(methodsToMockProperty)?.asSequence() ? : emptySequence()).map { methodId ->
47
+ if (loggedMockedMethods.add(methodId))
48
+ logger.info { " Actually mocked $methodId for the first time" }
49
+ // TODO accept `List<returnType>` instead of singular `returnType`
50
+ Routine .Call (types = listOf (
51
+ toFuzzerType(methodId.method.genericReturnType, description.typeCache)
52
+ )) { instance, (value) ->
53
+ (instance.model as UtCompositeModel ).mocks[methodId] = listOf (value.model)
54
+ }
55
+ }
56
+ ))
57
+
58
+ private fun emptyMockFuzzedValue (classId : ClassId ) = UtCompositeModel (
59
+ id = idGenerator.createId(),
60
+ classId = classId,
61
+ isMock = true ,
62
+ canHaveRedundantOrMissingMocks = true ,
63
+ ).fuzzed { summary = " %var% = mock()" }
64
+
65
+ fun addMockingCandidates (detectedMockingCandidates : Set <MethodId >) =
66
+ detectedMockingCandidates.forEach { methodId ->
67
+ if (methodsToMock.add(methodId))
68
+ logger.info { " Detected that $methodId may need mocking" }
69
+ }
70
+ }
0 commit comments