GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — IDE fatal error during tests generation #68 by Vassiliy-Kudryashov · Pull Request #379 · UnitTestBot/UTBotJava

IDE fatal error during tests generation #68 #379

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Sign up for GitHub

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Vassiliy-Kudryashov merged 2 commits into main from Vassiliy-Kudryashov/68-ide-fatal-error-during-tests-generation
Jul 4, 2022

Uh oh!

There was an error while loading. Please reload this page.

Merged

IDE fatal error during tests generation #68 #379

Changes from all commits
Commits
Show all changes
2 commits
Select commit Hold shift + click to select a range
7f8ab19
IDE fatal error during tests generation #68
Vassiliy-Kudryashov Jul 1, 2022
006ae08
IDE fatal error during tests generation #68
Vassiliy-Kudryashov Jul 4, 2022
File filter
Filter by extension

Clear filters
Conversations
Failed to load comments.
Loading

Uh oh!

There was an error while loading. Please reload this page.

Jump to
Jump to file
Failed to load files.
Loading

Uh oh!

There was an error while loading. Please reload this page.

Diff view
Diff view

There are no files selected for viewing

172 changes: 119 additions & 53 deletions 172 utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/TestGenerator.kt
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
@@ -1,11 +1,31 @@
package org.utbot.intellij.plugin.generator

import org.utbot.common.HTML_LINE_SEPARATOR
import org.utbot.common.PathUtil.classFqnToPath
import org.utbot.common.PathUtil.toHtmlLinkTag
import org.utbot.common.appendHtmlLine
import org.utbot.framework.codegen.Import
import org.utbot.framework.codegen.ParametrizedTestSource
import org.utbot.framework.codegen.StaticImport
import org.utbot.framework.codegen.TestsCodeWithTestReport
import org.utbot.framework.codegen.model.ModelBasedTestCodeGenerator
import org.utbot.framework.codegen.model.constructor.tree.TestsGenerationReport
import org.utbot.framework.plugin.api.CodegenLanguage
import org.utbot.framework.plugin.api.UtTestCase
import org.utbot.intellij.plugin.sarif.SarifReportIdea
import org.utbot.intellij.plugin.sarif.SourceFindingStrategyIdea
import org.utbot.intellij.plugin.settings.Settings
import org.utbot.intellij.plugin.ui.utils.getOrCreateSarifReportsPath
import org.utbot.intellij.plugin.ui.utils.getOrCreateTestResourcesPath
import org.utbot.sarif.SarifReport
import com.intellij.codeInsight.CodeInsightUtil
import com.intellij.codeInsight.FileModificationService
import com.intellij.ide.fileTemplates.FileTemplateManager
import com.intellij.ide.fileTemplates.FileTemplateUtil
import com.intellij.ide.fileTemplates.JavaTemplateUtil
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.runReadAction
import com.intellij.openapi.application.runWriteAction
import com.intellij.openapi.command.WriteCommandAction.runWriteCommandAction
import com.intellij.openapi.command.executeCommand
import com.intellij.openapi.components.service
Expand All @@ -21,51 +41,59 @@ import com.intellij.psi.codeStyle.JavaCodeStyleManager
import com.intellij.psi.search.GlobalSearchScopesCore
import com.intellij.testIntegration.TestIntegrationUtils
import com.intellij.util.IncorrectOperationException
import com.intellij.util.concurrency.AppExecutorUtil
import com.intellij.util.io.exists
import com.siyeh.ig.psiutils.ImportUtils
import java.nio.file.Path
import java.nio.file.Paths
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
import org.jetbrains.kotlin.asJava.classes.KtUltraLightClass
import org.jetbrains.kotlin.idea.core.ShortenReferences
import org.jetbrains.kotlin.idea.core.getPackage
import org.jetbrains.kotlin.idea.core.util.toPsiDirectory
import org.jetbrains.kotlin.idea.util.ImportInsertHelperImpl
import org.jetbrains.kotlin.idea.util.application.invokeLater
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.scripting.resolve.classId
import org.utbot.common.HTML_LINE_SEPARATOR
import org.utbot.common.PathUtil.classFqnToPath
import org.utbot.common.PathUtil.toHtmlLinkTag
import org.utbot.common.appendHtmlLine
import org.utbot.framework.codegen.Import
import org.utbot.framework.codegen.ParametrizedTestSource
import org.utbot.framework.codegen.StaticImport
import org.utbot.framework.codegen.TestsCodeWithTestReport
import org.utbot.framework.codegen.model.ModelBasedTestCodeGenerator
import org.utbot.framework.codegen.model.constructor.tree.TestsGenerationReport
import org.utbot.framework.plugin.api.CodegenLanguage
import org.utbot.framework.plugin.api.UtTestCase
import org.utbot.framework.plugin.api.util.UtContext
import org.utbot.framework.plugin.api.util.withUtContext
import org.utbot.intellij.plugin.error.showErrorDialogLater
import org.utbot.intellij.plugin.sarif.SarifReportIdea
import org.utbot.intellij.plugin.sarif.SourceFindingStrategyIdea
import org.utbot.intellij.plugin.settings.Settings
import org.utbot.intellij.plugin.ui.*
import org.utbot.intellij.plugin.ui.utils.getOrCreateSarifReportsPath
import org.utbot.intellij.plugin.ui.utils.getOrCreateTestResourcesPath
import org.utbot.sarif.SarifReport
import java.nio.file.Paths
import org.utbot.intellij.plugin.generator.TestGenerator.Target.*
import org.utbot.intellij.plugin.ui.GenerateTestsModel
import org.utbot.intellij.plugin.ui.SarifReportNotifier
import org.utbot.intellij.plugin.ui.TestReportUrlOpeningListener
import org.utbot.intellij.plugin.ui.TestsReportNotifier
import org.utbot.intellij.plugin.ui.packageName

