diff --git a/clion-plugin/build.gradle.kts b/clion-plugin/build.gradle.kts index 390b0dc18..3a1ee65fe 100644 --- a/clion-plugin/build.gradle.kts +++ b/clion-plugin/build.gradle.kts @@ -35,7 +35,7 @@ plugins { // Java support id("java") // Kotlin support - id("org.jetbrains.kotlin.jvm") version "1.6.10" + id("org.jetbrains.kotlin.jvm") version "1.7.20" // Gradle IntelliJ Plugin id("org.jetbrains.intellij") version "1.5.2" // Gradle Changelog Plugin @@ -91,11 +91,11 @@ detekt { allRules = false // activate all available (even unstable) rules. } -//kotlin { -// jvmToolchain { -// (this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(11)) -// } -//} +kotlin { + jvmToolchain { + (this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(11)) + } +} protobuf { protoc { @@ -194,7 +194,7 @@ tasks { setScanForTestClasses(false) // Only run tests from classes that end with "Test" include("**/*Test.class") - exclude("**/*BaseGenerationTestCaseTest.class") + exclude("**/*BaseGenerationTestCaseTest.class", "**/*BaseBuildingTest.class") systemProperty("idea.log.debug.categories", true) systemProperty("idea.log.trace.categories", true) diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/UTBotStartupActivity.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/UTBotStartupActivity.kt index 842964ab3..20ea648e7 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/UTBotStartupActivity.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/UTBotStartupActivity.kt @@ -4,6 +4,7 @@ import com.intellij.ide.util.RunOnceUtil import com.intellij.openapi.components.service import com.intellij.openapi.project.Project import com.intellij.openapi.startup.StartupActivity +import org.tinylog.kotlin.Logger import org.utbot.cpp.clion.plugin.client.ManagedClient import org.utbot.cpp.clion.plugin.settings.settings @@ -12,6 +13,7 @@ class UTBotStartupActivity : StartupActivity { // We initialize Client here, so that initialization will not happen // when user issues first generation request which would cause a UI freeze. if (project.settings.storedSettings.isPluginEnabled) { + Logger.info("startup activity is run: Initializing client") initializeClient(project) guessPathsOnFirstOpen(project) } diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/AskServerToGenerateBuildDir.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/AskServerToGenerateBuildDir.kt index adf9fca84..c5a6dd947 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/AskServerToGenerateBuildDir.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/AskServerToGenerateBuildDir.kt @@ -3,10 +3,18 @@ package org.utbot.cpp.clion.plugin.actions import com.intellij.openapi.actionSystem.AnActionEvent import org.utbot.cpp.clion.plugin.UTBot import org.utbot.cpp.clion.plugin.client.requests.CreateBuildDirRequest +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilderFactory +import org.utbot.cpp.clion.plugin.utils.activeProject +import org.utbot.cpp.clion.plugin.utils.client +import testsgen.Testgen class AskServerToGenerateBuildDir : UTBotBaseAction(UTBot.message("projectConfigure.generate.buildDir")) { - override fun actionPerformed(e: AnActionEvent) = CreateBuildDirRequest(e).execute() + override fun actionPerformed(e: AnActionEvent) = CreateBuildDirRequest( + GrpcRequestBuilderFactory(e.activeProject()).createProjectConfigRequestBuilder(Testgen.ConfigMode.CREATE_BUILD_DIR), + e.activeProject(), + e.activeProject().client + ).execute() override fun updateIfEnabled(e: AnActionEvent) { e.presentation.isEnabledAndVisible = e.project != null diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/RefreshTargetsAction.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/RefreshTargetsAction.kt index 758146de9..e94eea22f 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/RefreshTargetsAction.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/RefreshTargetsAction.kt @@ -1,7 +1,6 @@ package org.utbot.cpp.clion.plugin.actions import com.intellij.icons.AllIcons -import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.components.service import org.utbot.cpp.clion.plugin.ui.utbotToolWindow.targetToolWindow.UTBotTargetsController @@ -16,4 +15,4 @@ class RefreshTargetsAction: UTBotBaseAction() { e.presentation.isEnabledAndVisible = e.project != null e.presentation.icon = AllIcons.Actions.Refresh } -} \ No newline at end of file +} diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/ShowSettings.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/ShowSettings.kt new file mode 100644 index 000000000..be74c0fe4 --- /dev/null +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/ShowSettings.kt @@ -0,0 +1,13 @@ +package org.utbot.cpp.clion.plugin.actions + +import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.options.ShowSettingsUtil +import com.intellij.openapi.project.DumbAwareAction +import org.utbot.cpp.clion.plugin.UTBot +import org.utbot.cpp.clion.plugin.settings.UTBotConfigurable + +class ShowSettingsAction : DumbAwareAction(UTBot.message("show.settings.text"))/*, LightEditCompatible*/ { + override fun actionPerformed(e: AnActionEvent) { + ShowSettingsUtil.getInstance().showSettingsDialog(e.project, UTBotConfigurable::class.java) + } +} diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/UTBotBaseToggleAction.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/UTBotBaseToggleAction.kt index f246f70cb..14779931c 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/UTBotBaseToggleAction.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/UTBotBaseToggleAction.kt @@ -20,4 +20,4 @@ abstract class UTBotBaseToggleAction( } abstract fun updateIfEnabled(e: AnActionEvent) -} \ No newline at end of file +} diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/configure/ConfigureProjectAction.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/configure/ConfigureProjectAction.kt index 24f8830fa..d40d03fff 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/configure/ConfigureProjectAction.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/configure/ConfigureProjectAction.kt @@ -4,11 +4,16 @@ import com.intellij.openapi.actionSystem.AnActionEvent import org.utbot.cpp.clion.plugin.UTBot import org.utbot.cpp.clion.plugin.actions.UTBotBaseAction import org.utbot.cpp.clion.plugin.client.requests.CheckProjectConfigurationRequest +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilderFactory import org.utbot.cpp.clion.plugin.utils.activeProject +import testsgen.Testgen class ConfigureProjectAction : UTBotBaseAction(UTBot.message("projectConfigure.configure")) { - override fun actionPerformed(e: AnActionEvent) = CheckProjectConfigurationRequest(e.activeProject()).execute() + override fun actionPerformed(e: AnActionEvent) = CheckProjectConfigurationRequest( + GrpcRequestBuilderFactory(e.activeProject()).createProjectConfigRequestBuilder(Testgen.ConfigMode.CHECK), + e.activeProject() + ).execute() override fun updateIfEnabled(e: AnActionEvent) { e.presentation.isEnabledAndVisible = e.project != null diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/configure/ReconfigureProjectAction.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/configure/ReconfigureProjectAction.kt index 4597ba27c..76230369c 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/configure/ReconfigureProjectAction.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/configure/ReconfigureProjectAction.kt @@ -2,9 +2,9 @@ package org.utbot.cpp.clion.plugin.actions.configure import com.intellij.openapi.actionSystem.AnActionEvent import org.utbot.cpp.clion.plugin.UTBot -import org.utbot.cpp.clion.plugin.actions.UTBotBaseAction -import org.utbot.cpp.clion.plugin.grpc.getProjectConfigGrpcRequest import org.utbot.cpp.clion.plugin.client.requests.CheckProjectConfigurationRequest +import org.utbot.cpp.clion.plugin.actions.UTBotBaseAction +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilderFactory import org.utbot.cpp.clion.plugin.utils.activeProject import testsgen.Testgen @@ -13,7 +13,7 @@ class ReconfigureProjectAction: UTBotBaseAction(UTBot.message("projectConfigure. override fun actionPerformed(e: AnActionEvent) { val project = e.activeProject() CheckProjectConfigurationRequest( - getProjectConfigGrpcRequest(project, Testgen.ConfigMode.ALL), + GrpcRequestBuilderFactory(project).createProjectConfigRequestBuilder(Testgen.ConfigMode.ALL), project, ).execute() } diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/BaseGenerateTestsAction.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/BaseGenerateTestsAction.kt index 38f435213..ee6dda971 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/BaseGenerateTestsAction.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/BaseGenerateTestsAction.kt @@ -2,6 +2,8 @@ package org.utbot.cpp.clion.plugin.actions.generate import com.intellij.openapi.actionSystem.AnActionEvent import org.utbot.cpp.clion.plugin.actions.UTBotBaseAction +import org.utbot.cpp.clion.plugin.client.ManagedClient +import org.utbot.cpp.clion.plugin.utils.activeProject import org.utbot.cpp.clion.plugin.utils.client abstract class BaseGenerateTestsAction : UTBotBaseAction() { @@ -10,7 +12,7 @@ abstract class BaseGenerateTestsAction : UTBotBaseAction() { val isDefined: Boolean = isDefined(e) e.presentation.isVisible = isDefined - e.presentation.isEnabled = isDefined && e.client.isServerAvailable() + e.presentation.isEnabled = isDefined && ManagedClient.isConnectedToServer(e.activeProject()) } /** diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForAssertionAction.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForAssertionAction.kt index 90fbf6908..3ee785f5d 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForAssertionAction.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForAssertionAction.kt @@ -3,13 +3,15 @@ package org.utbot.cpp.clion.plugin.actions.generate import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.CommonDataKeys import org.utbot.cpp.clion.plugin.client.requests.test.AssertionRequest -import org.utbot.cpp.clion.plugin.grpc.getAssertionGrpcRequest +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilderFactory import org.utbot.cpp.clion.plugin.utils.activeProject +import org.utbot.cpp.clion.plugin.utils.getFilePathUnsafe +import org.utbot.cpp.clion.plugin.utils.getLineNumberUnsafe class GenerateForAssertionAction : BaseGenerateTestsAction() { override fun actionPerformed(e: AnActionEvent) = AssertionRequest( - getAssertionGrpcRequest(e), + GrpcRequestBuilderFactory(e.activeProject()).createAssertionRequestBuilder(e.getLineNumberUnsafe(), e.getFilePathUnsafe()), e.activeProject(), ).execute() diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForClassAction.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForClassAction.kt index d3c62ba64..b537e578c 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForClassAction.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForClassAction.kt @@ -3,14 +3,16 @@ package org.utbot.cpp.clion.plugin.actions.generate import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.CommonDataKeys import org.utbot.cpp.clion.plugin.client.requests.test.ClassRequest -import org.utbot.cpp.clion.plugin.grpc.getClassGrpcRequest +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilderFactory import org.utbot.cpp.clion.plugin.utils.activeProject +import org.utbot.cpp.clion.plugin.utils.getFilePathUnsafe +import org.utbot.cpp.clion.plugin.utils.getLineNumberUnsafe import org.utbot.cpp.clion.plugin.utils.isCPPFileName class GenerateForClassAction : BaseGenerateTestsAction() { override fun actionPerformed(e: AnActionEvent) = ClassRequest( - getClassGrpcRequest(e), + GrpcRequestBuilderFactory(e.activeProject()).createClassRequestBuilder(e.getFilePathUnsafe(), e.getLineNumberUnsafe()), e.activeProject(), ).execute() diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForFileAction.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForFileAction.kt index 5e83fd354..cae75c646 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForFileAction.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForFileAction.kt @@ -3,14 +3,14 @@ package org.utbot.cpp.clion.plugin.actions.generate import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.CommonDataKeys import org.utbot.cpp.clion.plugin.client.requests.test.FileRequest -import org.utbot.cpp.clion.plugin.grpc.getFileGrpcRequest import org.utbot.cpp.clion.plugin.utils.activeProject +import org.utbot.cpp.clion.plugin.utils.getBuilderForFileRequest import org.utbot.cpp.clion.plugin.utils.isCPPorCFileName class GenerateForFileAction : BaseGenerateTestsAction() { override fun actionPerformed(e: AnActionEvent) = FileRequest( - getFileGrpcRequest(e), + e.getBuilderForFileRequest(), e.activeProject(), ).execute() diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForFolderAction.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForFolderAction.kt index b88a4bb04..da0b3c5fb 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForFolderAction.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForFolderAction.kt @@ -3,15 +3,16 @@ package org.utbot.cpp.clion.plugin.actions.generate import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.CommonDataKeys import org.utbot.cpp.clion.plugin.client.requests.test.FolderRequest -import org.utbot.cpp.clion.plugin.grpc.getFolderGrpcRequest +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilderFactory import org.utbot.cpp.clion.plugin.utils.activeProject +import org.utbot.cpp.clion.plugin.utils.getFilePathUnsafe class GenerateForFolderAction : BaseGenerateTestsAction() { override fun actionPerformed(e: AnActionEvent) = - FolderRequest( - getFolderGrpcRequest(e), - e.activeProject() - ).execute() + FolderRequest( + GrpcRequestBuilderFactory(e.activeProject()).createFolderRequestBuilder(e.getFilePathUnsafe()), + e.activeProject() + ).execute() override fun isDefined(e: AnActionEvent): Boolean { val project = e.project diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForFunctionAction.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForFunctionAction.kt index abd4c0dfe..08701a61f 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForFunctionAction.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForFunctionAction.kt @@ -3,16 +3,18 @@ package org.utbot.cpp.clion.plugin.actions.generate import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.CommonDataKeys import org.utbot.cpp.clion.plugin.client.requests.test.FunctionRequest -import org.utbot.cpp.clion.plugin.grpc.getFunctionGrpcRequest +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilderFactory import org.utbot.cpp.clion.plugin.utils.activeProject +import org.utbot.cpp.clion.plugin.utils.getFilePathUnsafe +import org.utbot.cpp.clion.plugin.utils.getLineNumberUnsafe class GenerateForFunctionAction : BaseGenerateTestsAction() { - - override fun actionPerformed(e: AnActionEvent) = + override fun actionPerformed(e: AnActionEvent) { FunctionRequest( - getFunctionGrpcRequest(e), + GrpcRequestBuilderFactory(e.activeProject()).createFunctionRequestBuilder(e.getFilePathUnsafe(), e.getLineNumberUnsafe()), e.activeProject() ).execute() + } override fun isDefined(e: AnActionEvent): Boolean { val project = e.project diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForLineAction.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForLineAction.kt index dd9b4c2db..5064522e4 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForLineAction.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForLineAction.kt @@ -3,15 +3,16 @@ package org.utbot.cpp.clion.plugin.actions.generate import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.CommonDataKeys import org.utbot.cpp.clion.plugin.client.requests.test.LineRequest -import org.utbot.cpp.clion.plugin.grpc.getLineGrpcRequest import org.utbot.cpp.clion.plugin.utils.activeProject +import org.utbot.cpp.clion.plugin.utils.getBuilderForLineRequest class GenerateForLineAction : BaseGenerateTestsAction() { - override fun actionPerformed(e: AnActionEvent) = + override fun actionPerformed(e: AnActionEvent) { LineRequest( - getLineGrpcRequest(e), + e.getBuilderForLineRequest(), e.activeProject(), ).execute() + } override fun isDefined(e: AnActionEvent): Boolean { val project = e.project diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForPredicateAction.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForPredicateAction.kt index e96487acc..7f0dba175 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForPredicateAction.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForPredicateAction.kt @@ -9,12 +9,14 @@ import com.intellij.ui.DocumentAdapter import com.intellij.ui.components.fields.ExtendableTextField import javax.swing.ListSelectionModel import javax.swing.event.DocumentEvent -import org.utbot.cpp.clion.plugin.grpc.getFunctionGrpcRequest -import org.utbot.cpp.clion.plugin.grpc.getPredicateGrpcRequest +import org.utbot.cpp.clion.plugin.UTBot import org.utbot.cpp.clion.plugin.client.requests.test.FunctionReturnTypeRequest import org.utbot.cpp.clion.plugin.client.requests.test.PredicateRequest +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilderFactory import org.utbot.cpp.clion.plugin.utils.activeProject import org.utbot.cpp.clion.plugin.utils.client +import org.utbot.cpp.clion.plugin.utils.getFilePathUnsafe +import org.utbot.cpp.clion.plugin.utils.getLineNumberUnsafe import org.utbot.cpp.clion.plugin.utils.invokeOnEdt import org.utbot.cpp.clion.plugin.utils.notifyError import testsgen.Util.ValidationType @@ -46,7 +48,13 @@ class GenerateForPredicateAction : BaseGenerateTestsAction() { // when we gathered all needed information for predicate request, assemble it and execute it. fun sendPredicateToServer(validationType: ValidationType, valueToCompare: String, comparisonOperator: String) = PredicateRequest( - getPredicateGrpcRequest(e, comparisonOperator, validationType, valueToCompare), + GrpcRequestBuilderFactory(e.activeProject()).createPredicateRequestBuilder( + comparisonOperator, + validationType, + valueToCompare, + e.getLineNumberUnsafe(), + e.getFilePathUnsafe() + ), e.activeProject() ).apply { e.client.executeRequest(this) @@ -65,6 +73,7 @@ class GenerateForPredicateAction : BaseGenerateTestsAction() { } ValidationType.UNSUPPORTED -> { notifyError( + UTBot.message("notify.title.error"), "Unsupported return type for \'Generate Tests With Prompted Result\' feature: \n" + "supported types are integers, booleans, characters, floats and strings" ) @@ -72,6 +81,7 @@ class GenerateForPredicateAction : BaseGenerateTestsAction() { } ValidationType.UNRECOGNIZED -> { notifyError( + UTBot.message("notify.title.error"), "Could not recognise return type for 'Generate Tests With Prompted Result' feature: \n" + "supported types are integers, booleans, characters, floats and strings" ) @@ -101,7 +111,7 @@ class GenerateForPredicateAction : BaseGenerateTestsAction() { } //ask server for return type FunctionReturnTypeRequest( - getFunctionGrpcRequest(e), + GrpcRequestBuilderFactory(e.activeProject()).createFunctionRequestBuilder(e.getFilePathUnsafe(), e.getLineNumberUnsafe()), e.activeProject(), ) { functionReturnType -> val validationType = functionReturnType.validationType diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForProjectAction.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForProjectAction.kt index 5655985e8..eb9dd859f 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForProjectAction.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForProjectAction.kt @@ -1,15 +1,15 @@ package org.utbot.cpp.clion.plugin.actions.generate import com.intellij.openapi.actionSystem.AnActionEvent -import org.utbot.cpp.clion.plugin.grpc.getProjectGrpcRequest import org.utbot.cpp.clion.plugin.client.requests.test.ProjectRequest +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilderFactory import org.utbot.cpp.clion.plugin.utils.activeProject import org.utbot.cpp.clion.plugin.utils.client class GenerateForProjectAction : BaseGenerateTestsAction() { override fun actionPerformed(e: AnActionEvent) { ProjectRequest( - getProjectGrpcRequest(e), + GrpcRequestBuilderFactory(e.activeProject()).createProjectRequestBuilder(), e.activeProject(), ).apply { e.client.executeRequest(this) diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForSnippetAction.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForSnippetAction.kt index b29e48e4f..c0dd0e2e1 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForSnippetAction.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/GenerateForSnippetAction.kt @@ -3,13 +3,14 @@ package org.utbot.cpp.clion.plugin.actions.generate import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.CommonDataKeys import org.utbot.cpp.clion.plugin.client.requests.test.SnippetRequest -import org.utbot.cpp.clion.plugin.grpc.getSnippetGrpcRequest +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilderFactory import org.utbot.cpp.clion.plugin.utils.activeProject +import org.utbot.cpp.clion.plugin.utils.getFilePathUnsafe class GenerateForSnippetAction : BaseGenerateTestsAction() { override fun actionPerformed(e: AnActionEvent) { SnippetRequest( - getSnippetGrpcRequest(e), + GrpcRequestBuilderFactory(e.activeProject()).createSnippetRequestBuilder(e.getFilePathUnsafe()), e.activeProject(), ).execute() } diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/RunAllTestsWithCoverageAction.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/RunAllTestsWithCoverageAction.kt index 203e6f58f..a77066535 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/RunAllTestsWithCoverageAction.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/RunAllTestsWithCoverageAction.kt @@ -2,10 +2,15 @@ package org.utbot.cpp.clion.plugin.actions.generate import com.intellij.openapi.actionSystem.AnActionEvent import org.utbot.cpp.clion.plugin.client.requests.RunAllTestsWithCoverageRequest +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilderFactory +import org.utbot.cpp.clion.plugin.utils.activeProject -class RunAllTestsWithCoverageAction: BaseGenerateTestsAction() { +class RunAllTestsWithCoverageAction : BaseGenerateTestsAction() { override fun actionPerformed(e: AnActionEvent) { - RunAllTestsWithCoverageRequest(e).execute() + RunAllTestsWithCoverageRequest( + GrpcRequestBuilderFactory(e.activeProject()).createCovAndResulstsRequestBuilder(null), + e.activeProject() + ).execute() } override fun isDefined(e: AnActionEvent): Boolean { diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/RunWithCoverageAction.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/RunWithCoverageAction.kt index 7f9219c23..e3be437b3 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/RunWithCoverageAction.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/generate/RunWithCoverageAction.kt @@ -5,8 +5,7 @@ import com.intellij.openapi.actionSystem.CommonDataKeys import com.intellij.openapi.diagnostic.Logger import com.intellij.psi.PsiElement import org.utbot.cpp.clion.plugin.client.requests.RunWithCoverageRequest -import org.utbot.cpp.clion.plugin.grpc.getCoverageAndResultsGrpcRequest -import org.utbot.cpp.clion.plugin.ui.testsResults.TestNameAndTestSuite +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilderFactory import org.utbot.cpp.clion.plugin.utils.activeProject @@ -14,14 +13,10 @@ class RunWithCoverageAction(val element: PsiElement) : BaseGenerateTestsAction() override fun actionPerformed(e: AnActionEvent) { logger.debug("Action RunWithCoverageAction was called") - val testArgs = TestNameAndTestSuite.create(element) - val suiteName = testArgs.suite - val testedMethodName = testArgs.name - val filePath = e.getRequiredData(CommonDataKeys.VIRTUAL_FILE).path val project = e.activeProject() RunWithCoverageRequest( - getCoverageAndResultsGrpcRequest(project, filePath, suiteName, testedMethodName), + GrpcRequestBuilderFactory(project).createCovAndResulstsRequestBuilder(element), project, ).execute() } diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/mark/BaseSourceFolderAction.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/mark/BaseSourceFolderAction.kt index ad2f2f756..91174182b 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/mark/BaseSourceFolderAction.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/actions/mark/BaseSourceFolderAction.kt @@ -9,4 +9,4 @@ abstract class BaseSourceFolderAction: UTBotBaseAction() { override fun updateIfEnabled(e: AnActionEvent) { e.presentation.isEnabledAndVisible = e.getData(ProxyProjectViewTree.UTBOT_DIRS) != null } -} \ No newline at end of file +} diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/Client.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/Client.kt index 82d723769..d8539da2d 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/Client.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/Client.kt @@ -1,7 +1,7 @@ package org.utbot.cpp.clion.plugin.client import com.intellij.openapi.Disposable -import com.intellij.util.messages.MessageBus +import com.intellij.openapi.project.Project import io.grpc.Status import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineName @@ -18,11 +18,16 @@ import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withTimeout import org.jetbrains.annotations.TestOnly import org.utbot.cpp.clion.plugin.UTBot +import org.utbot.cpp.clion.plugin.actions.ShowSettingsAction import org.utbot.cpp.clion.plugin.client.channels.LogChannel +import org.utbot.cpp.clion.plugin.grpc.IllegalPathException import org.utbot.cpp.clion.plugin.client.logger.ClientLogger import org.utbot.cpp.clion.plugin.listeners.ConnectionStatus import org.utbot.cpp.clion.plugin.listeners.UTBotEventsListener import org.utbot.cpp.clion.plugin.settings.projectIndependentSettings +import org.utbot.cpp.clion.plugin.utils.notifyError +import org.utbot.cpp.clion.plugin.utils.notifyInfo +import org.utbot.cpp.clion.plugin.utils.notifyNotConnected import org.utbot.cpp.clion.plugin.utils.notifyWarning import testsgen.Testgen @@ -33,12 +38,13 @@ class Client( clientId: String, private val logger: ClientLogger, private val loggingChannels: List, - private val messageBus: MessageBus + private val project: Project ) : Disposable, GrpcClient(projectIndependentSettings.port, projectIndependentSettings.serverName, clientId) { var connectionStatus = ConnectionStatus.INIT private set + private val messageBus = project.messageBus private var newClient = true var isDisposed = false private set @@ -71,7 +77,10 @@ class Client( if (isDisposed) { // if client is disposed, then connection settings were changed, and requests issued to this client // are no longer relevant, so we don't execute them - notifyWarning(UTBot.message("warning.reconnecting")) + notifyWarning( + UTBot.message("notify.warning.reconnecting.title"), + UTBot.message("notify.warning.reconnecting") + ) return } executeRequestImpl(request) @@ -82,7 +91,37 @@ class Client( try { request.execute(stub, coroutineContext[Job]) } catch (e: io.grpc.StatusException) { - handleGRPCStatusException(e, "Exception when executing server request") + val id = request.id + when (e.status.code) { + Status.UNAVAILABLE.code -> notifyNotConnected(project, port, serverName) + Status.UNKNOWN.code -> notifyError( + UTBot.message("notify.title.unknown.server.error"), // unknown server error + UTBot.message("notify.unknown.server.error"), + project + ) + Status.CANCELLED.code -> notifyError( + UTBot.message("notify.title.cancelled"), + UTBot.message("notify.cancelled", id, e.message ?: ""), + project + ) + Status.FAILED_PRECONDITION.code, Status.INTERNAL.code, Status.UNIMPLEMENTED.code, Status.INVALID_ARGUMENT.code -> notifyError( + UTBot.message("notify.title.error"), + UTBot.message("notify.request.failed", e.message ?: "", id), + project + ) + else -> notifyError( + UTBot.message("notify.title.error"), + e.message ?: "Corresponding exception's message is missing", + project + ) + } + } catch (e: IllegalPathException) { + notifyError( + UTBot.message("notify.bad.settings.title"), + UTBot.message("notify.bad.path", e.message ?: ""), + project, + ShowSettingsAction() + ) } } } @@ -101,7 +140,7 @@ class Client( logger.info { "Sending REGISTER CLIENT request, clientID == $clientId" } stub.registerClient(Testgen.RegisterClientRequest.newBuilder().setClientId(clientId).build()) } catch (e: io.grpc.StatusException) { - handleGRPCStatusException(e, "Register client request failed with grpc exception!") + logger.error { "${e.status}: ${e.message}" } } } } @@ -125,6 +164,7 @@ class Client( connectionStatus = ConnectionStatus.CONNECTED if (oldStatus != ConnectionStatus.CONNECTED) { + notifyInfo(UTBot.message("notify.connected.title"), UTBot.message("notify.connected", port, serverName)) logger.info { "Successfully connected to server!" } registerClient() } @@ -148,19 +188,13 @@ class Client( if (!messageBus.isDisposed) { val connectionChangedPublisher = messageBus.syncPublisher(UTBotEventsListener.CONNECTION_CHANGED_TOPIC) - if (oldStatus != ConnectionStatus.BROKEN) + if (oldStatus != ConnectionStatus.BROKEN) { + notifyNotConnected(project, port, serverName) connectionChangedPublisher.onConnectionChange(oldStatus, ConnectionStatus.BROKEN) + } } - handleGRPCStatusException(e, "Heartbeat failed with grpc io exception") - } - } - - private fun handleGRPCStatusException(e: io.grpc.StatusException, message: String) { - logger.error { "$message \n${e.message}" } - when (e.status) { - Status.UNAVAILABLE -> logger.error { "Server is unavailable: possibly it is shut down." } - Status.UNKNOWN -> logger.error { "Server threw an exception." } + logger.error { "Failed to ping the server. Status code: ${e.status.code}" } } } @@ -176,9 +210,11 @@ class Client( // should be used only in tests @TestOnly - fun waitForServerRequestsToFinish(timeout: Long = SERVER_TIMEOUT, - delayTime: Long = 1000L, - ifNotFinished: (List) -> Unit = {}) { + fun waitForServerRequestsToFinish( + timeout: Long = SERVER_TIMEOUT, + delayTime: Long = 1000L, + ifNotFinished: (List) -> Unit = {} + ) { runBlocking { withTimeout(timeout) { while (requestsCS.coroutineContext.job.children.toList().any()) { diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/ManagedClient.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/ManagedClient.kt index 31e17a856..fca3efa21 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/ManagedClient.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/ManagedClient.kt @@ -2,6 +2,7 @@ package org.utbot.cpp.clion.plugin.client import com.intellij.openapi.Disposable import com.intellij.openapi.components.Service +import com.intellij.openapi.components.serviceIfCreated import com.intellij.openapi.project.Project import com.intellij.openapi.util.Disposer import org.utbot.cpp.clion.plugin.client.channels.GTestLogChannelImpl @@ -12,7 +13,7 @@ import kotlinx.coroutines.Job import org.jetbrains.annotations.TestOnly import org.utbot.cpp.clion.plugin.client.Client.Companion.SERVER_TIMEOUT import org.utbot.cpp.clion.plugin.client.requests.CheckProjectConfigurationRequest -import org.utbot.cpp.clion.plugin.grpc.getProjectConfigGrpcRequest +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilderFactory import org.utbot.cpp.clion.plugin.listeners.ConnectionSettingsListener import org.utbot.cpp.clion.plugin.listeners.ConnectionStatus import org.utbot.cpp.clion.plugin.listeners.PluginActivationListener @@ -26,6 +27,7 @@ class ManagedClient(val project: Project) : Disposable { private val clientId = generateClientID() private val loggingChannels = listOf(GTestLogChannelImpl(project), ServerLogChannelImpl(project)) val isPluginEnabled: Boolean get() = project.settings.storedSettings.isPluginEnabled + // if plugin is disabled then Client is null private var client: Client? = if (isPluginEnabled) createNewClient() else null @@ -76,7 +78,7 @@ class ManagedClient(val project: Project) : Disposable { fun configureProject() { CheckProjectConfigurationRequest( - getProjectConfigGrpcRequest(project, Testgen.ConfigMode.CHECK), + GrpcRequestBuilderFactory(project).createProjectConfigRequestBuilder(Testgen.ConfigMode.CHECK), project, ).also { request -> client?.executeRequestIfNotDisposed(request) @@ -88,7 +90,7 @@ class ManagedClient(val project: Project) : Disposable { client = null } - private fun createNewClient(): Client = Client(clientId, project.logger, loggingChannels, project.messageBus) + private fun createNewClient(): Client = Client(clientId, project.logger, loggingChannels, project) private fun generateClientID(): String { fun createRandomSequence() = (1..RANDOM_SEQUENCE_LENGTH) @@ -107,6 +109,8 @@ class ManagedClient(val project: Project) : Disposable { } companion object { + fun isConnectedToServer(project: Project) = + project.serviceIfCreated()?.isServerAvailable() ?: false const val RANDOM_SEQUENCE_MAX_VALUE = 10 const val RANDOM_SEQUENCE_LENGTH = 5 } diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/Request.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/Request.kt index 3734f793f..e283618d0 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/Request.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/Request.kt @@ -14,4 +14,5 @@ interface Request { * request can't be completed, for example because user canceled it from UI. */ suspend fun execute(stub: TestsGenServiceGrpcKt.TestsGenServiceCoroutineStub, cancellationJob: Job?) + abstract val id: String } diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/channels/GTestLogChannelImpl.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/channels/GTestLogChannelImpl.kt index a2d4907e1..fc946883e 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/channels/GTestLogChannelImpl.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/channels/GTestLogChannelImpl.kt @@ -2,9 +2,9 @@ package org.utbot.cpp.clion.plugin.client.channels import com.intellij.openapi.components.service import com.intellij.openapi.project.Project +import getDummyGrpcRequest +import getLogChannelGrpcRequest import kotlinx.coroutines.flow.Flow -import org.utbot.cpp.clion.plugin.grpc.getDummyGrpcRequest -import org.utbot.cpp.clion.plugin.grpc.getLogChannelGrpcRequest import org.utbot.cpp.clion.plugin.ui.services.OutputProvider import org.utbot.cpp.clion.plugin.ui.utbotToolWindow.logsToolWindow.UTBotConsole import testsgen.Testgen diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/channels/LogChannelImpl.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/channels/LogChannelImpl.kt index 4ced8c471..c59aea6e3 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/channels/LogChannelImpl.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/channels/LogChannelImpl.kt @@ -18,12 +18,15 @@ abstract class LogChannelImpl(val project: Project) : LogChannel { abstract val name: String abstract val logLevel: String - val console: UTBotConsole by lazy { createConsole() } + // because this function is called asynchronously (we call it from invokeOnEdt which is async) + // it may be called when project is disposed or other services are disposed -- this is very unlikely in production + // but possible in tests, so we do nothing if this happens + private val console: UTBotConsole? by lazy { if (project.isDisposed) null else createConsole() } abstract suspend fun open(stub: TestsGenServiceGrpcKt.TestsGenServiceCoroutineStub): Flow abstract suspend fun close(stub: TestsGenServiceGrpcKt.TestsGenServiceCoroutineStub) - abstract fun createConsole(): UTBotConsole + abstract fun createConsole(): UTBotConsole? override fun toString(): String = name @@ -37,6 +40,6 @@ abstract class LogChannelImpl(val project: Project) : LogChannel { open(stub) .catch { cause -> logger.error { "Exception in log channel: $name \n$cause" } } - .collect { invokeOnEdt { console.info(it.message) } } + .collect { invokeOnEdt { console?.info(it.message) } } } } diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/channels/ServerLogChannelImpl.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/channels/ServerLogChannelImpl.kt index f85f6d402..6527b7b7a 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/channels/ServerLogChannelImpl.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/channels/ServerLogChannelImpl.kt @@ -2,9 +2,9 @@ package org.utbot.cpp.clion.plugin.client.channels import com.intellij.openapi.components.service import com.intellij.openapi.project.Project +import getDummyGrpcRequest +import getLogChannelGrpcRequest import kotlinx.coroutines.flow.Flow -import org.utbot.cpp.clion.plugin.grpc.getDummyGrpcRequest -import org.utbot.cpp.clion.plugin.grpc.getLogChannelGrpcRequest import org.utbot.cpp.clion.plugin.ui.services.OutputProvider import org.utbot.cpp.clion.plugin.ui.utbotToolWindow.logsToolWindow.UTBotConsole import testsgen.Testgen diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/handlers/CoverageAndResultsHandler.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/handlers/CoverageAndResultsHandler.kt index fa063a2a1..3fe2a987a 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/handlers/CoverageAndResultsHandler.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/handlers/CoverageAndResultsHandler.kt @@ -3,11 +3,13 @@ package org.utbot.cpp.clion.plugin.client.handlers import com.intellij.coverage.CoverageDataManager import com.intellij.coverage.CoverageEngine import com.intellij.coverage.CoverageRunner +import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.project.Project import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.withContext +import org.utbot.cpp.clion.plugin.UTBot import org.utbot.cpp.clion.plugin.actions.FocusAction import org.utbot.cpp.clion.plugin.coverage.Coverage import org.utbot.cpp.clion.plugin.coverage.UTBotCoverageEngine @@ -44,7 +46,11 @@ class CoverageAndResultsHandler( return } if (response.errorMessage.isNotEmpty()) { - notifyError(response.errorMessage, project) + notifyError( + UTBot.message("notify.title.error"), + response.errorMessage, + project + ) } data class CoverageCollector( @@ -96,6 +102,11 @@ class CoverageAndResultsHandler( } private fun notifyCoverageReceived() { - notifyInfo("Coverage received!", project, sourceFilePath?.let { FocusAction(it) }) + notifyInfo( + UTBot.message("notify.coverage.received.title"), + UTBot.message("notify.coverage.received"), + project, + sourceFilePath?.let { FocusAction(it) } + ) } } diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/handlers/ProjectConfigurationHandler.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/handlers/ProjectConfigurationHandler.kt index 9b255a8fc..0ed44042c 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/handlers/ProjectConfigurationHandler.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/handlers/ProjectConfigurationHandler.kt @@ -1,6 +1,7 @@ package org.utbot.cpp.clion.plugin.client.handlers import com.intellij.openapi.project.Project +import kotlin.io.path.name import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow import org.utbot.cpp.clion.plugin.UTBot @@ -8,13 +9,12 @@ import org.utbot.cpp.clion.plugin.actions.AskServerToGenerateBuildDir import org.utbot.cpp.clion.plugin.actions.AskServerToGenerateJsonForProjectConfiguration import org.utbot.cpp.clion.plugin.client.ManagedClient import org.utbot.cpp.clion.plugin.client.requests.CheckProjectConfigurationRequest -import org.utbot.cpp.clion.plugin.grpc.getProjectConfigGrpcRequest +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilderFactory import org.utbot.cpp.clion.plugin.settings.settings import org.utbot.cpp.clion.plugin.utils.logger import org.utbot.cpp.clion.plugin.utils.notifyError import org.utbot.cpp.clion.plugin.utils.notifyInfo import org.utbot.cpp.clion.plugin.utils.notifyUnknownResponse -import org.utbot.cpp.clion.plugin.utils.notifyWarning import org.utbot.cpp.clion.plugin.utils.markDirtyAndRefresh import testsgen.Testgen @@ -45,11 +45,12 @@ class CheckProjectConfigurationHandler( override fun handle(response: Testgen.ProjectConfigResponse) { when (response.type) { Testgen.ProjectConfigStatus.IS_OK -> { - notifyInfo("Project is configured!", project) + notifyInfo(UTBot.message("notify.title.configured"), UTBot.message("notify.configured"), project) } Testgen.ProjectConfigStatus.BUILD_DIR_NOT_FOUND -> { notifyError( - "Project build dir not found! ${response.message}", + UTBot.message("notify.title.missingBuildDir"), + UTBot.message("notify.missingBuildDir"), project, AskServerToGenerateBuildDir() ) @@ -58,7 +59,8 @@ class CheckProjectConfigurationHandler( val missingFileName = if (response.type == Testgen.ProjectConfigStatus.LINK_COMMANDS_JSON_NOT_FOUND) "link_commands.json" else "compile_commands.json" notifyError( - "Project is not configured properly: file $missingFileName is missed in the build directory", + UTBot.message("notify.title.notConfigured"), + UTBot.message("notify.missing.cdb.files", missingFileName), project, AskServerToGenerateJsonForProjectConfiguration(), ) @@ -66,7 +68,7 @@ class CheckProjectConfigurationHandler( Testgen.ProjectConfigStatus.BUILD_DIR_SAME_AS_PROJECT -> { val message = response.message logger.warn(message) - notifyWarning("$message ${UTBot.message("uri.wiki")}", project) + notifyError(UTBot.message("notify.title.error"), "$message ${UTBot.message("uri.wiki")}", project) } else -> notifyUnknownResponse(response, project) } @@ -82,15 +84,25 @@ class CreateBuildDirHandler( override fun handle(response: Testgen.ProjectConfigResponse) { when (response.type) { Testgen.ProjectConfigStatus.IS_OK -> { - notifyInfo("Build directory was created!", project) + notifyInfo( + UTBot.message("notify.build.dir.created.title"), + UTBot.message("notify.build.dir.created", project.settings.buildDirPath.name), + project + ) CheckProjectConfigurationRequest( - getProjectConfigGrpcRequest(project, Testgen.ConfigMode.CHECK), - project, - ).execute() + GrpcRequestBuilderFactory(project).createProjectConfigRequestBuilder(Testgen.ConfigMode.CHECK), + project + ).also { + client.executeRequest(it) + } } Testgen.ProjectConfigStatus.BUILD_DIR_CREATION_FAILED -> { - notifyError("Failed to create build directory! ${response.message}", project) + notifyError( + UTBot.message("notify.failed.to.create.build.dir.title"), + "", + project + ) } else -> notifyUnknownResponse(response, project) } @@ -106,10 +118,14 @@ class GenerateJsonHandler( ) : ProjectConfigResponseHandler(project, grpcStream, progressName, cancellationJob) { override fun handle(response: Testgen.ProjectConfigResponse) { when (response.type) { - Testgen.ProjectConfigStatus.IS_OK -> notifyInfo("Successfully configured project!", project) + Testgen.ProjectConfigStatus.IS_OK -> notifyInfo( + UTBot.message("notify.title.configured"), + UTBot.message("notify.configured"), + project + ) Testgen.ProjectConfigStatus.RUN_JSON_GENERATION_FAILED -> notifyError( - "UTBot tried to configure project, but failed with the " + - "following message: ${response.message}", project + UTBot.message("notify.title.notConfigured"), + response.message ) else -> notifyUnknownResponse(response, project) } diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/handlers/StreamHandler.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/handlers/StreamHandler.kt index b1985905f..659c5d3d2 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/handlers/StreamHandler.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/handlers/StreamHandler.kt @@ -5,15 +5,13 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.cancellable import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.onCompletion -import org.utbot.cpp.clion.plugin.utils.notifyError -import java.util.concurrent.CancellationException /** * Base class for handling stream of server responses */ abstract class StreamHandler( val project: Project, - val grpcStream: Flow, + private val grpcStream: Flow, ) : Handler { val logger = com.intellij.openapi.diagnostic.Logger.getInstance(this::class.java) @@ -37,12 +35,8 @@ abstract class StreamHandler( abstract fun onData(data: T) open fun onCompletion(exception: Throwable?) { - if (exception != null) { - logger.warn(exception.message) - if (exception !is CancellationException) { - exception.printStackTrace() - exception.message?.let { notifyError(it, project) } - } + exception?.let { + throw it } } diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/handlers/StreamHandlerWithProgress.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/handlers/StreamHandlerWithProgress.kt index 5e88ea76a..3ecfd6cde 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/handlers/StreamHandlerWithProgress.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/handlers/StreamHandlerWithProgress.kt @@ -17,7 +17,7 @@ abstract class StreamHandlerWithProgress( progressName: String, cancellationJob: Job ): StreamHandler(project, grpcStream) { - private val indicator = UTBotRequestProgressIndicator(progressName, cancellationJob, project) + protected val indicator = UTBotRequestProgressIndicator(progressName, cancellationJob, project) override fun onStart() { super.onStart() @@ -49,11 +49,11 @@ abstract class StreamHandlerWithProgress( abstract fun T.getProgress(): Util.Progress override fun onCompletion(exception: Throwable?) { - super.onCompletion(exception) + invokeOnEdt { + indicator.stopShowingProgressInUI() + } if (exception != null) { - invokeOnEdt { - indicator.stop() - } + throw exception } } } diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/handlers/TestsStreamHandler.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/handlers/TestsStreamHandler.kt index 2113ffd69..6129448f3 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/handlers/TestsStreamHandler.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/handlers/TestsStreamHandler.kt @@ -3,12 +3,14 @@ package org.utbot.cpp.clion.plugin.client.handlers import com.intellij.openapi.components.service import com.intellij.openapi.project.Project import com.intellij.util.io.exists +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow import org.utbot.cpp.clion.plugin.settings.settings import org.utbot.cpp.clion.plugin.ui.services.TestsResultsStorage import org.utbot.cpp.clion.plugin.utils.convertFromRemotePathIfNeeded import org.utbot.cpp.clion.plugin.utils.createFileWithText +import org.utbot.cpp.clion.plugin.utils.invokeOnEdt import org.utbot.cpp.clion.plugin.utils.isSarifReport import org.utbot.cpp.clion.plugin.utils.logger import org.utbot.cpp.clion.plugin.utils.markDirtyAndRefresh @@ -26,7 +28,6 @@ class TestsStreamHandler( progressName: String, cancellationJob: Job, private val onSuccess: (List) -> Unit = {}, - private val onError: (Throwable) -> Unit = {} ) : StreamHandlerWithProgress(project, grpcStream, progressName, cancellationJob) { private val myGeneratedTestFilesLocalFS: MutableList = mutableListOf() @@ -58,6 +59,17 @@ class TestsStreamHandler( markDirtyAndRefresh(project.nioPath) } + override fun onCompletion(exception: Throwable?) { + invokeOnEdt { + indicator.stopShowingProgressInUI() + } + if (exception != null && exception !is CancellationException) { + throw exception + } else if (exception !is CancellationException) { + onSuccess(myGeneratedTestFilesLocalFS) + } + } + private fun handleSarifReport(sarif: SourceCode) { backupPreviousClientSarifReport(sarif.localPath) createSourceCodeFiles(listOf(sarif), "sarif report") @@ -121,12 +133,4 @@ class TestsStreamHandler( Files.move(previousReportPaths, newPath) } } - - override fun onCompletion(exception: Throwable?) { - super.onCompletion(exception) - if (exception == null) - onSuccess(myGeneratedTestFilesLocalFS) - else - onError(exception) - } } diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/logger/ClientLogger.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/logger/ClientLogger.kt index 3e92b66ee..854cc6130 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/logger/ClientLogger.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/logger/ClientLogger.kt @@ -5,27 +5,31 @@ import com.intellij.openapi.components.Service import com.intellij.openapi.project.Project interface Logger { - fun info(message: String, depth: Int = 3) = log({ message }, LogLevel.INFO, depth) + fun info(message: String, depth: Int = DEFAULT_LOG_DEPTH) = log({ message }, LogLevel.INFO, depth) - fun warn(message: String, depth: Int = 3) = log({ message }, LogLevel.WARN, depth) + fun warn(message: String, depth: Int = DEFAULT_LOG_DEPTH) = log({ message }, LogLevel.WARN, depth) - fun error(message: String, depth: Int = 3) = log({ message }, LogLevel.ERROR, depth) + fun error(message: String, depth: Int = DEFAULT_LOG_DEPTH) = log({ message }, LogLevel.ERROR, depth) - fun debug(message: String, depth: Int = 3) = log({ message }, LogLevel.DEBUG, depth) + fun debug(message: String, depth: Int = DEFAULT_LOG_DEPTH) = log({ message }, LogLevel.DEBUG, depth) - fun trace(message: String, depth: Int = 3) = log({ message }, LogLevel.TRACE, depth) + fun trace(message: String, depth: Int = DEFAULT_LOG_DEPTH) = log({ message }, LogLevel.TRACE, depth) - fun info(depth: Int = 3, message: () -> String) = log(message, LogLevel.INFO, depth) + fun info(depth: Int = DEFAULT_LOG_DEPTH, message: () -> String) = log(message, LogLevel.INFO, depth) - fun warn(depth: Int = 3, message: () -> String) = log(message, LogLevel.WARN, depth) + fun warn(depth: Int = DEFAULT_LOG_DEPTH, message: () -> String) = log(message, LogLevel.WARN, depth) - fun error(depth: Int = 3, message: () -> String) = log(message, LogLevel.ERROR, depth) + fun error(depth: Int = DEFAULT_LOG_DEPTH, message: () -> String) = log(message, LogLevel.ERROR, depth) - fun debug(depth: Int = 3, message: () -> String) = log(message, LogLevel.DEBUG, depth) + fun debug(depth: Int = DEFAULT_LOG_DEPTH, message: () -> String) = log(message, LogLevel.DEBUG, depth) - fun trace(depth: Int = 3, message: () -> String) = log(message, LogLevel.TRACE, depth) + fun trace(depth: Int = DEFAULT_LOG_DEPTH, message: () -> String) = log(message, LogLevel.TRACE, depth) - fun log(messageSupplier: () -> (String), level: LogLevel, depth: Int = 3) + fun log(messageSupplier: () -> (String), level: LogLevel, depth: Int = DEFAULT_LOG_DEPTH) + + companion object { + const val DEFAULT_LOG_DEPTH = 4 + } } @Service diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/BaseRequest.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/BaseRequest.kt index 27137e223..79976bb56 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/BaseRequest.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/BaseRequest.kt @@ -3,6 +3,8 @@ package org.utbot.cpp.clion.plugin.client.requests import com.intellij.openapi.project.Project import kotlinx.coroutines.Job import org.utbot.cpp.clion.plugin.client.Request +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilder +import org.utbot.cpp.clion.plugin.grpc.RemoteMapping import org.utbot.cpp.clion.plugin.utils.client import org.utbot.cpp.clion.plugin.utils.logger import testsgen.TestsGenServiceGrpcKt.TestsGenServiceCoroutineStub @@ -11,11 +13,17 @@ import testsgen.TestsGenServiceGrpcKt.TestsGenServiceCoroutineStub * Base class for requests. * It sends a request of type [X] and handles the response of type [Y]. */ -abstract class BaseRequest(val request: X, val project: Project) : Request { +abstract class BaseRequest(val params: GrpcRequestBuilder, val project: Project) : Request { abstract val logMessage: String + val request: X by lazy { build() } // must not be accessed from this class constructor override fun toString(): String = logMessage + open fun build(): X { + val mapping = RemoteMapping(project) + return params.build(mapping) + } + override suspend fun execute(stub: TestsGenServiceCoroutineStub, cancellationJob: Job?) { project.logger.info { "$logMessage \n$request" } stub.send(cancellationJob).handle(cancellationJob) diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/CheckProjectConfigurationRequest.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/CheckProjectConfigurationRequest.kt index 9c6a47275..9dae62773 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/CheckProjectConfigurationRequest.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/CheckProjectConfigurationRequest.kt @@ -4,20 +4,19 @@ import com.intellij.openapi.project.Project import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow import org.utbot.cpp.clion.plugin.UTBot -import org.utbot.cpp.clion.plugin.grpc.getProjectConfigGrpcRequest import org.utbot.cpp.clion.plugin.client.handlers.CheckProjectConfigurationHandler +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilder import testsgen.Testgen import testsgen.TestsGenServiceGrpcKt class CheckProjectConfigurationRequest( - request: Testgen.ProjectConfigRequest, + params: GrpcRequestBuilder, project: Project, -): BaseRequest>(request, project) { +) : BaseRequest>(params, project) { + override val id: String = "Configure Project" override val logMessage: String = "Sending request to check project configuration." - constructor(project: Project): this(getProjectConfigGrpcRequest(project, Testgen.ConfigMode.CHECK), project) - override suspend fun TestsGenServiceGrpcKt.TestsGenServiceCoroutineStub.send(cancellationJob: Job?): Flow { return this.configureProject(request) } diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/CreateBuildFolderRequest.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/CreateBuildFolderRequest.kt index 0e24f5259..a8e720650 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/CreateBuildFolderRequest.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/CreateBuildFolderRequest.kt @@ -1,28 +1,23 @@ package org.utbot.cpp.clion.plugin.client.requests -import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.project.Project import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow import org.utbot.cpp.clion.plugin.UTBot import org.utbot.cpp.clion.plugin.client.ManagedClient -import org.utbot.cpp.clion.plugin.grpc.getProjectConfigGrpcRequest import org.utbot.cpp.clion.plugin.client.handlers.CreateBuildDirHandler -import org.utbot.cpp.clion.plugin.utils.activeProject -import org.utbot.cpp.clion.plugin.utils.client +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilder import testsgen.Testgen import testsgen.TestsGenServiceGrpcKt.TestsGenServiceCoroutineStub class CreateBuildDirRequest( - val client: ManagedClient, - request: Testgen.ProjectConfigRequest, -) : BaseRequest>(request, client.project) { + params: GrpcRequestBuilder, + project: Project, + val client: ManagedClient +) : BaseRequest>(params, project) { + override val id: String = "Create Build Directory" override val logMessage: String = "Sending request to check project configuration." - constructor(e: AnActionEvent) : this( - e.project?.client ?: error("project is null for event: $e"), - getProjectConfigGrpcRequest(e.activeProject(), Testgen.ConfigMode.CREATE_BUILD_DIR) - ) - override suspend fun TestsGenServiceCoroutineStub.send(cancellationJob: Job?): Flow = this.configureProject(request) diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/GenerateJsonFilesRequest.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/GenerateJsonFilesRequest.kt index a39e9f813..32c104753 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/GenerateJsonFilesRequest.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/GenerateJsonFilesRequest.kt @@ -5,20 +5,26 @@ import com.intellij.openapi.project.Project import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow import org.utbot.cpp.clion.plugin.UTBot -import org.utbot.cpp.clion.plugin.grpc.getProjectConfigGrpcRequest import org.utbot.cpp.clion.plugin.client.handlers.GenerateJsonHandler +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilder +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilderFactory import org.utbot.cpp.clion.plugin.utils.activeProject import testsgen.Testgen import testsgen.TestsGenServiceGrpcKt class GenerateJsonFilesRequest( - project: Project, - request: Testgen.ProjectConfigRequest, -): BaseRequest>(request, project) { + params: GrpcRequestBuilder, + project: Project +) : BaseRequest>(params, project) { + override val id: String = "Generate JSON Files" override val logMessage: String = "Sending request to check project configuration." - constructor(project: Project): this(project, getProjectConfigGrpcRequest(project, Testgen.ConfigMode.GENERATE_JSON_FILES)) - constructor(e: AnActionEvent): this(e.activeProject()) + constructor(project: Project) : this( + GrpcRequestBuilderFactory(project).createProjectConfigRequestBuilder(Testgen.ConfigMode.GENERATE_JSON_FILES), + project + ) + + constructor(e: AnActionEvent) : this(e.activeProject()) override suspend fun TestsGenServiceGrpcKt.TestsGenServiceCoroutineStub.send(cancellationJob: Job?): Flow { return this.configureProject(request) diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/ProjectTargetsRequest.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/ProjectTargetsRequest.kt index 3462855fe..5a20da2a4 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/ProjectTargetsRequest.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/ProjectTargetsRequest.kt @@ -2,16 +2,17 @@ package org.utbot.cpp.clion.plugin.client.requests import com.intellij.openapi.project.Project import kotlinx.coroutines.Job +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilder import testsgen.Testgen import testsgen.TestsGenServiceGrpcKt class ProjectTargetsRequest( + params: GrpcRequestBuilder, project: Project, - request: Testgen.ProjectTargetsRequest, val processTargets: suspend (Testgen.ProjectTargetsResponse)->Unit, val onError: suspend (Throwable) -> Unit -): BaseRequest(request, project) { - +): BaseRequest(params, project) { + override val id: String = "Get Project Targets" override val logMessage: String = "Sending request to get project targets" override suspend fun execute(stub: TestsGenServiceGrpcKt.TestsGenServiceCoroutineStub, cancellationJob: Job?) { diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/RunAllTestsWithCoverageRequest.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/RunAllTestsWithCoverageRequest.kt index 63757c130..6c8dcc839 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/RunAllTestsWithCoverageRequest.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/RunAllTestsWithCoverageRequest.kt @@ -1,26 +1,22 @@ package org.utbot.cpp.clion.plugin.client.requests -import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.project.Project import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow import org.utbot.cpp.clion.plugin.UTBot import org.utbot.cpp.clion.plugin.client.handlers.CoverageAndResultsHandler -import org.utbot.cpp.clion.plugin.grpc.getRunWithCoverageRequestForAllTests -import org.utbot.cpp.clion.plugin.utils.activeProject +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilder import testsgen.Testgen import testsgen.Testgen.CoverageAndResultsRequest import testsgen.TestsGenServiceGrpcKt class RunAllTestsWithCoverageRequest( - request: CoverageAndResultsRequest, + params: GrpcRequestBuilder, project: Project, -) : BaseRequest>(request, project) { - +) : BaseRequest>(params, project) { + override val id: String = "Run All Tests with Coverage" override val logMessage: String = "Sending request to get tests run results and coverage" - constructor(e: AnActionEvent) : this(getRunWithCoverageRequestForAllTests(e.activeProject()), e.activeProject()) - override suspend fun Flow.handle(cancellationJob: Job?) { if (cancellationJob?.isActive == true) { CoverageAndResultsHandler( diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/RunWithCoverageRequest.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/RunWithCoverageRequest.kt index 630049078..19f70f79c 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/RunWithCoverageRequest.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/RunWithCoverageRequest.kt @@ -5,6 +5,7 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow import org.utbot.cpp.clion.plugin.UTBot import org.utbot.cpp.clion.plugin.client.handlers.CoverageAndResultsHandler +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilder import org.utbot.cpp.clion.plugin.utils.convertFromRemotePathIfNeeded import org.utbot.cpp.clion.plugin.utils.testFilePathToSourceFilePath import testsgen.Testgen @@ -12,10 +13,10 @@ import testsgen.Testgen.CoverageAndResultsResponse import testsgen.TestsGenServiceGrpcKt.TestsGenServiceCoroutineStub class RunWithCoverageRequest( - request: Testgen.CoverageAndResultsRequest, + params: GrpcRequestBuilder, project: Project, -): BaseRequest>(request, project) { - +): BaseRequest>(params, project) { + override val id: String = "Run with Coverage" override val logMessage: String = "Sending request to get tests run results and coverage" override suspend fun Flow.handle(cancellationJob: Job?) { diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/AssertionRequest.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/AssertionRequest.kt index 7667dba53..d9161ff27 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/AssertionRequest.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/AssertionRequest.kt @@ -4,13 +4,15 @@ import com.intellij.openapi.project.Project import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow import org.utbot.cpp.clion.plugin.UTBot +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilder import testsgen.Testgen import testsgen.TestsGenServiceGrpcKt.TestsGenServiceCoroutineStub class AssertionRequest( - request: Testgen.AssertionRequest, - project: Project, -) : BaseTestsRequest(request, project, UTBot.message("requests.assertion.description.progress")) { + params: GrpcRequestBuilder, + project: Project +) : BaseTestsRequest(params, project, UTBot.message("requests.assertion.description.progress")) { + override val id: String = "Generate for Assertion" override val logMessage: String = "Sending request to generate tests for Assertion" override fun getInfoMessage(): String = "Tests for assertion are generated!" diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/BaseTestsRequest.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/BaseTestsRequest.kt index 8ecde326f..329c38b46 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/BaseTestsRequest.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/BaseTestsRequest.kt @@ -3,9 +3,11 @@ package org.utbot.cpp.clion.plugin.client.requests.test import com.intellij.openapi.project.Project import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow +import org.utbot.cpp.clion.plugin.UTBot import org.utbot.cpp.clion.plugin.actions.FocusAction import org.utbot.cpp.clion.plugin.client.handlers.TestsStreamHandler import org.utbot.cpp.clion.plugin.client.requests.BaseRequest +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilder import org.utbot.cpp.clion.plugin.utils.getLongestCommonPathFromRoot import org.utbot.cpp.clion.plugin.utils.isHeaderFile import org.utbot.cpp.clion.plugin.utils.isSarifReport @@ -18,10 +20,9 @@ import java.nio.file.Path * Base class for requests that handle a stream of [Testgen.TestsResponse]. * @param progressName - a name of a progress that user will see, when this request will be executing. */ -abstract class BaseTestsRequest(request: R, project: Project, private val progressName: String) : - BaseRequest>(request, project) { +abstract class BaseTestsRequest(params: GrpcRequestBuilder, project: Project, private val progressName: String) : + BaseRequest>(params, project) { val logger = project.logger - override suspend fun Flow.handle(cancellationJob: Job?) { if (cancellationJob?.isActive == true) { TestsStreamHandler( @@ -30,7 +31,6 @@ abstract class BaseTestsRequest(request: R, project: Project, private val pro progressName, cancellationJob, ::notifySuccess, - ::notifyError ).handle() } } @@ -43,10 +43,12 @@ abstract class BaseTestsRequest(request: R, project: Project, private val pro open fun getInfoMessage() = "Tests generated!" open fun notifySuccess(generatedTestFiles: List) { - notifyInfo(getInfoMessage(), project, getFocusTarget(generatedTestFiles)?.let { - FocusAction(it) - }) + notifyInfo( + UTBot.message("notify.tests.generated"), + getInfoMessage(), + project, + getFocusTarget(generatedTestFiles)?.let { + FocusAction(it) + }) } - - open fun notifyError(cause: Throwable) {} -} \ No newline at end of file +} diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/ClassRequest.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/ClassRequest.kt index 932acf81f..9ad1075b0 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/ClassRequest.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/ClassRequest.kt @@ -4,13 +4,15 @@ import com.intellij.openapi.project.Project import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow import org.utbot.cpp.clion.plugin.UTBot +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilder import testsgen.Testgen import testsgen.TestsGenServiceGrpcKt.TestsGenServiceCoroutineStub class ClassRequest( - request: Testgen.ClassRequest, + params: GrpcRequestBuilder, project: Project, -) : BaseTestsRequest(request, project, UTBot.message("requests.class.description.progress")) { +) : BaseTestsRequest(params, project, UTBot.message("requests.class.description.progress")) { + override val id: String = "Generate for Class" override val logMessage: String = "Sending request to generate tests for class" override fun getInfoMessage(): String = "Tests for class are generated!" diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/FileRequest.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/FileRequest.kt index 5c5921531..4e0a133bd 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/FileRequest.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/FileRequest.kt @@ -4,14 +4,16 @@ import com.intellij.openapi.project.Project import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow import org.utbot.cpp.clion.plugin.UTBot +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilder import org.utbot.cpp.clion.plugin.utils.fileNameOrNull import testsgen.Testgen import testsgen.TestsGenServiceGrpcKt.TestsGenServiceCoroutineStub class FileRequest( - request: Testgen.FileRequest, + params: GrpcRequestBuilder, project: Project, -) : BaseTestsRequest(request, project, UTBot.message("requests.file.description.progress")) { +) : BaseTestsRequest(params, project, UTBot.message("requests.file.description.progress")) { + override val id: String = "Generate for File" override val logMessage: String = "Sending request to generate tests for file" override fun getInfoMessage(): String = "Tests for file ${(request.filePath.fileNameOrNull()?.plus(" ")) ?: ""} are generated!" diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/FolderRequest.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/FolderRequest.kt index e5f4e24ab..32ad36644 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/FolderRequest.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/FolderRequest.kt @@ -4,14 +4,16 @@ import com.intellij.openapi.project.Project import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow import org.utbot.cpp.clion.plugin.UTBot +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilder import org.utbot.cpp.clion.plugin.utils.fileNameOrNull import testsgen.Testgen import testsgen.TestsGenServiceGrpcKt.TestsGenServiceCoroutineStub class FolderRequest( - request: Testgen.FolderRequest, + folderRequestParams: GrpcRequestBuilder, project: Project, -) : BaseTestsRequest(request, project, UTBot.message("requests.folder.description.progress")) { +) : BaseTestsRequest(folderRequestParams, project, UTBot.message("requests.folder.description.progress")) { + override val id: String = "Generate for Folder" override val logMessage: String = "Sending request to generate tests for folder." override fun getInfoMessage(): String = "Tests for folder ${request.folderPath.fileNameOrNull()?.plus(" ") ?: ""} are generated!" diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/FunctionRequest.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/FunctionRequest.kt index ec1d4ec3a..652a83620 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/FunctionRequest.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/FunctionRequest.kt @@ -4,13 +4,15 @@ import com.intellij.openapi.project.Project import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow import org.utbot.cpp.clion.plugin.UTBot +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilder import testsgen.Testgen import testsgen.TestsGenServiceGrpcKt.TestsGenServiceCoroutineStub class FunctionRequest( - request: Testgen.FunctionRequest, + params: GrpcRequestBuilder, project: Project, -) : BaseTestsRequest(request, project, UTBot.message("requests.function.description.progress")) { +) : BaseTestsRequest(params, project, UTBot.message("requests.function.description.progress")) { + override val id: String = "Generate for Function" override val logMessage: String = "Sending request to generate tests for function." override fun getInfoMessage(): String = "Tests for function are generated!" diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/FunctionReturnTypeRequest.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/FunctionReturnTypeRequest.kt index 2684518b7..b0ef39207 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/FunctionReturnTypeRequest.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/FunctionReturnTypeRequest.kt @@ -3,15 +3,17 @@ package org.utbot.cpp.clion.plugin.client.requests.test import com.intellij.openapi.project.Project import kotlinx.coroutines.Job import org.utbot.cpp.clion.plugin.client.requests.BaseRequest +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilder import testsgen.Testgen import testsgen.Testgen.FunctionTypeResponse import testsgen.TestsGenServiceGrpcKt.TestsGenServiceCoroutineStub class FunctionReturnTypeRequest( - request: Testgen.FunctionRequest, + params: GrpcRequestBuilder, project: Project, val processReturnType: suspend (FunctionTypeResponse)->(Unit) -) : BaseRequest(request, project) { +) : BaseRequest(params, project) { + override val id: String = "Get Function Return Type" override val logMessage: String = "Sending request to get function return type" diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/LineRequest.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/LineRequest.kt index eba6d6b0d..38b747542 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/LineRequest.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/LineRequest.kt @@ -4,13 +4,15 @@ import com.intellij.openapi.project.Project import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow import org.utbot.cpp.clion.plugin.UTBot +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilder import testsgen.Testgen import testsgen.TestsGenServiceGrpcKt.TestsGenServiceCoroutineStub class LineRequest( - request: Testgen.LineRequest, + params: GrpcRequestBuilder, project: Project, -) : BaseTestsRequest(request, project, UTBot.message("requests.line.description.progress")) { +) : BaseTestsRequest(params, project, UTBot.message("requests.line.description.progress")) { + override val id: String = "Generate for Line" override val logMessage: String = "Sending request to generate tests for line." override fun getInfoMessage(): String = "Tests for line are generated!" diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/PredicateRequest.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/PredicateRequest.kt index 392d36578..e6b10bceb 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/PredicateRequest.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/PredicateRequest.kt @@ -4,13 +4,15 @@ import com.intellij.openapi.project.Project import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow import org.utbot.cpp.clion.plugin.UTBot +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilder import testsgen.Testgen import testsgen.TestsGenServiceGrpcKt.TestsGenServiceCoroutineStub class PredicateRequest( - request: Testgen.PredicateRequest, + params: GrpcRequestBuilder, project: Project, -) : BaseTestsRequest(request, project, UTBot.message("requests.predicate.description.progress")) { +) : BaseTestsRequest(params, project, UTBot.message("requests.predicate.description.progress")) { + override val id: String = "Generate for Predicate" override val logMessage: String = "Sending request to generate tests for predicate" override fun getInfoMessage(): String = "Tests for predicate are generated!" diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/ProjectRequest.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/ProjectRequest.kt index db1e747b9..9c163f2d3 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/ProjectRequest.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/ProjectRequest.kt @@ -4,13 +4,15 @@ import com.intellij.openapi.project.Project import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow import org.utbot.cpp.clion.plugin.UTBot +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilder import testsgen.Testgen import testsgen.TestsGenServiceGrpcKt.TestsGenServiceCoroutineStub class ProjectRequest( - request: Testgen.ProjectRequest, + params: GrpcRequestBuilder, project: Project, -) : BaseTestsRequest(request, project, UTBot.message("requests.project.description.progress")) { +) : BaseTestsRequest(params, project, UTBot.message("requests.project.description.progress")) { + override val id: String = "Generate for Project" override val logMessage: String = "Sending request to generate tests for project" override fun getInfoMessage(): String = "Tests for project are generated!" diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/SnippetRequest.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/SnippetRequest.kt index 0be96a02b..ef3b8d865 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/SnippetRequest.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/requests/test/SnippetRequest.kt @@ -4,13 +4,15 @@ import com.intellij.openapi.project.Project import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow import org.utbot.cpp.clion.plugin.UTBot +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilder import testsgen.Testgen import testsgen.TestsGenServiceGrpcKt.TestsGenServiceCoroutineStub class SnippetRequest( - request: Testgen.SnippetRequest, + params: GrpcRequestBuilder, project: Project -) : BaseTestsRequest(request, project, UTBot.message("requests.snippet.description.progress")) { +) : BaseTestsRequest(params, project, UTBot.message("requests.snippet.description.progress")) { + override val id: String = "Generate for Snippet" override val logMessage: String = "Sending request to generate tests for snippet" override fun getInfoMessage(): String = "Tests for snippet are generated!" diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/coverage/UTBotCoverageEngine.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/coverage/UTBotCoverageEngine.kt index d485686e4..30dbe97de 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/coverage/UTBotCoverageEngine.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/coverage/UTBotCoverageEngine.kt @@ -10,7 +10,6 @@ import com.intellij.coverage.SimpleCoverageAnnotator import com.intellij.execution.configurations.RunConfigurationBase import com.intellij.execution.configurations.coverage.CoverageEnabledConfiguration import com.intellij.execution.testframework.AbstractTestProxy -import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.module.Module import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement @@ -25,8 +24,6 @@ import java.io.File * for additional docs @see [CoverageEngine] in IntelliJ Platform source code */ class UTBotCoverageEngine : CoverageEngine() { - private val log = Logger.getInstance(this::class.java) - /** * This method is not called, when the coverage is processed in CoverageDataManager#coverageGathered(suite). * diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/coverage/UTBotCoverageRunner.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/coverage/UTBotCoverageRunner.kt index 65813c612..87ea48076 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/coverage/UTBotCoverageRunner.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/coverage/UTBotCoverageRunner.kt @@ -12,7 +12,6 @@ import java.io.File import java.nio.charset.StandardCharsets import java.nio.file.Files import java.nio.file.Path -import java.nio.file.Paths /** * This class is used to convert from our representation of coverage to IntelliJ's [ProjectData] diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/coverage/UTBotCoverageSuite.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/coverage/UTBotCoverageSuite.kt index dd48157f9..f8eeb00c1 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/coverage/UTBotCoverageSuite.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/coverage/UTBotCoverageSuite.kt @@ -35,8 +35,8 @@ class UTBotCoverageSuite( coverageRunner, project ) { - val covEngine = coverageEngine - val covRunner = coverageRunner + private val covEngine = coverageEngine + private val covRunner = coverageRunner val coveragesList: List? = covLists override fun getCoverageEngine(): CoverageEngine { diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/grpc/ActionsGrpcRequests.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/grpc/ActionsGrpcRequests.kt deleted file mode 100644 index 5ca482342..000000000 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/grpc/ActionsGrpcRequests.kt +++ /dev/null @@ -1,123 +0,0 @@ -package org.utbot.cpp.clion.plugin.grpc - -import com.intellij.openapi.actionSystem.AnActionEvent -import com.intellij.openapi.actionSystem.CommonDataKeys -import com.intellij.openapi.project.Project -import org.utbot.cpp.clion.plugin.settings.settings -import org.utbot.cpp.clion.plugin.utils.activeProject -import org.utbot.cpp.clion.plugin.utils.convertToRemotePathIfNeeded -import testsgen.Testgen -import testsgen.Util - -fun getProjectGrpcRequest(e: AnActionEvent): Testgen.ProjectRequest = getProjectGrpcRequest(e.activeProject()) - -fun getFolderGrpcRequest(e: AnActionEvent): Testgen.FolderRequest { - val project = e.activeProject() - val localPath = e.getRequiredData(CommonDataKeys.VIRTUAL_FILE).path - - return Testgen.FolderRequest.newBuilder() - .setProjectRequest(getProjectGrpcRequest(e)) - .setFolderPath(localPath.convertToRemotePathIfNeeded(project)) - .build() -} - -fun getRunWithCoverageRequestForAllTests(project: Project): Testgen.CoverageAndResultsRequest = - Testgen.CoverageAndResultsRequest.newBuilder() - .setCoverage(true) - .setSettingsContext(getSettingsContextMessage(project)) - .setProjectContext(getProjectContextMessage(project)) - .build() - -fun getFileGrpcRequest(e: AnActionEvent): Testgen.FileRequest { - val project = e.activeProject() - val filePath = e.getRequiredData(CommonDataKeys.VIRTUAL_FILE).path - - return Testgen.FileRequest.newBuilder() - .setProjectRequest(getProjectGrpcRequest(project)) - .setFilePath(filePath.convertToRemotePathIfNeeded(project)) - .build() -} - -fun getClassGrpcRequest(e: AnActionEvent): Testgen.ClassRequest = Testgen.ClassRequest.newBuilder() - .setLineRequest(getLineGrpcRequest(e)) - .build() - -fun getFunctionGrpcRequest(e: AnActionEvent): Testgen.FunctionRequest { - val lineRequest = getLineGrpcRequest(e) - return Testgen.FunctionRequest.newBuilder() - .setLineRequest(lineRequest) - .build() -} - -fun getSnippetGrpcRequest(e: AnActionEvent): Testgen.SnippetRequest { - val project = e.activeProject() - val localPath = e.getRequiredData(CommonDataKeys.VIRTUAL_FILE).path - - return Testgen.SnippetRequest.newBuilder() - .setProjectContext(getProjectContextMessage(project)) - .setSettingsContext(getSettingsContextMessage(project)) - .setFilePath(localPath.convertToRemotePathIfNeeded(project)) - .build() -} - -fun getLineGrpcRequest(e: AnActionEvent): Testgen.LineRequest { - val project = e.getRequiredData(CommonDataKeys.PROJECT) - val filePath = e.getRequiredData(CommonDataKeys.VIRTUAL_FILE).path - val editor = e.getRequiredData(CommonDataKeys.EDITOR) - val lineNumber = editor.caretModel.logicalPosition.line + 1 - - return getLineGrpcRequest(project, lineNumber, filePath) -} - -fun getAssertionGrpcRequest(e: AnActionEvent): Testgen.AssertionRequest { - return Testgen.AssertionRequest.newBuilder() - .setLineRequest(getLineGrpcRequest(e)) - .build() -} - -fun getPredicateGrpcRequest( - e: AnActionEvent, - predicate: String, - validationType: Util.ValidationType, - returnValue: String, -): Testgen.PredicateRequest { - val predicateInfo = getPredicateGrpcRequest(predicate, returnValue, validationType) - return Testgen.PredicateRequest.newBuilder() - .setLineRequest(getLineGrpcRequest(e)) - .setPredicateInfo(predicateInfo) - .build() -} - -private fun getPredicateGrpcRequest( - predicate: String, - returnValue: String, - type: Util.ValidationType -): Util.PredicateInfo = - Util.PredicateInfo.newBuilder() - .setPredicate(predicate) - .setReturnValue(returnValue) - .setType(type) - .build() - -private fun getProjectGrpcRequest(project: Project): Testgen.ProjectRequest { - return Testgen.ProjectRequest.newBuilder() - .setSettingsContext(getSettingsContextMessage(project)) - .setProjectContext(getProjectContextMessage(project)) - .setTargetPath(project.settings.convertedTargetPath) - .addAllSourcePaths(project.settings.convertedSourcePaths) - .setSynchronizeCode(project.settings.isRemoteScenario) - .build() -} - - -private fun getLineGrpcRequest(project: Project, line: Int, filePath: String): Testgen.LineRequest = - Testgen.LineRequest.newBuilder() - .setProjectRequest(getProjectGrpcRequest(project)) - .setSourceInfo(getSourceInfo(project, line, filePath)) - .build() - -private fun getSourceInfo(project: Project, line: Int, filePath: String): Util.SourceInfo = - Util.SourceInfo.newBuilder() - .setLine(line) - .setFilePath(filePath.convertToRemotePathIfNeeded(project)) - .build() diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/grpc/ConfigurationGrpcRequests.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/grpc/ConfigurationGrpcRequests.kt index 488114b27..713719f19 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/grpc/ConfigurationGrpcRequests.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/grpc/ConfigurationGrpcRequests.kt @@ -1,32 +1,8 @@ -package org.utbot.cpp.clion.plugin.grpc - -import com.intellij.openapi.project.Project -import com.jetbrains.cidr.cpp.cmake.workspace.CMakeWorkspace import testsgen.Testgen -fun getProjectTargetsGrpcRequest(project: Project): Testgen.ProjectTargetsRequest = - Testgen.ProjectTargetsRequest.newBuilder() - .setProjectContext(getProjectContextMessage(project)) - .build() - -fun getProjectConfigGrpcRequest(project: Project, configMode: Testgen.ConfigMode): Testgen.ProjectConfigRequest { - val builder = Testgen.ProjectConfigRequest.newBuilder() - .setProjectContext(getProjectContextMessage(project)) - .setConfigMode(configMode) - getCmakeOptions(project)?.let { builder.setCmakeOptions(0, it) } - - return builder.build() -} - fun getDummyGrpcRequest(): Testgen.DummyRequest = Testgen.DummyRequest.newBuilder().build() fun getLogChannelGrpcRequest(logLevel: String): Testgen.LogChannelRequest = Testgen.LogChannelRequest.newBuilder() .setLogLevel(logLevel) - .build() - -private fun getCmakeOptions(project: Project): String? = - CMakeWorkspace.getInstance(project).profileInfos - .map { it.profile } - .firstOrNull { it.enabled } - ?.generationOptions \ No newline at end of file + .build() \ No newline at end of file diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/grpc/CoverageAndResultGrpcRequests.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/grpc/CoverageAndResultGrpcRequests.kt deleted file mode 100644 index 724925728..000000000 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/grpc/CoverageAndResultGrpcRequests.kt +++ /dev/null @@ -1,33 +0,0 @@ -package org.utbot.cpp.clion.plugin.grpc - -import com.intellij.openapi.project.Project -import org.utbot.cpp.clion.plugin.utils.convertToRemotePathIfNeeded -import testsgen.Testgen - -/** - * [testName] and [testSuiteName] are non-empty if a concrete test is specified. - * Request for several tests leaves these fields empty. - */ -fun getCoverageAndResultsGrpcRequest( - project: Project, - filePath: String, - testSuiteName: String = "", - testName: String = "", - includeCoverage: Boolean = true, -): Testgen.CoverageAndResultsRequest { - val remoteFilePath = filePath.convertToRemotePathIfNeeded(project) - - return Testgen.CoverageAndResultsRequest.newBuilder() - .setCoverage(includeCoverage) - .setProjectContext(getProjectContextMessage(project)) - .setSettingsContext(getSettingsContextMessage(project)) - .setTestFilter(getTestFilter(remoteFilePath, testName, testSuiteName)) - .build() -} - -private fun getTestFilter(filePath: String, testName: String = "", testSuiteName: String = ""): Testgen.TestFilter = - Testgen.TestFilter.newBuilder() - .setTestFilePath(filePath) - .setTestName(testName) - .setTestSuite(testSuiteName) - .build() diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/grpc/GrpcMessagingUtils.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/grpc/GrpcMessagingUtils.kt deleted file mode 100644 index 3f7705b64..000000000 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/grpc/GrpcMessagingUtils.kt +++ /dev/null @@ -1,24 +0,0 @@ -package org.utbot.cpp.clion.plugin.grpc - -import com.intellij.openapi.project.Project -import org.utbot.cpp.clion.plugin.settings.settings -import testsgen.Testgen - -fun getSettingsContextMessage(project: Project): Testgen.SettingsContext { - val storedSettings = project.settings.storedSettings - return Testgen.SettingsContext.newBuilder() - .setVerbose(storedSettings.verbose) - .setUseStubs(storedSettings.useStubs) - .setTimeoutPerTest(storedSettings.timeoutPerTest) - .setTimeoutPerFunction(storedSettings.timeoutPerFunction) - .setGenerateForStaticFunctions(storedSettings.generateForStaticFunctions) - .setUseDeterministicSearcher(storedSettings.useDeterministicSearcher) - .build() -} - -fun getProjectContextMessage(project: Project): Testgen.ProjectContext = Testgen.ProjectContext.newBuilder() - .setProjectName(project.name) - .setProjectPath(project.settings.convertedProjectPath) - .setBuildDirRelativePath(project.settings.storedSettings.buildDirRelativePath) - .setTestDirPath(project.settings.convertedTestDirPath) - .build() \ No newline at end of file diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/grpc/GrpcRequestBuilder.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/grpc/GrpcRequestBuilder.kt new file mode 100644 index 000000000..39c458f7c --- /dev/null +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/grpc/GrpcRequestBuilder.kt @@ -0,0 +1,48 @@ +package org.utbot.cpp.clion.plugin.grpc + +import com.intellij.openapi.project.Project +import org.apache.commons.io.FilenameUtils +import org.utbot.cpp.clion.plugin.UTBot +import org.utbot.cpp.clion.plugin.settings.settings +import org.utbot.cpp.clion.plugin.utils.path +import java.nio.file.InvalidPathException +import java.nio.file.Paths + +abstract class ClientException(message: String) : Exception(message) + +class IllegalPathException(val path: String, val pathName: String, message: String? = null) : + ClientException(message ?: "Illegal: $pathName: $path") + + +data class RemoteMapping(val localProjectPath: String, val remoteProjectPath: String, val shouldConvert: Boolean = true) { + constructor(project: Project): this(project.path, project.settings.storedSettings.remotePath, project.settings.isRemoteScenario) + + fun convertToRemote(path: String, errorText: String): String { + if (!shouldConvert) + return path + val localProjectNioPath = Paths.get(localProjectPath) + val remoteProjectNioPath = try { + Paths.get(remoteProjectPath) + } catch (_: InvalidPathException) { + throw IllegalPathException(remoteProjectPath, UTBot.message("settings.project.remotePath")) + } + val relativeToProjectNioPath = try { + localProjectNioPath.relativize(Paths.get(path)) + } catch (_: IllegalArgumentException) { + throw IllegalPathException(path, errorText) + } + return FilenameUtils.separatorsToUnix(remoteProjectNioPath.resolve(relativeToProjectNioPath).toString()) + } +} + +/** + * Wrapper on grpc generated class [G], that can + * build request of type [G] for server, converting paths to remote filesystem + */ +fun interface GrpcRequestBuilder { + /** + * Builds grpc message [G] with paths converted to remote version. + * May throw exceptions + */ + fun build(remoteMapping: RemoteMapping): G +} diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/grpc/GrpcRequestBuilderFactory.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/grpc/GrpcRequestBuilderFactory.kt new file mode 100644 index 000000000..a28da1301 --- /dev/null +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/grpc/GrpcRequestBuilderFactory.kt @@ -0,0 +1,144 @@ +package org.utbot.cpp.clion.plugin.grpc + +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiElement +import org.utbot.cpp.clion.plugin.settings.settings +import org.utbot.cpp.clion.plugin.ui.testsResults.TestNameAndTestSuite +import org.utbot.cpp.clion.plugin.utils.localPath +import org.utbot.cpp.clion.plugin.utils.path +import testsgen.Testgen +import testsgen.Util + +/** + * A facade that provides builders for grpc generated requests aka GrpcRequestBuilder, + * where G is a grpc generated message + */ +class GrpcRequestBuilderFactory( + val project: Project +) { + fun createProjectContextBuilder(): GrpcRequestBuilder { + return ProjectContextBuilder( + project.name, + project.path, + project.settings.storedSettings.testDirRelativePath, + project.settings.storedSettings.buildDirRelativePath + ) + } + + fun createSettingsContextBuilder(): GrpcRequestBuilder { + return project.settings.storedSettings.let { + SettingsContextBuilder( + it.generateForStaticFunctions, + it.verbose, + it.timeoutPerFunction, + it.timeoutPerTest, + it.useDeterministicSearcher, + it.useStubs + ) + } + } + + fun createProjectRequestBuilder(): GrpcRequestBuilder { + val settings = project.settings.storedSettings + val sourcePaths = settings.sourceDirs.toList() + return ProjectRequestBuilder( + createProjectContextBuilder() as ProjectContextBuilder, + createSettingsContextBuilder() as SettingsContextBuilder, + sourcePaths, + project.settings.isRemoteScenario, + settings.targetPath + ) + } + + fun createLineRequestBuilder(lineNumber: Int, filePath: String): GrpcRequestBuilder { + return LineRequestBuilder( + createProjectRequestBuilder(), + SourceInfoParams(filePath, lineNumber) + ) + } + + fun createFunctionRequestBuilder(filePath: String, lineNumber: Int): GrpcRequestBuilder { + return FunctionRequestBuilder( + createLineRequestBuilder(lineNumber, filePath) + ) + } + + fun createFolderRequestBuilder(folderPath: String): GrpcRequestBuilder { + return FolderRequestBuilder( + createProjectRequestBuilder() as ProjectRequestBuilder, + folderPath + ) + } + + fun createFileRequestBuilder(filePath: String): GrpcRequestBuilder { + return FileRequestBuilder( + createProjectRequestBuilder() as ProjectRequestBuilder, + filePath + ) + } + + fun createProjectConfigRequestBuilder(configMode: Testgen.ConfigMode): GrpcRequestBuilder { + return ProjectConfigRequestBuilder( + createProjectContextBuilder() as ProjectContextBuilder, + configMode, + project.settings.storedSettings.cmakeOptions.split(" ") + ) + } + + fun createProjectTargetsRequestBuilder(): GrpcRequestBuilder { + return ProjectTargetsParams(createProjectContextBuilder() as ProjectContextBuilder) + } + + /** + * if [element] is null return params that correspond for running all tests + */ + fun createCovAndResulstsRequestBuilder(element: PsiElement? = null): GrpcRequestBuilder { + return CoverageAndResultsRequestBuilder( + createProjectContextBuilder() as ProjectContextBuilder, + createSettingsContextBuilder() as SettingsContextBuilder, + element?.let { createTestFilterBuilder(it) as TestFilterBuilder }, + coverage = true + ) + } + + private fun createTestFilterBuilder(element: PsiElement): GrpcRequestBuilder { + val (testName: String, testSuite: String) = TestNameAndTestSuite.create(element) + val testFilePath = element.containingFile.virtualFile.localPath.toString() + return TestFilterBuilder( + testFilePath, + testName, + testSuite + ) + } + + fun createClassRequestBuilder(filePath: String, lineNumber: Int): GrpcRequestBuilder { + return ClassRequestParams(createLineRequestBuilder(lineNumber, filePath) as LineRequestBuilder) + } + + fun createAssertionRequestBuilder(lineNumber: Int, filePath: String): GrpcRequestBuilder { + return AssertionRequestBuilder( + createLineRequestBuilder(lineNumber, filePath) as LineRequestBuilder + ) + } + + fun createPredicateRequestBuilder( + comparisonOperator: String, + validationType: Util.ValidationType, + valueToCompare: String, + lineNumber: Int, + filePath: String + ): GrpcRequestBuilder { + return PredicateRequestBuilder( + createLineRequestBuilder(lineNumber, filePath) as LineRequestBuilder, + PredicateInfoParams(validationType, comparisonOperator, valueToCompare) + ) + } + + fun createSnippetRequestBuilder(filePath: String): GrpcRequestBuilder { + return SnippetRequestBuilder( + createProjectContextBuilder() as ProjectContextBuilder, + createSettingsContextBuilder() as SettingsContextBuilder, + filePath + ) + } +} diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/grpc/GrpcRequestBuildersImpl.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/grpc/GrpcRequestBuildersImpl.kt new file mode 100644 index 000000000..4e2c68fef --- /dev/null +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/grpc/GrpcRequestBuildersImpl.kt @@ -0,0 +1,267 @@ +package org.utbot.cpp.clion.plugin.grpc + +import org.utbot.cpp.clion.plugin.UTBot +import org.utbot.cpp.clion.plugin.ui.utbotToolWindow.targetToolWindow.UTBotTarget +import testsgen.Testgen +import testsgen.Util +import java.nio.file.InvalidPathException +import java.nio.file.Paths + + +internal data class ProjectContextBuilder( + val projectName: String, + val projectPath: String, + val testDirRelativePath: String, + val buildDirRelativePath: String +) : GrpcRequestBuilder { + override fun build(remoteMapping: RemoteMapping): Testgen.ProjectContext { + val projectNioPath = Paths.get(projectPath) // project path is not set by user, assuming it is valid + val relativeTestsDirNioPath = try { + Paths.get(testDirRelativePath) + } catch (e: InvalidPathException) { + throw IllegalPathException(testDirRelativePath, UTBot.message("settings.project.testsDir.wrong")) + } + return Testgen.ProjectContext.newBuilder() + .setProjectPath(projectPath) + .setTestDirPath( + remoteMapping.convertToRemote( + projectNioPath.resolve(relativeTestsDirNioPath).toString(), + UTBot.message("settings.project.testsDir.wrong") + ) + ) + .setBuildDirRelativePath(buildDirRelativePath) + .setProjectName(projectName) + .setProjectPath(remoteMapping.convertToRemote(projectPath, UTBot.message("projectPath.wrong.conversion"))) + .build() + } +} + +internal data class SettingsContextBuilder( + val generateForStaticFunctions: Boolean, + val verbose: Boolean, + val timeoutPerFunction: Int, + val timeoutPerTest: Int, + val useDeterministicSearcher: Boolean, + val useStubs: Boolean +) : GrpcRequestBuilder { + override fun build(remoteMapping: RemoteMapping): Testgen.SettingsContext { + return Testgen.SettingsContext.newBuilder() + .setVerbose(verbose) + .setGenerateForStaticFunctions(generateForStaticFunctions) + .setTimeoutPerFunction(timeoutPerFunction) + .setTimeoutPerTest(timeoutPerTest) + .setUseStubs(useStubs) + .build() + } +} + +internal data class ProjectRequestBuilder( + val projectContextBuilder: ProjectContextBuilder, + val settingsContextBuilder: SettingsContextBuilder, + val sourcePaths: List, + val synchronizeCode: Boolean, + val targetPath: String +) : GrpcRequestBuilder { + override fun build(remoteMapping: RemoteMapping): Testgen.ProjectRequest { + return Testgen.ProjectRequest.newBuilder() + .setProjectContext(projectContextBuilder.build(remoteMapping)) + .setSettingsContext(settingsContextBuilder.build(remoteMapping)) + .addAllSourcePaths(sourcePaths.map { sourcePath -> + remoteMapping.convertToRemote( + sourcePath, + UTBot.message("settings.project.sourcePaths.wrong.conversion") + ) + }) + .setSynchronizeCode(synchronizeCode) + .also { builder -> + if (!UTBotTarget.isAutoTargetPath(targetPath)) { + builder.targetPath = remoteMapping.convertToRemote( + targetPath, + UTBot.message("settings.project.target.wrong.conversion") + ) + } else { + builder.targetPath = targetPath + } + } + .build() + } +} + +internal data class FolderRequestBuilder( + val projectRequestBuilder: ProjectRequestBuilder, + val folderPath: String +) : GrpcRequestBuilder { + override fun build(remoteMapping: RemoteMapping): Testgen.FolderRequest { + return Testgen.FolderRequest.newBuilder() + .setFolderPath(remoteMapping.convertToRemote(folderPath, UTBot.message("folderPath.wrong.conversion"))) + .setProjectRequest(projectRequestBuilder.build(remoteMapping)) + .build() + } +} + +internal data class FileRequestBuilder( + val projectRequestBuilder: ProjectRequestBuilder, + val filePath: String +) : GrpcRequestBuilder { + override fun build(remoteMapping: RemoteMapping): Testgen.FileRequest { + return Testgen.FileRequest.newBuilder() + .setProjectRequest(projectRequestBuilder.build(remoteMapping)) + .setFilePath(remoteMapping.convertToRemote(filePath, UTBot.message("filePath.wrong.conversion"))) + .build() + } +} + +internal data class ProjectConfigRequestBuilder( + val projectContextBuilder: ProjectContextBuilder, + val configMode: Testgen.ConfigMode, + val cmakeOptions: List +) : GrpcRequestBuilder { + override fun build(remoteMapping: RemoteMapping): Testgen.ProjectConfigRequest { + return Testgen.ProjectConfigRequest.newBuilder() + .setProjectContext(projectContextBuilder.build(remoteMapping)) + .setConfigMode(configMode) + .addAllCmakeOptions(cmakeOptions) + .build() + } +} + +internal data class ProjectTargetsParams( + val projectContextBuilder: ProjectContextBuilder +) : GrpcRequestBuilder { + override fun build(remoteMapping: RemoteMapping): Testgen.ProjectTargetsRequest { + return Testgen.ProjectTargetsRequest.newBuilder() + .setProjectContext(projectContextBuilder.build(remoteMapping)) + .build() + } +} + +internal data class TestFilterBuilder( + val testFilePath: String, + val testName: String, + val testSuite: String +) : GrpcRequestBuilder { + override fun build(remoteMapping: RemoteMapping): Testgen.TestFilter { + return Testgen.TestFilter.newBuilder() + .setTestFilePath( + remoteMapping.convertToRemote( + testFilePath, + UTBot.message("testFilePath.wrong.conversion") + ) + ) + .setTestName(testName) + .setTestSuite(testSuite) + .build() + } +} + +internal data class CoverageAndResultsRequestBuilder( + val projectContextBuilder: ProjectContextBuilder, + val settingsContextBuilder: SettingsContextBuilder, + val testFilterBuilder: TestFilterBuilder? = null, + val coverage: Boolean = true +) : GrpcRequestBuilder { + override fun build(remoteMapping: RemoteMapping): Testgen.CoverageAndResultsRequest { + val builder = Testgen.CoverageAndResultsRequest.newBuilder() + .setCoverage(coverage) + .setSettingsContext(settingsContextBuilder.build(remoteMapping)) + .setProjectContext(projectContextBuilder.build(remoteMapping)) + testFilterBuilder?.let { + builder.setTestFilter(it.build(remoteMapping)) + } + + return builder.build() + } +} + +internal data class SourceInfoParams( + val filePath: String, + val line: Int +) : GrpcRequestBuilder { + override fun build(remoteMapping: RemoteMapping): Util.SourceInfo { + return Util.SourceInfo.newBuilder() + .setLine(line) + .setFilePath(remoteMapping.convertToRemote(filePath, UTBot.message("filePath.wrong.conversion"))) + .build() + } +} + +data class LineRequestBuilder( + val projectRequestParams: GrpcRequestBuilder, + val sourceInfoParams: GrpcRequestBuilder +) : GrpcRequestBuilder { + override fun build(remoteMapping: RemoteMapping): Testgen.LineRequest { + return Testgen.LineRequest.newBuilder() + .setProjectRequest(projectRequestParams.build(remoteMapping)) + .setSourceInfo(sourceInfoParams.build(remoteMapping)) + .build() + } +} + +internal data class FunctionRequestBuilder( + val fileRequestParams: GrpcRequestBuilder +) : GrpcRequestBuilder { + override fun build(remoteMapping: RemoteMapping): Testgen.FunctionRequest { + return Testgen.FunctionRequest.newBuilder() + .setLineRequest(fileRequestParams.build(remoteMapping)) + .build() + } +} + +internal data class ClassRequestParams( + val lineRequestBuilder: LineRequestBuilder +) : GrpcRequestBuilder { + override fun build(remoteMapping: RemoteMapping): Testgen.ClassRequest { + return Testgen.ClassRequest.newBuilder() + .setLineRequest(lineRequestBuilder.build(remoteMapping)) + .build() + } +} + +internal class AssertionRequestBuilder(private val lineRequestBuilder: LineRequestBuilder) : + GrpcRequestBuilder { + override fun build(remoteMapping: RemoteMapping): Testgen.AssertionRequest { + return Testgen.AssertionRequest.newBuilder() + .setLineRequest(lineRequestBuilder.build(remoteMapping)) + .build() + } +} + +internal data class PredicateInfoParams( + val validationType: Util.ValidationType, + val predicate: String, + val returnValue: String +) : GrpcRequestBuilder { + override fun build(remoteMapping: RemoteMapping): Util.PredicateInfo { + return Util.PredicateInfo.newBuilder() + .setPredicate(predicate) + .setReturnValue(returnValue) + .setType(validationType) + .build() + } +} + +internal class PredicateRequestBuilder( + private val lineRequestBuilder: LineRequestBuilder, + private val predicateInfoParams: PredicateInfoParams +) : GrpcRequestBuilder { + override fun build(remoteMapping: RemoteMapping): Testgen.PredicateRequest { + return Testgen.PredicateRequest.newBuilder() + .setLineRequest(lineRequestBuilder.build(remoteMapping)) + .setPredicateInfo(predicateInfoParams.build(remoteMapping)) + .build() + } +} + +internal class SnippetRequestBuilder( + private val projectContextBuilder: ProjectContextBuilder, + private val settingsContextBuilder: SettingsContextBuilder, + val filePath: String +) : GrpcRequestBuilder { + override fun build(remoteMapping: RemoteMapping): Testgen.SnippetRequest { + return Testgen.SnippetRequest.newBuilder() + .setProjectContext(projectContextBuilder.build(remoteMapping)) + .setSettingsContext(settingsContextBuilder.build(remoteMapping)) + .setFilePath(remoteMapping.convertToRemote(filePath, UTBot.message("filePath.wrong.conversion"))) + .build() + } +} diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/settings/UTBotAllProjectSettings.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/settings/UTBotAllProjectSettings.kt index deb61dbf0..f348a000c 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/settings/UTBotAllProjectSettings.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/settings/UTBotAllProjectSettings.kt @@ -3,6 +3,8 @@ package org.utbot.cpp.clion.plugin.settings import com.intellij.openapi.components.Service import com.intellij.openapi.components.service import com.intellij.openapi.project.Project +import org.utbot.cpp.clion.plugin.UTBot +import org.utbot.cpp.clion.plugin.grpc.IllegalPathException import org.utbot.cpp.clion.plugin.listeners.PluginActivationListener import org.utbot.cpp.clion.plugin.listeners.UTBotSettingsChangedListener import org.utbot.cpp.clion.plugin.ui.utbotToolWindow.targetToolWindow.UTBotTarget @@ -10,6 +12,7 @@ import org.utbot.cpp.clion.plugin.utils.convertToRemotePathIfNeeded import org.utbot.cpp.clion.plugin.utils.isWindows import org.utbot.cpp.clion.plugin.utils.path import java.io.File +import java.nio.file.InvalidPathException import java.nio.file.Path import java.nio.file.Paths @@ -19,22 +22,36 @@ class UTBotAllProjectSettings(val project: Project) { get() = project.service() val buildDirPath: Path - get() = Paths.get(project.path).resolve(storedSettings.buildDirRelativePath) + get() { + try { + return Paths.get(project.path).resolve(storedSettings.buildDirRelativePath) + } catch (e: InvalidPathException) { + throw IllegalPathException( + UTBot.message( + "paths.invalid", + "relative path to build dir", + storedSettings.buildDirRelativePath + ), + storedSettings.buildDirRelativePath + ) + } + } val testsDirPath: Path - get() = Paths.get(project.path).resolve(storedSettings.testDirRelativePath) - - val convertedSourcePaths: List - get() = storedSettings.sourceDirs.map { it.convertToRemotePathIfNeeded(project) } - - val convertedTestDirPath: String - get() = testsDirPath.toString().convertToRemotePathIfNeeded(project) - - val convertedTargetPath: String - get() = if (storedSettings.targetPath == UTBotTarget.autoTarget.path) storedSettings.targetPath - else storedSettings.targetPath.convertToRemotePathIfNeeded(project) - - val convertedProjectPath: String get() = project.path.convertToRemotePathIfNeeded(project) + get() { + try { + return Paths.get(project.path).resolve(storedSettings.testDirRelativePath) + } catch (e: InvalidPathException) { + throw IllegalPathException( + storedSettings.testDirRelativePath, + UTBot.message( + "paths.invalid", + "relative path to tests dir", + storedSettings.testDirRelativePath + ) + ) + } + } /** * If this property returns true, plugin must convert path sent and returned from server. @@ -51,7 +68,7 @@ class UTBotAllProjectSettings(val project: Project) { fun fireUTBotSettingsChanged() { project.messageBus.let { bus -> - if(!bus.isDisposed) + if (!bus.isDisposed) bus.syncPublisher(UTBotSettingsChangedListener.TOPIC).settingsChanged(this) } } @@ -64,8 +81,6 @@ class UTBotAllProjectSettings(val project: Project) { } fun predictPaths() { - fun getSourceFoldersFromSources(sources: Collection) = sources.map { it.parent }.toMutableSet() - storedSettings.remotePath = UTBotProjectStoredSettings.REMOTE_PATH_VALUE_FOR_LOCAL_SCENARIO storedSettings.buildDirRelativePath = UTBotProjectStoredSettings.DEFAULT_RELATIVE_PATH_TO_BUILD_DIR storedSettings.targetPath = UTBotTarget.autoTarget.path diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/settings/UTBotConfigurable.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/settings/UTBotConfigurable.kt index 77e6e7987..e930aa2cf 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/settings/UTBotConfigurable.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/settings/UTBotConfigurable.kt @@ -5,6 +5,7 @@ package org.utbot.cpp.clion.plugin.settings import com.intellij.openapi.components.service import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.options.BoundConfigurable +import com.intellij.openapi.options.ConfigurationException import com.intellij.openapi.project.Project import com.intellij.openapi.ui.DialogPanel import com.intellij.ui.JBIntSpinner @@ -12,6 +13,7 @@ import com.intellij.ui.components.JBCheckBox import com.intellij.ui.components.JBTextField import com.intellij.ui.dsl.builder.BottomGap import com.intellij.ui.dsl.builder.COLUMNS_LARGE +import com.intellij.ui.dsl.builder.Cell import com.intellij.ui.dsl.builder.LabelPosition import com.intellij.ui.dsl.builder.Panel import com.intellij.ui.dsl.builder.bindIntValue @@ -25,7 +27,12 @@ import org.utbot.cpp.clion.plugin.UTBot import org.utbot.cpp.clion.plugin.listeners.UTBotSettingsChangedListener import org.utbot.cpp.clion.plugin.ui.ObservableValue import org.utbot.cpp.clion.plugin.ui.sourceFoldersView.UTBotProjectViewPaneForSettings +import org.utbot.cpp.clion.plugin.utils.ComponentValidationInfo +import org.utbot.cpp.clion.plugin.utils.ValidationCondition +import org.utbot.cpp.clion.plugin.utils.addValidation import org.utbot.cpp.clion.plugin.utils.commandLineEditor +import org.utbot.cpp.clion.plugin.utils.isLookLikeUnixPath +import org.utbot.cpp.clion.plugin.utils.isValidHostName import org.utbot.cpp.clion.plugin.utils.projectLifetimeDisposable import java.awt.Dimension import java.awt.event.ItemEvent @@ -37,6 +44,7 @@ class UTBotConfigurable(private val myProject: Project) : BoundConfigurable( private val panel by lazy { createMainPanel() } private val settings: UTBotProjectStoredSettings = myProject.service() + private val validationInfos: MutableList = mutableListOf() private lateinit var portComponent: JBIntSpinner private lateinit var serverNameTextField: JBTextField private lateinit var pluginEnabledCheckBox: JBCheckBox @@ -49,6 +57,13 @@ class UTBotConfigurable(private val myProject: Project) : BoundConfigurable( }) } + private fun Cell.validateInput(vararg conditions: ValidationCondition): Cell { + return this.apply { + validationInfos.add(this.addValidation(*conditions)) + } + } + + override fun createPanel() = panel private fun createMainPanel(): DialogPanel { @@ -93,22 +108,33 @@ class UTBotConfigurable(private val myProject: Project) : BoundConfigurable( ).bindIntValue(projectIndependentSettings::port).applyToComponent { portComponent = this } - }.rowComment(UTBot.message("deployment.utbotPort.description")) + }.rowComment(UTBot.message("deployment.utbot.port.description")) row(UTBot.message("settings.project.serverName")) { textField().bindText(projectIndependentSettings::serverName).applyToComponent { serverNameTextField = this - } - }.rowComment(UTBot.message("deployment.utbotHost.description")) + }.validateInput( + ValidationCondition( + UTBot.message("validation.invalid.host") + ) { it.text.isValidHostName() } + ) + }.rowComment(UTBot.message("deployment.utbot.host.description")) row(UTBot.message("settings.project.remotePath")) { - textField().bindText(settings::remotePath).columns(COLUMNS_LARGE) + textField().bindText(settings::remotePath).columns(COLUMNS_LARGE).validateInput( + ValidationCondition(UTBot.message("validation.not.empty")) { it.text.isNotEmpty() }, + ValidationCondition(UTBot.message("validation.not.unix.path")) { it.text.isLookLikeUnixPath() } + ) }.rowComment(UTBot.message("deployment.remotePath.description")) } private fun Panel.createPathsSettings() { row(UTBot.message("settings.project.buildDir")) { + val validator: (JBTextField) -> Boolean = { + it.text.isNotEmpty() + } textField().bindText(settings::buildDirRelativePath).columns(COLUMNS_LARGE) + .validateInput(ValidationCondition(UTBot.message("validation.not.empty")) { it.text.isNotEmpty() }) }.rowComment(UTBot.message("paths.buildDirectory.description")) row(UTBot.message("settings.project.target")) { @@ -122,6 +148,7 @@ class UTBotConfigurable(private val myProject: Project) : BoundConfigurable( row(UTBot.message("settings.project.testsDir")) { textField().bindText(settings::testDirRelativePath).columns(COLUMNS_LARGE) + .validateInput(ValidationCondition(UTBot.message("validation.not.empty")) { it.text.isNotEmpty() }) }.rowComment(UTBot.message("paths.testsDir.description")) row { @@ -208,6 +235,12 @@ class UTBotConfigurable(private val myProject: Project) : BoundConfigurable( } override fun apply() { + val invalidComponentValidationInfo = validationInfos.find { !it.isValid() } + if (invalidComponentValidationInfo != null) { + panel.scrollRectToVisible(invalidComponentValidationInfo.component.visibleRect) + invalidComponentValidationInfo.component.requestFocus() + throw ConfigurationException("Some fields have invalid values") + } val wereConnectionSettingsModified = portComponent.number != projectIndependentSettings.port || serverNameTextField.text != projectIndependentSettings.serverName val wasPluginEnabledChanged = pluginEnabledCheckBox.isSelected != settings.isPluginEnabled @@ -226,4 +259,4 @@ class UTBotConfigurable(private val myProject: Project) : BoundConfigurable( companion object { val TEXT_FIELD_MAX_SIZE = Dimension(370, 100) } -} \ No newline at end of file +} diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/settings/UTBotProjectStoredSettings.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/settings/UTBotProjectStoredSettings.kt index cfce4b7c3..063bc4b76 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/settings/UTBotProjectStoredSettings.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/settings/UTBotProjectStoredSettings.kt @@ -13,6 +13,7 @@ import org.utbot.cpp.clion.plugin.ui.utbotToolWindow.targetToolWindow.UTBotTarge import org.utbot.cpp.clion.plugin.ui.wizard.UTBotWizard import org.utbot.cpp.clion.plugin.utils.invokeOnEdt import org.utbot.cpp.clion.plugin.utils.path +import org.utbot.cpp.clion.plugin.utils.stripLeadingSlashes import java.nio.file.Paths /** @@ -101,7 +102,7 @@ class UTBotProjectStoredSettings(val project: Project) : PersistentStateComponen } var testDirRelativePath: String - get() = myState.testsDirRelativePath + get() = myState.testsDirRelativePath.stripLeadingSlashes() set(value) { myState.testsDirRelativePath = value } @@ -129,7 +130,7 @@ class UTBotProjectStoredSettings(val project: Project) : PersistentStateComponen Paths.get(project.path).relativize(Paths.get(targetPath)).toString() var buildDirRelativePath: String - get() = myState.buildDirRelativePath + get() = myState.buildDirRelativePath.stripLeadingSlashes() set(value) { myState.buildDirRelativePath = value } diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/UTBotRequestProgressIndicator.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/UTBotRequestProgressIndicator.kt index eee03581b..a3db5664b 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/UTBotRequestProgressIndicator.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/UTBotRequestProgressIndicator.kt @@ -6,9 +6,11 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.wm.ex.StatusBarEx import com.intellij.openapi.wm.ex.WindowManagerEx import kotlinx.coroutines.Job +import org.utbot.cpp.clion.plugin.UTBot import org.utbot.cpp.clion.plugin.utils.invokeOnEdt import org.utbot.cpp.clion.plugin.utils.notifyInfo +// todo: remove this class and use new api for coroutines progress: TaskCancellation, withBackgroundProgressIndicator class UTBotRequestProgressIndicator( private val taskDisplayName: String, private val requestJob: Job? = null, @@ -16,32 +18,39 @@ class UTBotRequestProgressIndicator( ) : AbstractProgressIndicatorExBase(true) { private val requestTask = UTBotRequestTaskInfo(taskDisplayName) + init { isIndeterminate = false } override fun start() { + // start showing progress in the ui + super.start() val frame = WindowManagerEx.getInstanceEx().findFrameFor(project) ?: return val statusBar = frame.statusBar as? StatusBarEx ?: return invokeOnEdt { statusBar.addProgress(this, requestTask) } - super.start() } - override fun stop() { - requestJob?.cancel() + fun stopShowingProgressInUI() { + // stop can be called only if progress was started (=running) finish() super.stop() } - fun finish() = finish(requestTask) + fun finish() { + finish(requestTask) + } override fun cancel() { requestJob?.cancel() - finish(requestTask) + finish() super.cancel() - notifyInfo("Successfully canceled: $taskDisplayName") + notifyInfo( + UTBot.message("notify.cancelled.request.title"), + UTBot.message("notify.cancelled.request", taskDisplayName) + ) } private class UTBotRequestTaskInfo(private val titleText: String) : TaskInfo { diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/sourceFoldersView/ProxyProjectViewTree.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/sourceFoldersView/ProxyProjectViewTree.kt index a0baff8c1..53e705c9c 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/sourceFoldersView/ProxyProjectViewTree.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/sourceFoldersView/ProxyProjectViewTree.kt @@ -5,8 +5,6 @@ import com.intellij.openapi.actionSystem.DataKey import com.intellij.openapi.actionSystem.DataProvider import com.intellij.openapi.project.Project import org.utbot.cpp.clion.plugin.settings.settings -import java.awt.event.MouseAdapter -import java.awt.event.MouseEvent import javax.swing.tree.DefaultTreeModel import org.utbot.cpp.clion.plugin.listeners.SourceFoldersListener diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/testsResults/TestNameAndTestSuite.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/testsResults/TestNameAndTestSuite.kt index 23f3df6b5..3d61216b3 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/testsResults/TestNameAndTestSuite.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/testsResults/TestNameAndTestSuite.kt @@ -28,4 +28,4 @@ data class TestNameAndTestSuite private constructor(val name: String = "", val s return TestNameAndTestSuite(testedMethodName, suiteName) } } -} \ No newline at end of file +} diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/testsResults/UTBotTestRunLineMarkerProvider.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/testsResults/UTBotTestRunLineMarkerProvider.kt index d4bf45a11..b7a3447e8 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/testsResults/UTBotTestRunLineMarkerProvider.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/testsResults/UTBotTestRunLineMarkerProvider.kt @@ -11,6 +11,7 @@ import com.intellij.psi.PsiElement import javax.swing.Icon import kotlin.io.path.name import org.utbot.cpp.clion.plugin.actions.generate.RunWithCoverageAction +import org.utbot.cpp.clion.plugin.grpc.IllegalPathException import org.utbot.cpp.clion.plugin.settings.settings import org.utbot.cpp.clion.plugin.ui.services.TestsResultsStorage import org.utbot.cpp.clion.plugin.utils.localPath @@ -57,10 +58,15 @@ class UTBotTestRunLineMarkerProvider : LineMarkerProvider { private fun isElementInTestFileGeneratedByUTBot(element: PsiElement) = element.containingFile.virtualFile.localPath.let { - it.toString().startsWith(element.project.settings.testsDirPath.toString()) && - it.name.contains("test") + try { + it.toString().startsWith(element.project.settings.testsDirPath.toString()) && + it.name.contains("test") + } catch (e: IllegalPathException) { + return false + } } + fun getStatusIcon(element: PsiElement): Icon { // return icon for Running All Tests if (element.canPlaceAllTestsIcon()) { diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/userLog/ConsoleToolWindowProvider.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/userLog/ConsoleToolWindowProvider.kt deleted file mode 100644 index fa10c490a..000000000 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/userLog/ConsoleToolWindowProvider.kt +++ /dev/null @@ -1,20 +0,0 @@ -package org.utbot.cpp.clion.plugin.ui.userLog - -import com.intellij.openapi.diagnostic.Logger -import com.intellij.openapi.project.Project -import com.intellij.openapi.wm.ToolWindow -import com.intellij.openapi.wm.ToolWindowFactory -import org.utbot.cpp.clion.plugin.ui.utbotToolWindow.logsToolWindow.ConsoleToolWindow - -class ConsoleToolWindowProvider : ToolWindowFactory { - private val logger = Logger.getInstance(this::class.java) - - override fun createToolWindowContent(project: Project, toolWindow: ToolWindow) { - logger.debug("createToolWindowContent was called") - - val contentManager = toolWindow.contentManager - val content = - contentManager.factory.createContent(ConsoleToolWindow(project), null, false) - contentManager.addContent(content) - } -} diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/utbotToolWindow/UTBotToolWindowFactory.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/utbotToolWindow/UTBotToolWindowFactory.kt index 7947b0635..6bc664bbb 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/utbotToolWindow/UTBotToolWindowFactory.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/utbotToolWindow/UTBotToolWindowFactory.kt @@ -9,6 +9,7 @@ import com.intellij.openapi.wm.ToolWindowFactory import org.utbot.cpp.clion.plugin.UTBot import org.utbot.cpp.clion.plugin.ui.utbotToolWindow.logsToolWindow.ConsoleToolWindow import org.utbot.cpp.clion.plugin.ui.utbotToolWindow.targetToolWindow.UTBotTargetsController +import org.utbot.cpp.clion.plugin.utils.invokeOnEdt class UTBotToolWindowFactory : ToolWindowFactory, DumbAware { private val logger = Logger.getInstance(this::class.java) diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/utbotToolWindow/targetToolWindow/UTBotTarget.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/utbotToolWindow/targetToolWindow/UTBotTarget.kt index 585ceca1f..b3861d4bd 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/utbotToolWindow/targetToolWindow/UTBotTarget.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/utbotToolWindow/targetToolWindow/UTBotTarget.kt @@ -21,5 +21,7 @@ data class UTBotTarget(val path: String, val name: String, val description: Stri name = "UTBot: auto", description = "Finds any target that contains the code under test" ) + + fun isAutoTargetPath(path: String): Boolean = autoTarget.path == path } } diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/utbotToolWindow/targetToolWindow/UTBotTargetsController.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/utbotToolWindow/targetToolWindow/UTBotTargetsController.kt index 3ac335e8d..8cb3ee70f 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/utbotToolWindow/targetToolWindow/UTBotTargetsController.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/utbotToolWindow/targetToolWindow/UTBotTargetsController.kt @@ -7,7 +7,7 @@ import com.intellij.openapi.project.Project import com.intellij.ui.CollectionListModel import org.utbot.cpp.clion.plugin.client.ManagedClient import org.utbot.cpp.clion.plugin.client.requests.ProjectTargetsRequest -import org.utbot.cpp.clion.plugin.grpc.getProjectTargetsGrpcRequest +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilderFactory import org.utbot.cpp.clion.plugin.listeners.ConnectionStatus import org.utbot.cpp.clion.plugin.listeners.UTBotEventsListener import org.utbot.cpp.clion.plugin.settings.UTBotAllProjectSettings @@ -26,7 +26,6 @@ class UTBotTargetsController(val project: Project) { private var areTargetsUpToDate = false private val targetsUiModel = CollectionListModel(mutableListOf()) - private val client = project.service() val targetsToolWindow: UTBotTargetsToolWindow by lazy { UTBotTargetsToolWindow(targetsUiModel, this) } val targets: List @@ -39,15 +38,17 @@ class UTBotTargetsController(val project: Project) { fun isTargetUpToDate(path: String): Boolean = areTargetsUpToDate && targets.find { it.path == path } != null fun requestTargetsFromServer() { + invokeOnEdt { requestTargetsEdt() } + } + + private fun requestTargetsEdt() { areTargetsUpToDate = false - invokeOnEdt { - targetsUiModel.removeAll() - targetsToolWindow.setBusy(true) - } + targetsUiModel.removeAll() + targetsToolWindow.setBusy(true) ProjectTargetsRequest( + GrpcRequestBuilderFactory(project).createProjectTargetsRequestBuilder(), project, - getProjectTargetsGrpcRequest(project), processTargets = { targetsResponse: Testgen.ProjectTargetsResponse -> invokeOnEdt { targetsToolWindow.setBusy(false) @@ -76,14 +77,14 @@ class UTBotTargetsController(val project: Project) { targetsToolWindow.setBusy(false) } }).let { targetsRequest -> - //todo: throw exception from client and handle it here + val client = project.service() + if (!client.isServerAvailable()) { logger.error { "Could not request targets from server: server is unavailable!" } - invokeOnEdt { - targetsToolWindow.setBusy(false) - } + targetsToolWindow.setBusy(false) return } + logger.trace { "Requesting project targets from server!" } client.executeRequest(targetsRequest) } @@ -110,7 +111,7 @@ class UTBotTargetsController(val project: Project) { if (newStatus != oldStatus) { // todo: remove this, when ci is fixed if (!ApplicationManager.getApplication().isUnitTestMode) - requestTargetsFromServer() + invokeOnEdt(::requestTargetsFromServer) } } } diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/wizard/UTBotBaseWizardStep.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/wizard/UTBotBaseWizardStep.kt index 232420be5..def619fc6 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/wizard/UTBotBaseWizardStep.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/wizard/UTBotBaseWizardStep.kt @@ -1,7 +1,10 @@ package org.utbot.cpp.clion.plugin.ui.wizard import com.intellij.ide.wizard.Step +import com.intellij.openapi.Disposable import com.intellij.openapi.ui.DialogPanel +import com.intellij.ui.components.JBTextField +import com.intellij.ui.dsl.builder.Cell import com.intellij.util.ui.HtmlPanel import com.intellij.util.ui.UIUtil import javax.swing.Box @@ -9,16 +12,18 @@ import javax.swing.BoxLayout import javax.swing.Icon import javax.swing.JComponent import javax.swing.JPanel +import org.utbot.cpp.clion.plugin.utils.ComponentValidationInfo +import org.utbot.cpp.clion.plugin.utils.ValidationCondition +import org.utbot.cpp.clion.plugin.utils.validateInput import java.awt.Component import java.awt.Dimension import java.awt.Font -abstract class UTBotBaseWizardStep: Step { +abstract class UTBotBaseWizardStep(private val parentDisposable: Disposable) : Step { private val panel by lazy { JPanel() } private var isInitialized = false - + private val validators = mutableListOf() private val onApplyCallbacks = mutableListOf<() -> Unit>() - abstract fun createUI() override fun _init() { @@ -39,6 +44,12 @@ abstract class UTBotBaseWizardStep: Step { addComponentToStep(this) } + protected fun Cell.validateWith(vararg conditions: ValidationCondition): Cell { + return this.applyToComponent { + validators.add(this.validateInput(parentDisposable, *conditions)) + } + } + override fun _commit(finishChosen: Boolean) = onApplyCallbacks.forEach { it.invoke() } //TODO: find a good icon and use here @@ -60,7 +71,15 @@ abstract class UTBotBaseWizardStep: Step { panel.add(component) } - open fun canProceedToNextStep(): Boolean = true + protected fun validate(): JComponent? { + return validators.find { !it.isValid() }?.component + } + + open fun canProceedToNextStep(): Boolean { + val validationResult = validate() + validationResult?.requestFocus() + return validationResult == null + } private fun createHtmlComponent(html: String): JComponent = object : HtmlPanel() { init { diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/wizard/UTBotWizard.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/wizard/UTBotWizard.kt index 4a2755ec7..747e1aeef 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/wizard/UTBotWizard.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/wizard/UTBotWizard.kt @@ -16,13 +16,14 @@ import java.awt.event.KeyEvent class UTBotWizard(private val project: Project) : AbstractWizard("UTBot: Quickstart", project) { // copy of settings to make changes during wizard steps - private val mySettingsModel = UTBotSettingsModel(project.settings.storedSettings.state.copy(), projectIndependentSettings.copy()) + private val mySettingsModel = + UTBotSettingsModel(project.settings.storedSettings.state.copy(), projectIndependentSettings.copy()) init { - addStep(IntroStep()) - addStep(ConnectionStep(project, mySettingsModel)) - addStep(BuildOptionsStep(mySettingsModel)) - addStep(FinalStep()) + addStep(IntroStep(disposable)) + addStep(ConnectionStep(disposable, project, mySettingsModel)) + addStep(BuildOptionsStep(disposable, mySettingsModel)) + addStep(FinalStep(disposable)) super.init() isResizable = true setSize(400, 400) @@ -55,6 +56,7 @@ class UTBotWizard(private val project: Project) : AbstractWizard Unit) { useConnectionDefaults.addOnChangeListener { newValue -> listener(!newValue) } } - }) + }).validateWith( + ValidationCondition( + UTBot.message("validation.invalid.host") + ) { it.text.isValidHostName() } + ) } row("Port") { @@ -194,7 +212,10 @@ class ConnectionStep( override fun addListener(listener: (Boolean) -> Unit) { useConnectionDefaults.addOnChangeListener { newValue -> listener(!newValue) } } - }) + }).validateWith( + ValidationCondition(UTBot.message("validation.not.empty")) { it.text.isNotEmpty() }, + ValidationCondition(UTBot.message("validation.not.unix.path")) { it.text.isLookLikeUnixPath() } + ) } }.addToUI() } @@ -221,7 +242,10 @@ class ConnectionStep( } private fun pingServer() { - CoroutineScope(Dispatchers.IO + SupervisorJob()).launch { + val handler = CoroutineExceptionHandler { _, e -> + e.printStackTrace() + } + CoroutineScope(Dispatchers.IO + SupervisorJob() + handler).launch { connectionStatus.value = pingServer(portComponent.number, hostTextField.text) } } @@ -229,7 +253,8 @@ class ConnectionStep( private fun setupPingOnPortOrHostChange() { hostTextField.document.addDocumentListener(object : DocumentAdapter() { override fun textChanged(e: DocumentEvent) { - pingServer() + if (hostTextField.text.isValidHostName()) + pingServer() } }) portComponent.addChangeListener { diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/wizard/steps/FinalStep.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/wizard/steps/FinalStep.kt index ab620b944..dbc303e25 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/wizard/steps/FinalStep.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/wizard/steps/FinalStep.kt @@ -1,7 +1,8 @@ package org.utbot.cpp.clion.plugin.ui.wizard.steps +import com.intellij.openapi.Disposable import org.utbot.cpp.clion.plugin.ui.wizard.UTBotBaseWizardStep -class FinalStep : UTBotBaseWizardStep() { +class FinalStep(parentDisposable: Disposable) : UTBotBaseWizardStep(parentDisposable) { override fun createUI() = addHtml("media/final_wizard_text.html") } diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/wizard/steps/IntroStep.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/wizard/steps/IntroStep.kt index 557eb7955..eb3d5605b 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/wizard/steps/IntroStep.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/wizard/steps/IntroStep.kt @@ -1,7 +1,8 @@ package org.utbot.cpp.clion.plugin.ui.wizard.steps +import com.intellij.openapi.Disposable import org.utbot.cpp.clion.plugin.ui.wizard.UTBotBaseWizardStep -class IntroStep : UTBotBaseWizardStep() { +class IntroStep(parentDisposable: Disposable) : UTBotBaseWizardStep(parentDisposable) { override fun createUI() = addHtml("media/intro_wizard_text.html") } diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/utils/ActionUtils.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/utils/ActionUtils.kt index 10431534b..d089f8c3c 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/utils/ActionUtils.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/utils/ActionUtils.kt @@ -1,7 +1,33 @@ package org.utbot.cpp.clion.plugin.utils import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.actionSystem.CommonDataKeys +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilder +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilderFactory import org.utbot.cpp.clion.plugin.settings.settings +import testsgen.Testgen + +fun AnActionEvent.getLineNumberUnsafe(): Int { + val editor = this.getRequiredData(CommonDataKeys.EDITOR) + return editor.caretModel.logicalPosition.line + 1 +} + +fun AnActionEvent.getFilePathUnsafe(): String { + return getRequiredData(CommonDataKeys.VIRTUAL_FILE).localPath.toString() +} + +fun AnActionEvent.getBuilderForFileRequest(): GrpcRequestBuilder { + return GrpcRequestBuilderFactory(this.activeProject()) + .createFileRequestBuilder(this.getFilePathUnsafe()) +} + +fun AnActionEvent.getBuilderForLineRequest(): GrpcRequestBuilder { + val filePath = this.getRequiredData(CommonDataKeys.VIRTUAL_FILE).path + val editor = this.getRequiredData(CommonDataKeys.EDITOR) + val lineNumber = editor.caretModel.logicalPosition.line + 1 + return GrpcRequestBuilderFactory(this.activeProject()) + .createLineRequestBuilder(lineNumber, filePath) +} fun isPluginEnabled(e: AnActionEvent): Boolean { var isEnabled = false diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/utils/ClientUtils.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/utils/ClientUtils.kt index 4cafe81bb..708ab2fcb 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/utils/ClientUtils.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/utils/ClientUtils.kt @@ -22,4 +22,4 @@ val AnActionEvent.client: ManagedClient val Project.client: ManagedClient get() = this.service() fun AnActionEvent.activeProject() = this.project - ?: error("A project related to action event $this not found") + ?: error("Project is missing for event: $this") diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/utils/NotificationUtils.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/utils/NotificationUtils.kt index 5822b9258..d8081d465 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/utils/NotificationUtils.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/utils/NotificationUtils.kt @@ -4,30 +4,46 @@ import com.intellij.notification.NotificationGroupManager import com.intellij.notification.NotificationType import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.project.Project +import org.utbot.cpp.clion.plugin.UTBot +import org.utbot.cpp.clion.plugin.actions.ReconnectAction +import org.utbot.cpp.clion.plugin.actions.ShowSettingsAction import testsgen.Testgen -fun notifyError(errorText: String, project: Project? = null, action: AnAction? = null) = - notify(NotificationType.ERROR, errorText, project, action) +fun notifyError(title: String, errorText: String, project: Project? = null, vararg actions: AnAction?) = + notify(NotificationType.ERROR, title, errorText,project, *actions) -fun notifyInfo(infoText: String, project: Project? = null, action: AnAction? = null) = - notify(NotificationType.INFORMATION, infoText, project, action) +fun notifyInfo(title: String, infoText: String, project: Project? = null, vararg actions: AnAction?) = + notify(NotificationType.INFORMATION, title, infoText, project, *actions) -fun notifyWarning(warningText: String, project: Project? = null, action: AnAction? = null) = - notify(NotificationType.WARNING, warningText, project, action) +fun notifyWarning(title: String, warningText: String, project: Project? = null, vararg actions: AnAction?) = + notify(NotificationType.WARNING, title, warningText, project, *actions) fun notifyUnknownResponse(response: Testgen.ProjectConfigResponse, project: Project) = - notifyInfo("Unknown server response: ${response.message}", project) + notifyError(UTBot.message("notify.title.error"), "Unknown server response: ${response.message}", project) private fun notify( type: NotificationType, + title: String, content: String, project: Project? = null, - action: AnAction? = null, + vararg actions: AnAction? ) { val notification = NotificationGroupManager.getInstance() .getNotificationGroup("UTBot events") - .createNotification(content, type) + .createNotification(title, content, type) notification.notify(project) - action?.let { notification.addAction(it) } + actions.filterNotNull().forEach { + notification.addAction(it) + } +} + +fun notifyNotConnected(project: Project? = null, port: Int, serverName: String) { + notifyError( + UTBot.message("notify.disconnected.title"), + UTBot.message("notify.disconnected", port, serverName), + project, + ShowSettingsAction(), + ReconnectAction() + ) } diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/utils/PathUtils.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/utils/PathUtils.kt index c469a7ed3..e9ad53d94 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/utils/PathUtils.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/utils/PathUtils.kt @@ -13,6 +13,8 @@ import java.nio.file.SimpleFileVisitor import java.nio.file.attribute.BasicFileAttributes import java.util.* import kotlin.io.path.div +import java.net.URI +import java.net.URISyntaxException val Project.path get() = this.basePath ?: error("Project path can't be null!") val Project.nioPath: Path get() = Paths.get(this.path) @@ -62,6 +64,19 @@ fun String.fileNameOrNull(): String? { } } +fun String.isLookLikeUnixPath(): Boolean { + return this.startsWith("/") && !this.contains("\\") +} + +fun String.isValidHostName(): Boolean { + try { + URI(null, null, this, 2121, null, null, null).authority + } catch (_: URISyntaxException) { + return false + } + return true +} + fun testFilePathToSourceFilePath(path: Path, project: Project): Path { val relativeToProject = project.settings.testsDirPath.relativize(path.parent) return (Paths.get(project.path) / relativeToProject / testFileNameToSourceFileName(path)) @@ -115,11 +130,14 @@ fun String.convertFromRemotePathIfNeeded(project: Project): Path { private fun String.convertToRemotePath(project: Project): String { val relativeToProjectPath = relativize(project.path, this) - return FilenameUtils.separatorsToUnix(Paths.get(project.settings.storedSettings.remotePath, relativeToProjectPath).toString()) + return FilenameUtils.separatorsToUnix( + Paths.get(project.settings.storedSettings.remotePath, relativeToProjectPath).toString() + ) } private fun String.convertFromRemotePath(project: Project): String { - val relativeToProjectPath = FilenameUtils.separatorsToSystem(relativize(project.settings.storedSettings.remotePath, this)) + val relativeToProjectPath = + FilenameUtils.separatorsToSystem(relativize(project.settings.storedSettings.remotePath, this)) return FilenameUtils.separatorsToSystem(Paths.get(project.path, relativeToProjectPath).toString()) } @@ -166,8 +184,11 @@ private fun removeSuffix(path: Path, suffix: String): Path { ) } -val VirtualFile.localPath: Path get() = this.fileSystem.getNioPath(this) ?: error("Could not get filesystem path from $this") +fun String.stripLeadingSlashes() = this.replace("""^[\\/]+""".toRegex(), "") + +val VirtualFile.localPath: Path + get() = this.fileSystem.getNioPath(this) ?: error("Could not get filesystem path from $this") private const val DOT_SEP = "_dot_" -private const val TEST_SUFFIX = "_test" \ No newline at end of file +private const val TEST_SUFFIX = "_test" diff --git a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/utils/UiUtils.kt b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/utils/UiUtils.kt index 5484f1079..3f190c997 100644 --- a/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/utils/UiUtils.kt +++ b/clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/utils/UiUtils.kt @@ -6,32 +6,54 @@ import com.intellij.openapi.Disposable import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.ui.ComponentValidator import com.intellij.openapi.ui.ValidationInfo -import com.intellij.ui.DocumentAdapter import com.intellij.ui.RawCommandLineEditor +import com.intellij.ui.components.JBTextField +import com.intellij.ui.dsl.builder.Cell import com.intellij.ui.dsl.builder.Row import com.intellij.ui.layout.PropertyBinding -import javax.swing.JSpinner +import javax.swing.JComponent import javax.swing.JTextField -import javax.swing.event.DocumentEvent fun invokeOnEdt(task: () -> Unit) { ApplicationManager.getApplication().invokeLater(task) } -fun JTextField.validateInput(parentDisposable: Disposable, validator: () -> ValidationInfo?) { +data class ValidationCondition(val errorText: String, val isValid: (JTextField) -> Boolean) +data class ComponentValidationInfo(val component: JComponent, val isValid: () -> Boolean) + +fun Cell.addValidation(vararg conditions: ValidationCondition): ComponentValidationInfo { + this.validationOnInput { textField -> + conditions.forEach { condition -> + if (!condition.isValid(textField)) { + return@validationOnInput ValidationInfo(condition.errorText) + } + } + return@validationOnInput null + } + return ComponentValidationInfo(this.component) { + conditions.all { it.isValid(this.component) } + } +} + +fun JBTextField.validateInput( + parentDisposable: Disposable, + vararg conditions: ValidationCondition +): ComponentValidationInfo { + val validator: () -> ValidationInfo? = lmb@{ + for (condition in conditions) { + if (!condition.isValid(this)) { + return@lmb ValidationInfo(condition.errorText, this) + } + } + null + } + ComponentValidator(parentDisposable) .withValidator(validator) .installOn(this) + .andRegisterOnDocumentListener(this) - document.addDocumentListener( - object : DocumentAdapter() { - override fun textChanged(e: DocumentEvent) { - ComponentValidator - .getInstance(this@validateInput) - .ifPresent { v -> v.revalidate() } - } - } - ) + return ComponentValidationInfo(this) { conditions.all { it.isValid(this) } } } fun Row.commandLineEditor( diff --git a/clion-plugin/src/main/resources/messages/UTBot.properties b/clion-plugin/src/main/resources/messages/UTBot.properties index 945d7104a..98bc7cb0e 100644 --- a/clion-plugin/src/main/resources/messages/UTBot.properties +++ b/clion-plugin/src/main/resources/messages/UTBot.properties @@ -1,13 +1,15 @@ -name=UTBot plugin projectConfigure.configure=Configure Project projectConfigure.generate.buildDir=Generate build directory -projectConfigure.generate.json=Generate Missing Json Files +projectConfigure.generate.json=Generate Missing JSON Files projectConfigure.reconfigure=Reset cache and configure project wizard.show=Quickstart wizard -settings.project.sourcePaths=Source paths +settings.project.sourcePaths=Source paths: settings.project.buildDir=Build directory: settings.project.target=target path: +settings.project.target.wrong.conversion=Possibly wrong target path. Could not create relative path from remote path settings.project.testsDir=Tests directory: +settings.project.testsDir.wrong=Wrong relative path to tests directory +settings.project.sourcePaths.wrong.conversion=Possibly wrong source path. Could not create relative path from remote path or this path settings.project.remotePath=Path to project on remote machine settings.project.serverName=Server host name settings.project.port=Server port @@ -28,8 +30,8 @@ requests.check.description.progress=Checking project configuration... requests.json.description.progress=Generating json files... requests.buildDir.description.progress=Creating build directory... uri.wiki=https://github.com/UnitTestBot/UTBotCpp/wiki -deployment.utbotHost.description=UTBot Server host address. Learn more -deployment.utbotPort.description=UTBot Server port. Learn more +deployment.utbot.host.description=UTBot Server host address. Learn more +deployment.utbot.port.description=UTBot Server port. Learn more deployment.remotePath.description=Remote path configuration specifies the path to the project on a remote host. Empty value specifies local scenario (for Linux). Learn more paths.buildDirectory.description=Relative path to build directory with compile_commands.json and/or coverage.json. Learn more paths.target.description=Path to target which is passed to UTBot. You can select targets in UTBot targets tool window @@ -53,7 +55,54 @@ actions.enable.menu.enabled=Enabled actions.enable.menu.disabled=Enable actions.enable.enabled=UTBot: Plugin Enabled actions.enable.disabled=UTBot: Enable Plugin -warning.reconnecting=Reconnecting to server! Request won't be executed! Please try again, later. +notify.warning.reconnecting=Reconnecting to server! Request won't be executed! Please try again, later. +notify.warning.reconnecting.title=UTBot: Reconnecting +folderPath.wrong.conversion=Could not create relative path from remote path to folder path! Review your remote path in settings \ + and make sure folder you generate tests for is under project root. +filePath.wrong.conversion=Could not create relative path from remote path to file path! Review your remote path in settings \ + and make sure file you generate tests for is under project root. +# hardly it will ever happen +#0 - path name (e.g relative path to ...), #1 - path value +paths.invalid=Invalid {0}: {1}. Please review it in settings! +projectPath.wrong.conversion=Could not convert project path to remote version. Please, report this issue, here +testFilePath.wrong.conversion=Could not create relative path from remote path to test file! Please review your remote path in settings \ + and make sure test file is under project root. +notify.title.missingBuildDir=UTBot: Build directory not found +notify.missingBuildDir=Build directory does not exist on server filesystem! +notify.title.configured=UTBot: Project is configured +notify.configured=Project is configured, you are ready to generate tests! +notify.title.notConfigured=UTBot: Project not configured +notify.failed.to.create.build.dir.title=UTBot: Failed to Create Build Directory +notify.title.unknown.server.error=UTBot: Unknown Server Error +notify.unknown.server.error=Server threw an unknown exception +notify.title.cancelled=UTBot: Request was cancelled +#0 - exception message, #1 - request id +notify.cancelled={0}
Request "{1}" cancelled. +notify.request.failed={0}
Request "{1}" failed +notify.title.failed.precondition=UTBot: Failed Precondition +notify.title.error=UTBot: Error +notify.coverage.received.title=UTBot: Coverage gathered +notify.coverage.received=Coverage response received from server. +notify.build.dir.created.title=UTBot: Build Directory was created +#0 - name of a build directory +notify.build.dir.created=Build directory {0} was created +notify.tests.generated=UTBot: Tests generated +notify.bad.settings.title=UTBot: Error +#0 - Message containing info about bad path +notify.bad.path=Please check your settings. {0} +notify.cancelled.request.title=UTBot: Request cancelled +#0 - request id +notify.cancelled.request=Successfully cancelled: "{0}" +notify.connected.title=UTBot: Connection Established +notify.connected=Successfully pinged UTBot server on port: {0, number, #}, host: {1} +notify.disconnected.title=UTBot: No Connection +notify.disconnected=Please check your connection settings +#0 - name of a json file missing in the build dir (link_commands.json or compile_commands.json) +notify.missing.cdb.files=File {0} is missing in the build directory +show.settings.text=Go to Settings +validation.not.empty=Please fill in this field +validation.not.unix.path=This path must be an absolute unix path! +validation.invalid.host=Invalid host name toolwindow.targets.displayName=Targets toolwindow.logs.displayName=Logs actions.verbose.menu.enabled=Verbose Mode: On diff --git a/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/TestFixtureProxy.kt b/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/TestFixtureProxy.kt new file mode 100644 index 000000000..a14756ca6 --- /dev/null +++ b/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/TestFixtureProxy.kt @@ -0,0 +1,23 @@ +package org.utbot.cpp.clion.plugin + +import com.intellij.testFramework.fixtures.impl.TempDirTestFixtureImpl +import java.nio.file.Path + +/** + * Implementation of TempDirTestFixture that uses [testsDirectory] as + * a tempDirectory, and does not delete it on tearDown. + * + * Intellij Platform tests are based on files in temp directory, which is provided and managed by TempDirTestFixture. + * On tearDown, temp directory is deleted. + * it may be expensive to copy all project files to temporary directory. + * This class solves the problem, by using [testsDirectory] + * instead of some generated temp directory. + */ +class TestFixtureProxy(private val testsDirectory: Path) : TempDirTestFixtureImpl() { + override fun doCreateTempDirectory(): Path { + return testsDirectory + } + + // as the directory is not actually temporary, it should not be deleted + override fun deleteOnTearDown() = false +} diff --git a/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/TestUtil.kt b/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/TestUtil.kt index 223804b76..3930535a8 100644 --- a/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/TestUtil.kt +++ b/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/TestUtil.kt @@ -1,5 +1,13 @@ package org.utbot.cpp.clion.plugin +import com.intellij.openapi.actionSystem.ActionPlaces +import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.actionSystem.Presentation +import com.intellij.openapi.actionSystem.ex.ActionManagerEx +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.editor.ex.EditorEx +import com.intellij.testFramework.fixtures.CodeInsightTestFixture +import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory import com.intellij.util.io.exists import com.intellij.util.io.readText import kotlin.io.path.extension @@ -30,7 +38,8 @@ fun Path.assertTestFilesExist(sourceFileNames: List) { val name = testFile.nameWithoutExtension if (!name.endsWith("_stub") && !name.endsWith("_wrapper") && - testFile.extension != "mk") { + testFile.extension != "mk" + ) { val sourceFileName = testFile.name.removeTestSuffixes() if (sourceFileName !in visitedFile) { Logger.error("Unable to find a corresponding source file for test: ${testFile.name}") @@ -59,3 +68,32 @@ fun String.removeTestSuffixes(): String { fun Path.assertFileOrDirExists(message: String = "") { assert(this.exists()) { "$this does not exist!\n${message}" } } + +fun createActionEventFrom(editor: Editor): AnActionEvent { + val dataContext = (editor as EditorEx).dataContext + val actionManager = ActionManagerEx.getInstance() + return AnActionEvent(null, dataContext, ActionPlaces.UNKNOWN, Presentation(), actionManager, 0); +} + +/** + * moves caret to beginning of the line with [lineNumber] + * + * @param lineNumber - 1-based line number + */ +fun Editor.moveCursorToLine(lineNumber: Int) { + this.caretModel.moveToOffset(this.document.getLineStartOffset(lineNumber - 1)) +} + +fun createFixture(projectPath: Path): CodeInsightTestFixture { + Logger.info("Creating fixture") + val fixture = IdeaTestFixtureFactory.getFixtureFactory().let { + it.createCodeInsightFixture( + it.createFixtureBuilder(projectPath.name, projectPath, false).fixture, + TestFixtureProxy(projectPath) + ) + } + fixture.setUp() + fixture.testDataPath = projectPath.toString() + Logger.info("Finished creating fixture") + return fixture +} diff --git a/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/buildingRequestsTests/BaseBuildingTest.kt b/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/buildingRequestsTests/BaseBuildingTest.kt new file mode 100644 index 000000000..2883face7 --- /dev/null +++ b/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/buildingRequestsTests/BaseBuildingTest.kt @@ -0,0 +1,92 @@ +package org.utbot.cpp.clion.plugin.tests.buildingRequestsTests + +import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.actionSystem.ex.ActionUtil +import com.intellij.openapi.project.Project +import com.intellij.testFramework.fixtures.CodeInsightTestFixture +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.extension.ExtendWith +import org.utbot.cpp.clion.plugin.SwingEdtInterceptor +import org.utbot.cpp.clion.plugin.actions.generate.GenerateForLineAction +import org.utbot.cpp.clion.plugin.client.logger.SystemWriter +import org.utbot.cpp.clion.plugin.createActionEventFrom +import org.utbot.cpp.clion.plugin.createFixture +import org.utbot.cpp.clion.plugin.moveCursorToLine +import org.utbot.cpp.clion.plugin.settings.UTBotProjectStoredSettings +import org.utbot.cpp.clion.plugin.settings.settings +import org.utbot.cpp.clion.plugin.utils.logger +import testsgen.Testgen +import java.io.File +import java.nio.file.Path +import java.nio.file.Paths + +@ExtendWith(SwingEdtInterceptor::class) +open class BaseBuildingTest { + val projectPath: Path = + Paths.get(File(".").canonicalPath).resolve("../integration-tests/c-example-mini").normalize() + protected val testsDirRelativePath = "cl-plugin-test-tests" + protected val testsDirectoryPath: Path = projectPath.resolve(testsDirRelativePath) + protected val buildDirRelativePath = "build" + protected val fixture: CodeInsightTestFixture = createFixture(projectPath) + protected val project: Project + get() = fixture.project + val settings = project.settings.storedSettings + + init { + settings.buildDirRelativePath = buildDirRelativePath + settings.testDirRelativePath = projectPath.relativize(testsDirectoryPath).toString() + settings.isPluginEnabled = true + project.logger.logWriters.let { + it.clear() + it.add(SystemWriter()) + } + } + + @AfterEach + fun tearDown() { + fixture.tearDown() + } + + // HELPER METHODS: + + protected fun createExpectedProjectContext(remotePath: String): Testgen.ProjectContext { + val isRemote = isRemoteScenarioExpectedInTests(remotePath) + return Testgen.ProjectContext.newBuilder().apply { + projectPath = if (isRemote) remotePath else this@BaseBuildingTest.projectPath.toString() + projectName = project.name + testDirPath = + if (isRemote) "$remotePath/$testsDirRelativePath" else this@BaseBuildingTest.testsDirectoryPath.toString() + buildDirRelativePath = this@BaseBuildingTest.buildDirRelativePath + }.build() + } + + protected fun createExpectedSettingsContextFromCurrentSettings(): Testgen.SettingsContext { + return Testgen.SettingsContext.newBuilder().apply { + generateForStaticFunctions = settings.generateForStaticFunctions + verbose = settings.verbose + timeoutPerFunction = settings.timeoutPerFunction + timeoutPerTest = settings.timeoutPerTest + useDeterministicSearcher = settings.useDeterministicSearcher + useStubs = settings.useStubs + }.build() + } + + protected fun isRemoteScenarioExpectedInTests(remotePath: String): Boolean = + remotePath != UTBotProjectStoredSettings.REMOTE_PATH_VALUE_FOR_LOCAL_SCENARIO + + protected fun setRemoteScenarioInPlugin(remotePath: String) { + settings.remotePath = remotePath + } + + fun createActionEventFromEditor(relativeFilePath: String, lineNumber: Int? = null): AnActionEvent { + fixture.configureFromTempProjectFile(relativeFilePath) + val editor = fixture.editor ?: error("Fixture's editor is null") + if (lineNumber != null) + editor.moveCursorToLine(lineNumber) + val event = createActionEventFrom(editor) + val action = GenerateForLineAction() + ActionUtil.performDumbAwareUpdate(action, event, true) + + return event + } +} \ No newline at end of file diff --git a/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/buildingRequestsTests/FileRequestBuildingTest.kt b/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/buildingRequestsTests/FileRequestBuildingTest.kt new file mode 100644 index 000000000..3f0ce2fb2 --- /dev/null +++ b/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/buildingRequestsTests/FileRequestBuildingTest.kt @@ -0,0 +1,45 @@ +package org.utbot.cpp.clion.plugin.tests.buildingRequestsTests + +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test +import org.utbot.cpp.clion.plugin.grpc.RemoteMapping +import org.utbot.cpp.clion.plugin.settings.UTBotProjectStoredSettings +import org.utbot.cpp.clion.plugin.utils.getBuilderForFileRequest +import testsgen.Testgen + +class FileRequestBuildingTest : BaseBuildingTest() { + private fun doTest( + testedFileRelativePath: String, + remotePath: String = UTBotProjectStoredSettings.REMOTE_PATH_VALUE_FOR_LOCAL_SCENARIO + ) { + setRemoteScenarioInPlugin(remotePath) + val isRemoteExpected = isRemoteScenarioExpectedInTests(remotePath) + + val actualRequest: Testgen.FileRequest = + createActionEventFromEditor(testedFileRelativePath).getBuilderForFileRequest().build(RemoteMapping(project)) + + val expectedRequest: Testgen.FileRequest = Testgen.FileRequest.newBuilder().apply { + projectRequest = Testgen.ProjectRequest.newBuilder().apply { + targetPath = settings.targetPath + synchronizeCode = isRemoteExpected + projectContext = this@FileRequestBuildingTest.createExpectedProjectContext(remotePath) + settingsContext = this@FileRequestBuildingTest.createExpectedSettingsContextFromCurrentSettings() + }.build() + filePath = if (isRemoteExpected) "$remotePath/$testedFileRelativePath" else projectPath.resolve( + testedFileRelativePath + ).toString() + }.build() + + Assertions.assertEquals(expectedRequest, actualRequest) + } + + @Test + fun `test generateForFile grpc request is built correctly from action event in local scenario`() { + doTest("lib/basic_functions.c") + } + + @Test + fun `test grpc FileRequest is built correctly from action event in remote scenario`() { + doTest("lib/basic_functions.c", "/some/remote/path/${project.name}") + } +} diff --git a/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/buildingRequestsTests/LineRequestBuildingTest.kt b/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/buildingRequestsTests/LineRequestBuildingTest.kt new file mode 100644 index 000000000..d7518aaf3 --- /dev/null +++ b/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/buildingRequestsTests/LineRequestBuildingTest.kt @@ -0,0 +1,56 @@ +package org.utbot.cpp.clion.plugin.tests.buildingRequestsTests + +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test +import org.utbot.cpp.clion.plugin.grpc.RemoteMapping +import org.utbot.cpp.clion.plugin.settings.UTBotProjectStoredSettings +import org.utbot.cpp.clion.plugin.tests.integrationTests.GenerateForLineTest +import org.utbot.cpp.clion.plugin.utils.getBuilderForLineRequest +import testsgen.Testgen +import testsgen.Util + +class LineRequestBuildingTest : BaseBuildingTest() { + private fun doTest( + testedFileRelativeFilePath: String, + lineNumber: Int, // 1-indexed + remotePath: String = UTBotProjectStoredSettings.REMOTE_PATH_VALUE_FOR_LOCAL_SCENARIO + ) { + this.setRemoteScenarioInPlugin(remotePath) + val isRemoteExpected = this.isRemoteScenarioExpectedInTests(remotePath) + + val actualRequest: Testgen.LineRequest = + this.createActionEventFromEditor(testedFileRelativeFilePath, lineNumber) + .getBuilderForLineRequest().build(RemoteMapping(project)) + + val expectedRequest: Testgen.LineRequest = Testgen.LineRequest.newBuilder().apply { + projectRequest = Testgen.ProjectRequest.newBuilder().apply { + targetPath = settings.targetPath + synchronizeCode = isRemoteExpected + projectContext = createExpectedProjectContext(remotePath) + settingsContext = createExpectedSettingsContextFromCurrentSettings() + }.build() + sourceInfo = Util.SourceInfo.newBuilder().apply { + filePath = if (isRemoteExpected) "$remotePath/$testedFileRelativeFilePath" else projectPath.resolve( + testedFileRelativeFilePath + ).toString() + line = lineNumber + }.build() + }.build() + + Assertions.assertEquals(expectedRequest, actualRequest) + } + + @Test + fun `test grpc LineRequest is built correctly from action event in local scenario`() { + doTest("lib/basic_functions.c", GenerateForLineTest.IF_IN_MAX_FUNCTION_LINE) + } + + @Test + fun `test grpc LineRequest is built correctly from action event in remote scenario`() { + doTest( + "lib/basic_functions.c", + GenerateForLineTest.IF_IN_MAX_FUNCTION_LINE, + "/some/remote/path/${project.name}" + ) + } +} diff --git a/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/buildingRequestsTests/ProjectRequestBuildingTest.kt b/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/buildingRequestsTests/ProjectRequestBuildingTest.kt new file mode 100644 index 000000000..d5a79d718 --- /dev/null +++ b/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/buildingRequestsTests/ProjectRequestBuildingTest.kt @@ -0,0 +1,37 @@ +package org.utbot.cpp.clion.plugin.tests.buildingRequestsTests + +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test +import org.utbot.cpp.clion.plugin.grpc.GrpcRequestBuilderFactory +import org.utbot.cpp.clion.plugin.grpc.RemoteMapping +import org.utbot.cpp.clion.plugin.settings.UTBotProjectStoredSettings +import testsgen.Testgen + +class ProjectRequestBuildingTest : BaseBuildingTest() { + private fun doTest(remotePath: String = UTBotProjectStoredSettings.REMOTE_PATH_VALUE_FOR_LOCAL_SCENARIO) { + setRemoteScenarioInPlugin(remotePath) + val isRemoteExpected = isRemoteScenarioExpectedInTests(remotePath) + + val actualRequest: Testgen.ProjectRequest = + GrpcRequestBuilderFactory(project).createProjectRequestBuilder().build(RemoteMapping(project)) + + val expectedRequest: Testgen.ProjectRequest = Testgen.ProjectRequest.newBuilder().apply { + targetPath = settings.targetPath + synchronizeCode = isRemoteExpected + projectContext = createExpectedProjectContext(remotePath) + settingsContext = createExpectedSettingsContextFromCurrentSettings() + }.build() + + Assertions.assertEquals(expectedRequest, actualRequest) + } + + @Test + fun `test grpc ProjectRequest is built correctly in local scenario`() { + doTest(UTBotProjectStoredSettings.REMOTE_PATH_VALUE_FOR_LOCAL_SCENARIO) + } + + @Test + fun `test grpc ProjectRequest is built correctly in remote scenario`() { + doTest("/some/remote/path") + } +} diff --git a/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/BaseGenerationTestCase.kt b/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/integrationTests/BaseGenerationTestCase.kt similarity index 69% rename from clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/BaseGenerationTestCase.kt rename to clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/integrationTests/BaseGenerationTestCase.kt index 2d82ced40..3db3cee0a 100644 --- a/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/BaseGenerationTestCase.kt +++ b/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/integrationTests/BaseGenerationTestCase.kt @@ -1,61 +1,40 @@ -package org.utbot.cpp.clion.plugin +package org.utbot.cpp.clion.plugin.tests.integrationTests import com.intellij.openapi.components.service import com.intellij.openapi.project.Project import com.intellij.testFramework.PlatformTestUtil -import com.intellij.testFramework.TestLoggerFactory import com.intellij.testFramework.fixtures.CodeInsightTestFixture -import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory -import com.intellij.testFramework.fixtures.impl.TempDirTestFixtureImpl import com.intellij.util.io.delete +import kotlinx.coroutines.Job +import kotlinx.coroutines.TimeoutCancellationException +import kotlinx.coroutines.delay +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withTimeout import org.junit.jupiter.api.AfterAll import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.TestInstance import org.junit.jupiter.api.extension.ExtendWith +import org.tinylog.kotlin.Logger +import org.utbot.cpp.clion.plugin.SwingEdtInterceptor +import org.utbot.cpp.clion.plugin.client.ManagedClient import org.utbot.cpp.clion.plugin.client.logger.SystemWriter +import org.utbot.cpp.clion.plugin.createFixture import org.utbot.cpp.clion.plugin.settings.settings +import org.utbot.cpp.clion.plugin.ui.utbotToolWindow.targetToolWindow.UTBotTargetsController +import org.utbot.cpp.clion.plugin.utils.client import org.utbot.cpp.clion.plugin.utils.logger import java.io.File import java.nio.file.Path import java.nio.file.Paths -import kotlin.io.path.name -import kotlinx.coroutines.Job -import kotlinx.coroutines.TimeoutCancellationException -import kotlinx.coroutines.delay -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.withTimeout -import org.tinylog.kotlin.Logger -import org.utbot.cpp.clion.plugin.client.ManagedClient -import org.utbot.cpp.clion.plugin.ui.utbotToolWindow.targetToolWindow.UTBotTargetsController -import org.utbot.cpp.clion.plugin.utils.client @TestInstance(TestInstance.Lifecycle.PER_CLASS) @ExtendWith(SwingEdtInterceptor::class) abstract class BaseGenerationTestCase { - /** - * Implementation of TempDirTestFixture that uses [testsDirectory] as - * a tempDirectory, and does not delete it on tearDown. - * - * Intellij Platform tests are based on files in temp directory, which is provided and managed by TempDirTestFixture. - * On tearDown, temp directory is deleted. - * it may be expensive to copy all project files to temporary directory. - * This class solves the problem, by using [testsDirectory] - * instead of some generated temp directory. - */ - class TestFixtureProxy(private val testsDirectory: Path) : TempDirTestFixtureImpl() { - override fun doCreateTempDirectory(): Path { - return testsDirectory - } - - // as the directory is not actually temporary, it should not be deleted - override fun deleteOnTearDown() = false - } - val projectPath: Path = Paths.get(File(".").canonicalPath).resolve("../integration-tests/c-example-mini").normalize() val testsDirectoryPath: Path = projectPath.resolve("cl-plugin-test-tests") val buildDirName = "build" - protected val fixture: CodeInsightTestFixture = createFixture() + protected val fixture: CodeInsightTestFixture = createFixture(projectPath) protected val project: Project get() = fixture.project protected val client: ManagedClient @@ -71,20 +50,6 @@ abstract class BaseGenerationTestCase { } } - private fun createFixture(): CodeInsightTestFixture { - Logger.info("Creating fixture") - val fixture = IdeaTestFixtureFactory.getFixtureFactory().let { - it.createCodeInsightFixture( - it.createFixtureBuilder(projectPath.name, projectPath, false).fixture, - TestFixtureProxy(projectPath) - ) - } - fixture.setUp() - fixture.testDataPath = projectPath.toString() - Logger.info("Finished creating fixture") - return fixture - } - fun setTarget(targetName: String) { val targetsController = project.service() assert(client.isServerAvailable()) { "Not connected to server!" } @@ -109,15 +74,16 @@ abstract class BaseGenerationTestCase { } protected fun waitForConnection(timeout: Long = 10000L) { + Logger.info { "Waiting for connection to server!" } runBlocking { try { withTimeout(timeout) { while (!client.isServerAvailable()) { delay(1000L) - Logger.info { "Waiting for connection to server!" } } } - } catch (_: TimeoutCancellationException) {} + } catch (_: TimeoutCancellationException) { + } assert(client.isServerAvailable()) { "Not connected to server!" } Logger.info { "Connected" } } @@ -136,4 +102,4 @@ abstract class BaseGenerationTestCase { fixture.tearDown() Logger.info("tearDownAll of BaseGenerationTest has finished!") } -} +} \ No newline at end of file diff --git a/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/CppCompiler.kt b/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/integrationTests/CppCompiler.kt similarity index 93% rename from clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/CppCompiler.kt rename to clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/integrationTests/CppCompiler.kt index 68195fea6..ff01966fe 100644 --- a/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/CppCompiler.kt +++ b/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/integrationTests/CppCompiler.kt @@ -1,6 +1,7 @@ -package org.utbot.cpp.clion.plugin +package org.utbot.cpp.clion.plugin.tests.integrationTests import org.tinylog.kotlin.Logger +import org.utbot.cpp.clion.plugin.assertFileOrDirExists import java.nio.file.Path abstract class CppCompiler { diff --git a/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/GenerateForFileTest.kt b/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/integrationTests/GenerateForFileTest.kt similarity index 88% rename from clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/GenerateForFileTest.kt rename to clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/integrationTests/GenerateForFileTest.kt index d094f19e3..5b052466a 100644 --- a/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/GenerateForFileTest.kt +++ b/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/integrationTests/GenerateForFileTest.kt @@ -1,10 +1,7 @@ -package org.utbot.cpp.clion.plugin.tests +package org.utbot.cpp.clion.plugin.tests.integrationTests import org.junit.jupiter.api.Test import org.tinylog.kotlin.Logger -import org.utbot.cpp.clion.plugin.BaseGenerationTestCase -import org.utbot.cpp.clion.plugin.Clang -import org.utbot.cpp.clion.plugin.CppCompiler import org.utbot.cpp.clion.plugin.assertAllFilesNotEmptyRecursively import org.utbot.cpp.clion.plugin.assertFileOrDirExists import org.utbot.cpp.clion.plugin.assertTestFilesExist @@ -34,4 +31,4 @@ class GenerateForFileTest : BaseGenerationTestCase() { fun `test generate for file with non-verbose mode`() { doTest("/lib/basic_functions.c", Clang, false) } -} +} \ No newline at end of file diff --git a/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/GenerateForIsolatedFileTest.kt b/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/integrationTests/GenerateForIsolatedFileTest.kt similarity index 81% rename from clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/GenerateForIsolatedFileTest.kt rename to clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/integrationTests/GenerateForIsolatedFileTest.kt index 65844cd9d..a5d3d8d66 100644 --- a/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/GenerateForIsolatedFileTest.kt +++ b/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/integrationTests/GenerateForIsolatedFileTest.kt @@ -1,9 +1,7 @@ -package org.utbot.cpp.clion.plugin.tests +package org.utbot.cpp.clion.plugin.tests.integrationTests import org.junit.jupiter.api.Test import org.tinylog.kotlin.Logger -import org.utbot.cpp.clion.plugin.BaseGenerationTestCase -import org.utbot.cpp.clion.plugin.Clang import org.utbot.cpp.clion.plugin.assertAllFilesNotEmptyRecursively import org.utbot.cpp.clion.plugin.assertFileOrDirExists import org.utbot.cpp.clion.plugin.assertTestFilesExist @@ -14,7 +12,8 @@ class GenerateForIsolatedFileTest : BaseGenerationTestCase() { fun testGenerateForFile() { val compiler = Clang Logger.info( - "Testing generate for snippet using target: auto, compiler: ${compiler.name}, verbose mode = ${project.settings.storedSettings.verbose}") + "Testing generate for snippet using target: auto, compiler: ${Clang.name}, verbose mode = ${project.settings.storedSettings.verbose}" + ) compiler.buildProject(projectPath, buildDirName) fixture.configureFromTempProjectFile("snippet.c") waitForConnection() @@ -24,4 +23,4 @@ class GenerateForIsolatedFileTest : BaseGenerationTestCase() { testsDirectoryPath.assertTestFilesExist(listOf("snippet")) testsDirectoryPath.assertAllFilesNotEmptyRecursively() } -} +} \ No newline at end of file diff --git a/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/GenerateForLineTest.kt b/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/integrationTests/GenerateForLineTest.kt similarity index 75% rename from clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/GenerateForLineTest.kt rename to clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/integrationTests/GenerateForLineTest.kt index f17462561..29078df24 100644 --- a/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/GenerateForLineTest.kt +++ b/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/integrationTests/GenerateForLineTest.kt @@ -1,16 +1,12 @@ -package org.utbot.cpp.clion.plugin.tests +package org.utbot.cpp.clion.plugin.tests.integrationTests -import com.intellij.openapi.editor.Editor import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.tinylog.kotlin.Logger -import org.utbot.cpp.clion.plugin.BaseGenerationTestCase -import org.utbot.cpp.clion.plugin.Clang -import org.utbot.cpp.clion.plugin.CppCompiler -import org.utbot.cpp.clion.plugin.Gcc import org.utbot.cpp.clion.plugin.assertAllFilesNotEmptyRecursively import org.utbot.cpp.clion.plugin.assertFileOrDirExists import org.utbot.cpp.clion.plugin.assertTestFilesExist +import org.utbot.cpp.clion.plugin.moveCursorToLine import org.utbot.cpp.clion.plugin.settings.settings @Disabled("Disabled as a flaky test until #483 is fixed") @@ -48,14 +44,9 @@ class GenerateForLineTest: BaseGenerationTestCase() { doTest(IF_IN_MAX_FUNCTION_LINE, compiler = Gcc) } - private fun Editor.moveCursorToLine(lineNumber: Int) { - this.caretModel.moveToOffset(this.document.getLineStartOffset(lineNumber)) - } - companion object { - // line numbers are assumed to start from 0 - const val HEAD_OF_MAX_LINE = 2 - const val IF_IN_MAX_FUNCTION_LINE = 3 + // line numbers are assumed to start from 1 + const val HEAD_OF_MAX_LINE = 3 + const val IF_IN_MAX_FUNCTION_LINE = 2 } -} - +} \ No newline at end of file diff --git a/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/GenerateForProjectTest.kt b/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/integrationTests/GenerateForProjectTest.kt similarity index 83% rename from clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/GenerateForProjectTest.kt rename to clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/integrationTests/GenerateForProjectTest.kt index ceffb7333..67d4a3ee3 100644 --- a/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/GenerateForProjectTest.kt +++ b/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/integrationTests/GenerateForProjectTest.kt @@ -1,13 +1,9 @@ -package org.utbot.cpp.clion.plugin.tests +package org.utbot.cpp.clion.plugin.tests.integrationTests import com.intellij.openapi.components.service import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.tinylog.kotlin.Logger -import org.utbot.cpp.clion.plugin.BaseGenerationTestCase -import org.utbot.cpp.clion.plugin.Clang -import org.utbot.cpp.clion.plugin.CppCompiler -import org.utbot.cpp.clion.plugin.Gcc import org.utbot.cpp.clion.plugin.actions.generate.GenerateForProjectAction import org.utbot.cpp.clion.plugin.assertFileOrDirExists import org.utbot.cpp.clion.plugin.assertTestFilesExist @@ -17,7 +13,7 @@ import org.utbot.cpp.clion.plugin.ui.utbotToolWindow.targetToolWindow.UTBotTarge @Disabled("Disabled as a flaky test until #483 is fixed") class GenerateForProjectTest : BaseGenerationTestCase() { private fun doTest(compiler: CppCompiler, isVerbose: Boolean, targetNames: List = emptyList()) { - Logger.info ( "Testing generate for project with ${compiler.name}, verbose mode: $isVerbose, and targets: ${targetNames.joinToString()}") + Logger.info("Testing generate for project with ${compiler.name}, verbose mode: $isVerbose, and targets: ${targetNames.joinToString()}") project.settings.storedSettings.verbose = isVerbose compiler.buildProject(projectPath, buildDirName) @@ -55,4 +51,4 @@ class GenerateForProjectTest : BaseGenerationTestCase() { fun `test generate for project with gcc, non-verbose mode`() { doTest(Gcc, false, emptyList()) } -} +} \ No newline at end of file diff --git a/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/utilsTests/ToWslFormatTest.kt b/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/utilsTests/ToWslFormatTest.kt index 1590cf452..bb23e8e32 100644 --- a/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/utilsTests/ToWslFormatTest.kt +++ b/clion-plugin/src/test/kotlin/org/utbot/cpp/clion/plugin/tests/utilsTests/ToWslFormatTest.kt @@ -5,7 +5,6 @@ import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.MethodSource import org.utbot.cpp.clion.plugin.utils.convertPathToWslFormat -import org.utbot.cpp.clion.plugin.utils.toWslFormatIfNeeded class ToWslFormatTest { @MethodSource("inputData") diff --git a/clion-plugin/src/test/resources/tinylog.properties b/clion-plugin/src/test/resources/tinylog.properties index 0cf7b7c28..c811d6215 100644 --- a/clion-plugin/src/test/resources/tinylog.properties +++ b/clion-plugin/src/test/resources/tinylog.properties @@ -1,2 +1,3 @@ writer = console +writer.level = ${PLUGIN_LOG_LEVEL:info} writer.format = {date: HH:mm:ss.SSS} | {file}: {line} [{thread}] {pipe}{level}{pipe} {message}