Skip to content

Commit fca42cf

Browse files
Improve test generation cancellation (#1458)
Co-authored-by: Vassiliy Kudryashov <vassiliy.kudryashov@gmail.com>
1 parent e379980 commit fca42cf

File tree

4 files changed

+78
-21
lines changed

4 files changed

+78
-21
lines changed

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,11 @@ object UtSettings : AbstractSettings(logger, defaultKeyForSettingsPath, defaultS
500500
* It is used to do not encode big type storages due to significand performance degradation.
501501
*/
502502
var maxNumberOfTypesToEncode by getIntProperty(512)
503+
504+
/**
505+
* The behaviour of further analysis if tests generation cancellation is requested.
506+
*/
507+
var cancellationStrategyType by getEnumProperty(CancellationStrategyType.SAVE_PROCESSED_RESULTS)
503508
}
504509

505510
/**
@@ -564,6 +569,26 @@ enum class TestSelectionStrategyType {
564569
COVERAGE_STRATEGY
565570
}
566571

572+
/**
573+
* Describes the behaviour if test generation is canceled.
574+
*/
575+
enum class CancellationStrategyType {
576+
/**
577+
* Do not react on cancellation
578+
*/
579+
NONE,
580+
581+
/**
582+
* Clear all generated test classes
583+
*/
584+
CANCEL_EVERYTHING,
585+
586+
/**
587+
* Show already processed test classes
588+
*/
589+
SAVE_PROCESSED_RESULTS
590+
}
591+
567592
/**
568593
* Enum to specify [MLSelector], see implementations for more details
569594
*/

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

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import com.intellij.ide.fileTemplates.FileTemplateUtil
88
import com.intellij.ide.fileTemplates.JavaTemplateUtil
99
import com.intellij.ide.highlighter.JavaFileType
1010
import com.intellij.openapi.application.ApplicationManager
11-
import com.intellij.openapi.application.readAction
1211
import com.intellij.openapi.application.runReadAction
1312
import com.intellij.openapi.application.runWriteAction
1413
import com.intellij.openapi.command.WriteCommandAction.runWriteCommandAction
@@ -42,18 +41,13 @@ import com.intellij.psi.codeStyle.JavaCodeStyleManager.DO_NOT_ADD_IMPORTS
4241
import com.intellij.psi.search.GlobalSearchScopesCore
4342
import com.intellij.testIntegration.TestIntegrationUtils
4443
import com.siyeh.ig.psiutils.ImportUtils
45-
import java.nio.file.Path
46-
import java.util.concurrent.CancellationException
47-
import java.util.concurrent.CountDownLatch
48-
import java.util.concurrent.TimeUnit
4944
import mu.KotlinLogging
5045
import org.jetbrains.kotlin.asJava.classes.KtUltraLightClass
5146
import org.jetbrains.kotlin.idea.KotlinFileType
5247
import org.jetbrains.kotlin.idea.core.ShortenReferences
5348
import org.jetbrains.kotlin.idea.core.getPackage
5449
import org.jetbrains.kotlin.idea.core.util.toPsiDirectory
5550
import org.jetbrains.kotlin.idea.util.ImportInsertHelperImpl
56-
import org.jetbrains.kotlin.idea.util.projectStructure.allModules
5751
import org.jetbrains.kotlin.name.FqName
5852
import org.jetbrains.kotlin.psi.KtClass
5953
import org.jetbrains.kotlin.psi.KtNamedFunction
@@ -64,6 +58,9 @@ import org.jetbrains.kotlin.psi.psiUtil.startOffset
6458
import org.utbot.common.FileUtil
6559
import org.utbot.common.HTML_LINE_SEPARATOR
6660
import org.utbot.common.PathUtil.toHtmlLinkTag
61+
import org.utbot.framework.CancellationStrategyType.CANCEL_EVERYTHING
62+
import org.utbot.framework.CancellationStrategyType.NONE
63+
import org.utbot.framework.CancellationStrategyType.SAVE_PROCESSED_RESULTS
6764
import org.utbot.framework.UtSettings
6865
import org.utbot.framework.codegen.domain.Import
6966
import org.utbot.framework.codegen.domain.ParametrizedTestSource
@@ -98,6 +95,10 @@ import org.utbot.intellij.plugin.util.assertIsWriteThread
9895
import org.utbot.intellij.plugin.util.extractClassMethodsIncludingNested
9996
import org.utbot.sarif.Sarif
10097
import org.utbot.sarif.SarifReport
98+
import java.nio.file.Path
99+
import java.util.concurrent.CancellationException
100+
import java.util.concurrent.CountDownLatch
101+
import java.util.concurrent.TimeUnit
101102

102103
object CodeGenerationController {
103104
private val logger = KotlinLogging.logger {}
@@ -114,7 +115,7 @@ object CodeGenerationController {
114115
model: GenerateTestsModel,
115116
classesWithTests: Map<PsiClass, RdTestGenerationResult>,
116117
psi2KClass: Map<PsiClass, ClassId>,
117-
proccess: EngineProcess,
118+
process: EngineProcess,
118119
indicator: ProgressIndicator
119120
) {
120121
assertIsDispatchThread()
@@ -127,7 +128,14 @@ object CodeGenerationController {
127128
val utilClassListener = UtilClassListener()
128129
var index = 0
129130
for ((srcClass, generateResult) in classesWithTests) {
130-
if (indicator.isCanceled) return
131+
if (indicator.isCanceled) {
132+
when (UtSettings.cancellationStrategyType) {
133+
NONE,
134+
SAVE_PROCESSED_RESULTS -> {}
135+
CANCEL_EVERYTHING -> break
136+
}
137+
}
138+
131139
val (count, testSetsId) = generateResult
132140
if (count <= 0) {
133141
latch.countDown()
@@ -143,7 +151,7 @@ object CodeGenerationController {
143151
val cut = psi2KClass[srcClass] ?: error("Didn't find KClass instance for class ${srcClass.name}")
144152
runWriteCommandAction(model.project, "Generate tests with UtBot", null, {
145153
generateCodeAndReport(
146-
proccess,
154+
process,
147155
testSetsId,
148156
srcClass,
149157
cut,
@@ -170,9 +178,9 @@ object CodeGenerationController {
170178
waitForCountDown(latch, indicator = indicator) {
171179
run(EDT_LATER, indicator,"Go to EDT for utility class creation") {
172180
run(WRITE_ACTION, indicator, "Need write action for utility class creation") {
173-
createUtilityClassIfNeed(utilClassListener, model, baseTestDirectory, indicator)
181+
createUtilityClassIfNeeded(utilClassListener, model, baseTestDirectory, indicator)
174182
run(THREAD_POOL, indicator, "Generate summary Sarif report") {
175-
proceedTestReport(proccess, model)
183+
proceedTestReport(process, model)
176184
val sarifReportsPath =
177185
model.testModule.getOrCreateSarifReportsPath(model.testSourceRoot)
178186
UtTestsDialogProcessor.updateIndicator(indicator, UtTestsDialogProcessor.ProgressRange.SARIF, "Merge Sarif reports", 0.75)
@@ -181,7 +189,7 @@ object CodeGenerationController {
181189
UtTestsDialogProcessor.updateIndicator(indicator, UtTestsDialogProcessor.ProgressRange.SARIF, "Start tests with coverage", 0.95)
182190
RunConfigurationHelper.runTestsWithCoverage(model, testFilesPointers)
183191
}
184-
proccess.terminate()
192+
process.terminate()
185193
UtTestsDialogProcessor.updateIndicator(indicator, UtTestsDialogProcessor.ProgressRange.SARIF, "Generation finished", 1.0)
186194

187195
run(EDT_LATER, null, "Run sarif-based inspections") {
@@ -232,7 +240,7 @@ object CodeGenerationController {
232240
)
233241
}
234242
}
235-
private fun createUtilityClassIfNeed(
243+
private fun createUtilityClassIfNeeded(
236244
utilClassListener: UtilClassListener,
237245
model: GenerateTestsModel,
238246
baseTestDirectory: PsiDirectory,

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

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,13 @@ import com.intellij.util.containers.nullize
2424
import com.intellij.util.io.exists
2525
import mu.KotlinLogging
2626
import org.jetbrains.kotlin.idea.util.module
27+
import org.utbot.framework.CancellationStrategyType.CANCEL_EVERYTHING
28+
import org.utbot.framework.CancellationStrategyType.NONE
29+
import org.utbot.framework.CancellationStrategyType.SAVE_PROCESSED_RESULTS
2730
import org.utbot.framework.UtSettings
2831
import org.utbot.framework.plugin.api.ClassId
2932
import org.utbot.framework.plugin.api.JavaDocCommentStyle
33+
import org.utbot.framework.plugin.api.util.LockFile
3034
import org.utbot.framework.plugin.api.util.withStaticsSubstitutionRequired
3135
import org.utbot.framework.plugin.services.JdkInfoService
3236
import org.utbot.framework.plugin.services.WorkingDirService
@@ -37,17 +41,20 @@ import org.utbot.intellij.plugin.process.EngineProcess
3741
import org.utbot.intellij.plugin.process.RdTestGenerationResult
3842
import org.utbot.intellij.plugin.settings.Settings
3943
import org.utbot.intellij.plugin.ui.GenerateTestsDialogWindow
44+
import org.utbot.intellij.plugin.ui.utils.isBuildWithGradle
4045
import org.utbot.intellij.plugin.ui.utils.showErrorDialogLater
4146
import org.utbot.intellij.plugin.ui.utils.testModules
42-
import org.utbot.intellij.plugin.util.*
47+
import org.utbot.intellij.plugin.util.IntelliJApiHelper
48+
import org.utbot.intellij.plugin.util.PluginJdkInfoProvider
49+
import org.utbot.intellij.plugin.util.PluginWorkingDirProvider
50+
import org.utbot.intellij.plugin.util.assertIsNonDispatchThread
51+
import org.utbot.intellij.plugin.util.extractClassMethodsIncludingNested
52+
import org.utbot.rd.terminateOnException
4353
import java.io.File
4454
import java.nio.file.Path
4555
import java.nio.file.Paths
4656
import java.util.concurrent.TimeUnit
4757
import kotlin.io.path.pathString
48-
import org.utbot.framework.plugin.api.util.LockFile
49-
import org.utbot.intellij.plugin.ui.utils.isBuildWithGradle
50-
import org.utbot.rd.terminateOnException
5158
import java.time.LocalDateTime
5259
import java.time.format.DateTimeFormatter
5360

@@ -176,6 +183,14 @@ object UtTestsDialogProcessor {
176183

177184

178185
for (srcClass in model.srcClasses) {
186+
if (indicator.isCanceled) {
187+
when (UtSettings.cancellationStrategyType) {
188+
NONE -> {}
189+
SAVE_PROCESSED_RESULTS,
190+
CANCEL_EVERYTHING -> break
191+
}
192+
}
193+
179194
val (methods, className) = DumbService.getInstance(project)
180195
.runReadActionInSmartMode(Computable {
181196
val canonicalName = srcClass.canonicalName

utbot-ui-commons/src/main/kotlin/org/utbot/intellij/plugin/util/IntelliJApiHelper.kt

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ import com.intellij.util.PlatformUtils
1212
import com.intellij.util.ReflectionUtil
1313
import com.intellij.util.concurrency.AppExecutorUtil
1414
import mu.KotlinLogging
15-
import org.jetbrains.kotlin.idea.util.application.invokeLater
15+
import org.utbot.framework.CancellationStrategyType.*
16+
import org.utbot.framework.UtSettings
1617

1718
/**
1819
* This object is required to encapsulate Android API usage and grant safe access to it.
@@ -24,10 +25,18 @@ object IntelliJApiHelper {
2425
fun run(target: Target, indicator: ProgressIndicator? = null, logMessage : String, runnable: Runnable) {
2526
logger.info { "[${target}]: " + logMessage +
2627
if (indicator != null) ", indicator[${indicator.text}; ${(indicator.fraction * 100).toInt()}%]" else "" }
27-
if (indicator != null && indicator.isCanceled) {
28-
logger.error { "Indicator is already cancelled" }
29-
return
28+
29+
if (indicator?.isCanceled == true) {
30+
when (UtSettings.cancellationStrategyType) {
31+
NONE,
32+
SAVE_PROCESSED_RESULTS -> {}
33+
CANCEL_EVERYTHING -> {
34+
logger.info { "Indicator is already cancelled" }
35+
return
36+
}
37+
}
3038
}
39+
3140
val wrapper = Runnable {
3241
try {
3342
runnable.run()

0 commit comments

Comments
 (0)