Skip to content

Commit 2f8b870

Browse files
authored
Enables utbot-analytics module in utbot-intellij module (#733)
* Added an initial solution * Added an initial solution * Added a solution through the class name * Added an ut-settings * Added an ut-settings * Added an ut-settings * Added an ut-settings * Fixed tests * Return the settings back * Remove blank line
1 parent b7b18b9 commit 2f8b870

File tree

9 files changed

+19080
-39
lines changed

9 files changed

+19080
-39
lines changed

models/0/nn.json

Lines changed: 18970 additions & 0 deletions
Large diffs are not rendered by default.

models/0/scaler.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2.6720630059068036,1.0017657905428634,1.9156327155670845,9.149623402193956,28.647771666093696,3.7526096196518424,10.19303372191143,1.82985123605338,3.1600228146388725,1.5738584867331313,1.435431446698128,1.2643060286901897,1.1452401787667594
2+
1.858559757027421,0.4865249978344985,3.162572904879665,25.21040017953888,34.48252849402906,5.320336536404879,25.362484286622546,3.722723690419032,10.46575141988185,2.489423223957629,1.8889113541845977,1.0913557664615596,0.6525565126200781

utbot-analytics/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ test {
5959
jvmArgs '-XX:MaxHeapSize=3072m'
6060

6161
useJUnitPlatform() {
62-
excludeTags 'slow', 'IntegrationTest', 'Summary'
62+
excludeTags 'slow', 'IntegrationTest'
6363
}
6464
}
6565

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package org.utbot
2+
3+
import org.utbot.analytics.EngineAnalyticsContext
4+
import org.utbot.features.FeatureExtractorFactoryImpl
5+
import org.utbot.features.FeatureProcessorWithStatesRepetitionFactory
6+
import org.utbot.predictors.StateRewardPredictorFactoryImpl
7+
8+
/**
9+
* The basic configuration of the utbot-analytics module used in utbot-intellij and (as planned) in utbot-cli
10+
* to implement the hidden configuration initialization to avoid direct calls of this configuration and usage of utbot-analytics imports.
11+
*
12+
* @see <a href="https://github.com/UnitTestBot/UTBotJava/issues/725">
13+
* Issue: Enable utbot-analytics module in utbot-intellij module</a>
14+
*/
15+
object AnalyticsConfiguration {
16+
init {
17+
EngineAnalyticsContext.featureProcessorFactory = FeatureProcessorWithStatesRepetitionFactory()
18+
EngineAnalyticsContext.featureExtractorFactory = FeatureExtractorFactoryImpl()
19+
EngineAnalyticsContext.stateRewardPredictorFactory = StateRewardPredictorFactoryImpl()
20+
}
21+
}

utbot-analytics/src/test/kotlin/org/utbot/analytics/UtBotPredictorTest.kt

Lines changed: 0 additions & 10 deletions
This file was deleted.

utbot-analytics/src/test/kotlin/org/utbot/features/FeatureProcessorWithRepetitionTest.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,11 @@ class FeatureProcessorWithRepetitionTest : UtValueTestCaseChecker(OnePath::class
9696

9797
/**
9898
* Test, that we correctly add test cases and dump them into file
99+
*
100+
* NOTE: works only if the
101+
* ```
102+
* UtSettings.pathSelectorType == PathSelectorType.INHERITORS_SELECTOR
103+
* ```
99104
*/
100105
@Test
101106
fun addTestCaseTest() {

utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,11 @@ object UtSettings {
364364
*/
365365
var rewardModelPath by getStringProperty("../models/0")
366366

367+
/**
368+
* Full class name of the class containing the configuration for the ML models to solve path selection task.
369+
*/
370+
var analyticsConfigurationClassPath by getStringProperty("org.utbot.AnalyticsConfiguration")
371+
367372
/**
368373
* Number of model iterations that will be used during ContestEstimator
369374
*/

utbot-intellij/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ dependencies {
2929

3030
implementation(project(":utbot-framework")) { exclude group: 'org.slf4j', module: 'slf4j-api' }
3131
implementation(project(":utbot-fuzzers"))
32-
32+
api project(':utbot-analytics')
3333
testImplementation 'org.mock-server:mockserver-netty:5.4.1'
3434
testImplementation(project(":utbot-sample"))
3535
testApi(project(":utbot-framework"))

utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/UtTestsDialogProcessor.kt

Lines changed: 75 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,25 @@ import com.intellij.testIntegration.TestIntegrationUtils
2525
import com.intellij.util.concurrency.AppExecutorUtil
2626
import mu.KotlinLogging
2727
import org.jetbrains.kotlin.idea.util.module
28+
import org.utbot.analytics.EngineAnalyticsContext
29+
import org.utbot.analytics.Predictors
30+
import org.utbot.common.filterWhen
2831
import org.utbot.engine.util.mockListeners.ForceMockListener
2932
import org.utbot.framework.plugin.services.JdkInfoService
3033
import org.utbot.framework.UtSettings
3134
import org.utbot.framework.plugin.api.TestCaseGenerator
3235
import org.utbot.framework.plugin.api.UtMethod
3336
import org.utbot.framework.plugin.api.UtMethodTestSet
37+
import org.utbot.framework.plugin.api.testFlow
3438
import org.utbot.framework.plugin.api.util.UtContext
3539
import org.utbot.framework.plugin.api.util.withStaticsSubstitutionRequired
3640
import org.utbot.framework.plugin.api.util.withUtContext
3741
import org.utbot.intellij.plugin.generator.CodeGenerationController.generateTests
3842
import org.utbot.intellij.plugin.models.GenerateTestsModel
3943
import org.utbot.intellij.plugin.ui.GenerateTestsDialogWindow
4044
import org.utbot.intellij.plugin.ui.utils.showErrorDialogLater
45+
import org.utbot.intellij.plugin.ui.utils.suitableTestSourceRoots
46+
import org.utbot.intellij.plugin.ui.utils.testModules
4147
import org.utbot.intellij.plugin.util.IntelliJApiHelper
4248
import org.utbot.intellij.plugin.util.PluginJdkInfoProvider
4349
import org.utbot.intellij.plugin.util.signature
@@ -47,16 +53,14 @@ import java.net.URLClassLoader
4753
import java.nio.file.Path
4854
import java.nio.file.Paths
4955
import java.util.concurrent.TimeUnit
50-
import org.utbot.common.filterWhen
5156
import org.utbot.engine.util.mockListeners.ForceStaticMockListener
52-
import org.utbot.framework.plugin.api.testFlow
57+
import org.utbot.framework.PathSelectorType
5358
import org.utbot.framework.plugin.services.WorkingDirService
5459
import org.utbot.intellij.plugin.settings.Settings
5560
import org.utbot.intellij.plugin.ui.utils.isBuildWithGradle
5661
import org.utbot.intellij.plugin.ui.utils.suitableTestSourceRoots
5762
import org.utbot.intellij.plugin.util.PluginWorkingDirProvider
5863
import org.utbot.intellij.plugin.util.isAbstract
59-
import org.utbot.intellij.plugin.ui.utils.testModules
6064
import kotlin.reflect.KClass
6165
import kotlin.reflect.full.functions
6266

@@ -112,7 +116,8 @@ object UtTestsDialogProcessor {
112116
.make(
113117
// Compile only chosen classes and their dependencies before generation.
114118
CompositeScope(
115-
model.srcClasses.map{ OneProjectItemCompileScope(project, it.containingFile.virtualFile) }.toTypedArray()
119+
model.srcClasses.map { OneProjectItemCompileScope(project, it.containingFile.virtualFile) }
120+
.toTypedArray()
116121
)
117122
) { aborted: Boolean, errors: Int, _: Int, _: CompileContext ->
118123
if (!aborted && errors == 0) {
@@ -143,18 +148,23 @@ object UtTestsDialogProcessor {
143148
var processedClasses = 0
144149
val totalClasses = model.srcClasses.size
145150

151+
configureML()
152+
146153
val testCaseGenerator = TestCaseGenerator(
147-
Paths.get(buildDir),
148-
classpath,
149-
pluginJarsPath.joinToString(separator = File.pathSeparator),
150-
isCanceled = { indicator.isCanceled }
151-
)
154+
Paths.get(buildDir),
155+
classpath,
156+
pluginJarsPath.joinToString(separator = File.pathSeparator),
157+
isCanceled = { indicator.isCanceled }
158+
)
152159

153160
for (srcClass in model.srcClasses) {
154161
val methods = ReadAction.nonBlocking<List<UtMethod<*>>> {
155162
val clazz = classLoader.loadClass(srcClass.qualifiedName).kotlin
156-
val srcMethods = model.selectedMethods?.toList() ?:
157-
TestIntegrationUtils.extractClassMethods(srcClass, false)
163+
val srcMethods =
164+
model.selectedMethods?.toList() ?: TestIntegrationUtils.extractClassMethods(
165+
srcClass,
166+
false
167+
)
158168
.filterWhen(UtSettings.skipTestGenerationForSyntheticMethods) {
159169
it.member !is SyntheticElement
160170
}
@@ -172,14 +182,18 @@ object UtTestsDialogProcessor {
172182

173183
indicator.text = "Generate test cases for class $className"
174184
if (totalClasses > 1) {
175-
indicator.fraction = indicator.fraction.coerceAtLeast(0.9 * processedClasses / totalClasses)
185+
indicator.fraction =
186+
indicator.fraction.coerceAtLeast(0.9 * processedClasses / totalClasses)
176187
}
177188

178189
// set timeout for concrete execution and for generated tests
179190
UtSettings.concreteExecutionTimeoutInChildProcess = model.hangingTestsTimeout.timeoutMs
180191

181-
val searchDirectory = ReadAction
182-
.nonBlocking<Path> { project.basePath?.let { Paths.get(it) } ?: Paths.get(srcClass.containingFile.virtualFile.parent.path) }
192+
val searchDirectory = ReadAction
193+
.nonBlocking<Path> {
194+
project.basePath?.let { Paths.get(it) }
195+
?: Paths.get(srcClass.containingFile.virtualFile.parent.path)
196+
}
183197
.executeSynchronously()
184198

185199
withStaticsSubstitutionRequired(true) {
@@ -197,17 +211,17 @@ object UtTestsDialogProcessor {
197211
withUtContext(context) {
198212
testCaseGenerator
199213
.generate(
200-
methods,
201-
model.mockStrategy,
202-
model.chosenClassesToMockAlways,
203-
model.timeout,
204-
generate = testFlow {
205-
generationTimeout = model.timeout
206-
isSymbolicEngineEnabled = true
207-
isFuzzingEnabled = UtSettings.useFuzzing
208-
fuzzingValue = project.service<Settings>().fuzzingValue
209-
}
210-
)
214+
methods,
215+
model.mockStrategy,
216+
model.chosenClassesToMockAlways,
217+
model.timeout,
218+
generate = testFlow {
219+
generationTimeout = model.timeout
220+
isSymbolicEngineEnabled = true
221+
isFuzzingEnabled = UtSettings.useFuzzing
222+
fuzzingValue = project.service<Settings>().fuzzingValue
223+
}
224+
)
211225
.map { it.summarize(searchDirectory) }
212226
.filterNot { it.executions.isEmpty() && it.errors.isEmpty() }
213227
}
@@ -237,7 +251,8 @@ object UtTestsDialogProcessor {
237251
Messages.showInfoMessage(
238252
model.project,
239253
"No methods for test generation were found among selected items",
240-
"No methods found")
254+
"No methods found"
255+
)
241256
}
242257
return
243258
}
@@ -258,14 +273,47 @@ object UtTestsDialogProcessor {
258273
}
259274
}
260275

276+
/**
277+
* Configures utbot-analytics models for the better path selection.
278+
*
279+
* NOTE: If analytics configuration for the NN Path Selector could not be loaded,
280+
* it switches to the [PathSelectorType.INHERITORS_SELECTOR].
281+
*/
282+
private fun configureML() {
283+
logger.info { "PathSelectorType: ${UtSettings.pathSelectorType}" }
284+
285+
if (UtSettings.pathSelectorType == PathSelectorType.NN_REWARD_GUIDED_SELECTOR) {
286+
val analyticsConfigurationClassPath = UtSettings.analyticsConfigurationClassPath
287+
try {
288+
Class.forName(analyticsConfigurationClassPath)
289+
Predictors.stateRewardPredictor = EngineAnalyticsContext.stateRewardPredictorFactory()
290+
291+
logger.info { "RewardModelPath: ${UtSettings.rewardModelPath}" }
292+
} catch (e: ClassNotFoundException) {
293+
logger.error {
294+
"Configuration of the predictors from the utbot-analytics module described in the class: " +
295+
"$analyticsConfigurationClassPath is not found!"
296+
}
297+
298+
logger.info(e) {
299+
"Error while initialization of ${UtSettings.pathSelectorType}. Changing pathSelectorType on INHERITORS_SELECTOR"
300+
}
301+
UtSettings.pathSelectorType = PathSelectorType.INHERITORS_SELECTOR
302+
}
303+
}
304+
}
305+
261306
private fun errorMessage(className: String?, timeout: Long) = buildString {
262307
appendLine("UtBot failed to generate any test cases for class $className.")
263308
appendLine()
264309
appendLine("Try to alter test generation configuration, e.g. enable mocking and static mocking.")
265310
appendLine("Alternatively, you could try to increase current timeout $timeout sec for generating tests in generation dialog.")
266311
}
267312

268-
private fun findMethodsInClassMatchingSelected(clazz: KClass<*>, selectedMethods: List<MemberInfo>): List<UtMethod<*>> {
313+
private fun findMethodsInClassMatchingSelected(
314+
clazz: KClass<*>,
315+
selectedMethods: List<MemberInfo>
316+
): List<UtMethod<*>> {
269317
val selectedSignatures = selectedMethods.map { it.signature() }
270318
return clazz.functions
271319
.sortedWith(compareBy { selectedSignatures.indexOf(it.signature()) })

0 commit comments

Comments
 (0)