object TestGenerator {
fun generateTests(model: GenerateTestsModel, testCases: Map<PsiClass, List<UtTestCase>>) {
generateTestsInternal(model, testCases)
private enum class Target {THREAD_POOL, READ_ACTION, WRITE_ACTION, EDT_LATER}

private fun run(target: Target, runnable: Runnable) {
UtContext.currentContext()?.let {
when (target) {
THREAD_POOL -> AppExecutorUtil.getAppExecutorService().submit {
withUtContext(it) {
runnable.run()
}
}
READ_ACTION -> runReadAction { withUtContext(it) { runnable.run() } }
WRITE_ACTION -> runWriteAction { withUtContext(it) { runnable.run() } }
EDT_LATER -> invokeLater { withUtContext(it) { runnable.run() } }
}
} ?: error("No context in thread ${Thread.currentThread()}")
}

private fun generateTestsInternal(model: GenerateTestsModel, testCasesByClass: Map<PsiClass, List<UtTestCase>>) {
fun generateTests(model: GenerateTestsModel, testCasesByClass: Map<PsiClass, List<UtTestCase>>) {
val baseTestDirectory = model.testSourceRoot?.toPsiDirectory(model.project)
?: return
val allTestPackages = getPackageDirectories(baseTestDirectory)
val latch = CountDownLatch(testCasesByClass.size)

for (srcClass in testCasesByClass.keys) {
val testCases = testCasesByClass[srcClass] ?: continue
Expand All @@ -75,20 +103,37 @@ object TestGenerator {
val testDirectory = allTestPackages[classPackageName] ?: baseTestDirectory
val testClass = createTestClass(srcClass, testDirectory, model) ?: continue
val file = testClass.containingFile

runWriteCommandAction(model.project, "Generate tests with UtBot", null, {
addTestMethodsAndSaveReports(testClass, file, testCases, model)
try {
addTestMethodsAndSaveReports(testClass, file, testCases, model, latch)
} catch (e: IncorrectOperationException) {
showCreatingClassError(model.project, createTestClassName(srcClass))
}
})
} catch (e: IncorrectOperationException) {
showCreatingClassError(model.project, createTestClassName(srcClass))
}
}
run(READ_ACTION) {
val sarifReportsPath = model.testModule.getOrCreateSarifReportsPath(model.testSourceRoot)
run(THREAD_POOL) {
waitForCountDown(latch, model, sarifReportsPath)
}
}
}

mergeSarifReports(model)
private fun waitForCountDown(latch: CountDownLatch, model: GenerateTestsModel, sarifReportsPath : Path) {
try {
if (!latch.await(5, TimeUnit.SECONDS)) {
run(THREAD_POOL) { waitForCountDown(latch, model, sarifReportsPath) }
} else {
mergeSarifReports(model, sarifReportsPath)
}
} catch (ignored: InterruptedException) {
}
}

private fun mergeSarifReports(model: GenerateTestsModel) {
val sarifReportsPath = model.testModule.getOrCreateSarifReportsPath(model.testSourceRoot)
private fun mergeSarifReports(model: GenerateTestsModel, sarifReportsPath : Path) {
val sarifReports = sarifReportsPath.toFile()
.walkTopDown()
.filter { it.extension == "sarif" }
Expand Down Expand Up @@ -175,6 +220,7 @@ object TestGenerator {
file: PsiFile,
testCases: List<UtTestCase>,
model: GenerateTestsModel,
reportsCountDown: CountDownLatch,
) {
val selectedMethods = TestIntegrationUtils.extractClassMethods(testClass, false)
val testFramework = model.testFramework
Expand Down Expand Up @@ -205,33 +251,50 @@ object TestGenerator {
when (generator) {
is ModelBasedTestCodeGenerator -> {
val editor = CodeInsightUtil.positionCursorAtLBrace(testClass.project, file, testClass)
val testsCodeWithTestReport = generator.generateAsStringWithTestReport(testCases)
val generatedTestsCode = testsCodeWithTestReport.generatedCode
//TODO Use PsiDocumentManager.getInstance(model.project).getDocument(file)
// if we don't want to open _all_ new files with tests in editor one-by-one
run(THREAD_POOL) {
val testsCodeWithTestReport = generator.generateAsStringWithTestReport(testCases)
val generatedTestsCode = testsCodeWithTestReport.generatedCode
run(EDT_LATER) {
run(WRITE_ACTION) {
unblockDocument(testClass.project, editor.document)
// TODO: JIRA:1246 - display warnings if we rewrite the file
executeCommand(testClass.project, "Insert Generated Tests") {
editor.document.setText(generatedTestsCode)
}
unblockDocument(testClass.project, editor.document)

// after committing the document the `testClass` is invalid in PsiTree,
// so we have to reload it from the corresponding `file`
val testClassUpdated = (file as PsiClassOwner).classes.first() // only one class in the file

// reformatting before creating reports due to
// SarifReport requires the final version of the generated tests code
runWriteCommandAction(testClassUpdated.project, "UtBot tests reformatting", null, {
reformat(model, file, testClassUpdated)
})
unblockDocument(testClassUpdated.project, editor.document)

// uploading formatted code
val testsCodeWithTestReportFormatted =
testsCodeWithTestReport.copy(generatedCode = file.text)

// creating and saving reports
saveSarifAndTestReports(
testClassUpdated,
testCases,
model,
testsCodeWithTestReportFormatted,
reportsCountDown
)

unblockDocument(testClass.project, editor.document)
// TODO: JIRA:1246 - display warnings if we rewrite the file
executeCommand(testClass.project, "Insert Generated Tests") {
editor.document.setText(generatedTestsCode)
unblockDocument(testClassUpdated.project, editor.document)
}
}
}
unblockDocument(testClass.project, editor.document)

// after committing the document the `testClass` is invalid in PsiTree,
// so we have to reload it from the corresponding `file`
val testClassUpdated = (file as PsiClassOwner).classes.first() // only one class in the file

// reformatting before creating reports due to
// SarifReport requires the final version of the generated tests code
reformat(model, file, testClassUpdated)
unblockDocument(testClassUpdated.project, editor.document)

// uploading formatted code
val testsCodeWithTestReportFormatted = testsCodeWithTestReport.copy(generatedCode = file.text)

// creating and saving reports
saveSarifAndTestReports(testClassUpdated, testCases, model, testsCodeWithTestReportFormatted)

unblockDocument(testClassUpdated.project, editor.document)
}
//Note that reportsCountDown.countDown() has to be called in every generator implementation to complete whole process
else -> TODO("Only model based code generator supported, but got: ${generator::class}")
}
}
Expand All @@ -257,7 +320,8 @@ object TestGenerator {
testClass: PsiClass,
testCases: List<UtTestCase>,
model: GenerateTestsModel,
testsCodeWithTestReport: TestsCodeWithTestReport
testsCodeWithTestReport: TestsCodeWithTestReport,
reportsCountDown: CountDownLatch
) {
val project = model.project
val generatedTestsCode = testsCodeWithTestReport.generatedCode
Expand All @@ -274,6 +338,8 @@ object TestGenerator {
message = "Cannot save Sarif report via generated tests: error occurred '${e.message}'",
title = "Failed to save Sarif report"
)
} finally {
reportsCountDown.countDown()
Comment thread
Vassiliy-Kudryashov marked this conversation as resolved.
Resolved

Uh oh!

There was an error while loading. Please reload this page.

}

try {
Expand Down
Add this suggestion to a batch that can be applied as a single commit. This suggestion is invalid because no changes were made to the code. Suggestions cannot be applied while the pull request is closed. Suggestions cannot be applied while viewing a subset of changes. Only one suggestion per line can be applied in a batch. Add this suggestion to a batch that can be applied as a single commit. Applying suggestions on deleted lines is not supported. You must change the existing code in this line in order to create a valid suggestion. Outdated suggestions cannot be applied. This suggestion has been applied or marked resolved. Suggestions cannot be applied from pending reviews. Suggestions cannot be applied on multi-line comments. Suggestions cannot be applied while the pull request is queued to merge. Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.