From 53e06d85c51f8f0f9ba5e535faeb7f6a9fbdcf88 Mon Sep 17 00:00:00 2001 From: Vladislav Artiukhov Date: Mon, 4 Dec 2023 16:04:57 +0200 Subject: [PATCH 1/8] Add classpath separator and isWindows method to Util class --- .../org/jetbrains/research/testspark/Util.kt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main/kotlin/org/jetbrains/research/testspark/Util.kt b/src/main/kotlin/org/jetbrains/research/testspark/Util.kt index 69aafc04c..a2f3e9d38 100644 --- a/src/main/kotlin/org/jetbrains/research/testspark/Util.kt +++ b/src/main/kotlin/org/jetbrains/research/testspark/Util.kt @@ -2,6 +2,7 @@ package org.jetbrains.research.testspark import com.intellij.openapi.util.io.FileUtilRt import java.io.File +import java.util.* class Util { companion object { @@ -22,5 +23,19 @@ class Util { dir.mkdirs() } } + + val classpathSeparator: Char + get() { + var sep = ':' + if (isWindows()) { + sep = ';' + } + return sep + } + + fun isWindows(): Boolean { + val os = System.getProperty("os.name").lowercase(Locale.getDefault()) + return (os.indexOf("win") >= 0) + } } } From 929ac31c98a8d555440dcd03011bb3d4cc26703b Mon Sep 17 00:00:00 2001 From: Vladislav Artiukhov Date: Mon, 4 Dec 2023 16:15:05 +0200 Subject: [PATCH 2/8] Replace wildcard import with single import --- src/main/kotlin/org/jetbrains/research/testspark/Util.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/org/jetbrains/research/testspark/Util.kt b/src/main/kotlin/org/jetbrains/research/testspark/Util.kt index a2f3e9d38..b0c69d423 100644 --- a/src/main/kotlin/org/jetbrains/research/testspark/Util.kt +++ b/src/main/kotlin/org/jetbrains/research/testspark/Util.kt @@ -2,7 +2,7 @@ package org.jetbrains.research.testspark import com.intellij.openapi.util.io.FileUtilRt import java.io.File -import java.util.* +import java.util.Locale class Util { companion object { From 5cd75dc1a4ae81411e51753e9a8b9ea7aa8b5996 Mon Sep 17 00:00:00 2001 From: Vladislav Artiukhov Date: Mon, 4 Dec 2023 16:16:46 +0200 Subject: [PATCH 3/8] Make RunCommandLineService.runCommandLine execute cmd CLI if target OS is Windows --- .../services/RunCommandLineService.kt | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/org/jetbrains/research/testspark/services/RunCommandLineService.kt b/src/main/kotlin/org/jetbrains/research/testspark/services/RunCommandLineService.kt index a5ab6b470..6bd95c662 100644 --- a/src/main/kotlin/org/jetbrains/research/testspark/services/RunCommandLineService.kt +++ b/src/main/kotlin/org/jetbrains/research/testspark/services/RunCommandLineService.kt @@ -2,6 +2,7 @@ package org.jetbrains.research.testspark.services import com.intellij.openapi.components.Service import com.intellij.openapi.project.Project +import org.jetbrains.research.testspark.Util import java.io.BufferedReader import java.io.InputStreamReader @@ -17,10 +18,21 @@ class RunCommandLineService(private val project: Project) { fun runCommandLine(cmd: ArrayList): String { var errorMessage = "" - val process = ProcessBuilder() - .command("bash", "-c", cmd.joinToString(" ")) - .redirectErrorStream(true) - .start() + /** + * Since Windows does not provide bash, use cmd or similar default command line interpreter + */ + val process = if (Util.isWindows()) { + ProcessBuilder() + .command("cmd", "/c", cmd.joinToString(" ")) + .redirectErrorStream(true) + .start() + } + else { + ProcessBuilder() + .command("bash", "-c", cmd.joinToString(" ")) + .redirectErrorStream(true) + .start() + } val reader = BufferedReader(InputStreamReader(process.inputStream)) var line: String? From cfb82b8dfa2f00e98f3b9060b6cbe8ec089c251c Mon Sep 17 00:00:00 2001 From: Vladislav Artiukhov Date: Mon, 4 Dec 2023 16:30:11 +0200 Subject: [PATCH 4/8] Make classpath separators & executables searching be OS-agnostic in TestCoverageCollectorService --- .../services/TestCoverageCollectorService.kt | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/org/jetbrains/research/testspark/services/TestCoverageCollectorService.kt b/src/main/kotlin/org/jetbrains/research/testspark/services/TestCoverageCollectorService.kt index 55ff7161c..e57d1d712 100644 --- a/src/main/kotlin/org/jetbrains/research/testspark/services/TestCoverageCollectorService.kt +++ b/src/main/kotlin/org/jetbrains/research/testspark/services/TestCoverageCollectorService.kt @@ -10,6 +10,7 @@ import com.intellij.openapi.roots.CompilerModuleExtension import com.intellij.openapi.roots.ModuleRootManager import com.intellij.openapi.roots.ProjectRootManager import com.intellij.openapi.util.io.FileUtilRt +import org.jetbrains.research.testspark.Util import org.jetbrains.research.testspark.data.TestCase import org.jetbrains.research.testspark.editor.Workspace import org.jetbrains.research.testspark.tools.getBuildPath @@ -47,7 +48,9 @@ class TestCoverageCollectorService(private val project: Project) { val hamcrestPath = "\"$pluginsPath${sep}TestSpark${sep}lib${sep}hamcrest-core-1.3.jar\"" val byteBuddy = "\"$pluginsPath${sep}TestSpark${sep}lib${sep}byte-buddy-1.14.6.jar\"" val byteBuddyAgent = "\"$pluginsPath${sep}TestSpark${sep}lib${sep}byte-buddy-agent-1.14.6.jar\"" - return "$junitPath:$hamcrestPath:$mockitoPath:$byteBuddy:$byteBuddyAgent:$buildPath" + + val sep = Util.classpathSeparator + return "$junitPath${sep}$hamcrestPath${sep}$mockitoPath${sep}$byteBuddy${sep}$byteBuddyAgent${sep}$buildPath" } /** @@ -71,7 +74,13 @@ class TestCoverageCollectorService(private val project: Project) { */ fun compileCode(path: String, projectBuildPath: String): Pair { // find the proper javac - val javaCompile = File(javaHomeDirectory.path).walk().filter { it.name.equals("javac") && it.isFile }.first() + val javaCompile = File(javaHomeDirectory.path).walk() + .filter { + val isCompilerName = if (Util.isWindows()) it.name.equals("javac.exe") else it.name.equals("javac") + isCompilerName && it.isFile + } + .first() + // compile file val errorMsg = project.service().runCommandLine( arrayListOf( @@ -135,7 +144,12 @@ class TestCoverageCollectorService(private val project: Project) { generatedTestPackage: String, ): String { // find the proper javac - val javaRunner = File(javaHomeDirectory.path).walk().filter { it.name.equals("java") && it.isFile }.first() + val javaRunner = File(javaHomeDirectory.path).walk() + .filter { + val isJavaName = if (Util.isWindows()) it.name.equals("java.exe") else it.name.equals("java") + isJavaName && it.isFile + } + .first() // JaCoCo libs val jacocoAgentDir = project.service().getLibrary("jacocoagent.jar") val jacocoCLIDir = project.service().getLibrary("jacococli.jar") @@ -151,7 +165,7 @@ class TestCoverageCollectorService(private val project: Project) { javaRunner.absolutePath, "-javaagent:$jacocoAgentDir=destfile=$dataFileName.exec,append=false,includes=${project.service().classFQN}", "-cp", - "${project.service().getPath(projectBuildPath)}${project.service().getLibrary("JUnitRunner.jar")}:$resultPath", + "${project.service().getPath(projectBuildPath)}${project.service().getLibrary("JUnitRunner.jar")}${Util.classpathSeparator}$resultPath", "org.jetbrains.research.SingleJUnitTestRunner", name, ), From c60a1663c3c1f0fbe636b37e294dddcb6bf829b4 Mon Sep 17 00:00:00 2001 From: Vladislav Artiukhov Date: Mon, 4 Dec 2023 16:39:00 +0200 Subject: [PATCH 5/8] Replace ':' with system agnostic classpath separator variable in ToolUtils --- .../org/jetbrains/research/testspark/tools/ToolUtils.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/org/jetbrains/research/testspark/tools/ToolUtils.kt b/src/main/kotlin/org/jetbrains/research/testspark/tools/ToolUtils.kt index 09b7a7e40..4a3df6d76 100644 --- a/src/main/kotlin/org/jetbrains/research/testspark/tools/ToolUtils.kt +++ b/src/main/kotlin/org/jetbrains/research/testspark/tools/ToolUtils.kt @@ -7,6 +7,7 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.roots.CompilerModuleExtension import com.intellij.openapi.roots.ModuleRootManager import org.jetbrains.research.testspark.TestSparkBundle +import org.jetbrains.research.testspark.Util import org.jetbrains.research.testspark.data.Report import org.jetbrains.research.testspark.editor.Workspace import org.jetbrains.research.testspark.services.ErrorService @@ -135,8 +136,8 @@ fun getBuildPath(project: Project): String { for (module in ModuleManager.getInstance(project).modules) { val compilerOutputPath = CompilerModuleExtension.getInstance(module)?.compilerOutputPath - compilerOutputPath?.let { buildPath += compilerOutputPath.path.plus(":") } + compilerOutputPath?.let { buildPath += compilerOutputPath.path.plus(Util.classpathSeparator.toString()) } // Include extra libraries in classpath val librariesPaths = ModuleRootManager.getInstance(module).orderEntries().librariesOnly().pathsList.pathList for (lib in librariesPaths) { @@ -157,7 +158,7 @@ fun getBuildPath(project: Project): String { continue } - buildPath += lib.plus(":") + buildPath += lib.plus(Util.classpathSeparator.toString()) } } return buildPath From 9d53eed8280a0080f151f5855de3b368357db194 Mon Sep 17 00:00:00 2001 From: Vladislav Artiukhov Date: Mon, 4 Dec 2023 16:43:54 +0200 Subject: [PATCH 6/8] Use File.separatorChar instead of '/' inside EvoSuite class --- .../jetbrains/research/testspark/tools/evosuite/EvoSuite.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/org/jetbrains/research/testspark/tools/evosuite/EvoSuite.kt b/src/main/kotlin/org/jetbrains/research/testspark/tools/evosuite/EvoSuite.kt index bce9279c9..ad51a0086 100644 --- a/src/main/kotlin/org/jetbrains/research/testspark/tools/evosuite/EvoSuite.kt +++ b/src/main/kotlin/org/jetbrains/research/testspark/tools/evosuite/EvoSuite.kt @@ -18,6 +18,7 @@ import org.jetbrains.research.testspark.helpers.generateMethodDescriptor import org.jetbrains.research.testspark.services.SettingsProjectService import org.jetbrains.research.testspark.tools.evosuite.generation.EvoSuiteProcessManager import org.jetbrains.research.testspark.tools.template.Tool +import java.io.File /** * Represents the EvoSuite class, which is a tool used to generate tests for Java code. @@ -32,7 +33,7 @@ class EvoSuite(override val name: String = "EvoSuite") : Tool { val project: Project = e.project!! val projectClassPath: String = ProjectRootManager.getInstance(project).contentRoots.first().path val settingsProjectState = project.service().state - val buildPath = "$projectClassPath/${settingsProjectState.buildPath}" + val buildPath = "$projectClassPath${File.separatorChar}${settingsProjectState.buildPath}" return EvoSuiteProcessManager(project, buildPath) } From 6e2b391245ae21b53e0a29199e3d3091c388afa2 Mon Sep 17 00:00:00 2001 From: Vladislav Artiukhov Date: Wed, 6 Dec 2023 17:05:13 +0200 Subject: [PATCH 7/8] Fix issue with inability to save tests into files due to '\r\n' insertions --- .../services/TestCaseDisplayService.kt | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/org/jetbrains/research/testspark/services/TestCaseDisplayService.kt b/src/main/kotlin/org/jetbrains/research/testspark/services/TestCaseDisplayService.kt index 34ba7ad6d..32756f64a 100644 --- a/src/main/kotlin/org/jetbrains/research/testspark/services/TestCaseDisplayService.kt +++ b/src/main/kotlin/org/jetbrains/research/testspark/services/TestCaseDisplayService.kt @@ -462,14 +462,20 @@ class TestCaseDisplayService(private val project: Project) { // insert tests to a code testCaseComponents.reversed().forEach { + val testMethodCode = project + .service() + .getTestMethodCodeFromClassWithTestCase( + project.service().formatJavaCode( + it.replace("\r\n", "\n") + .replace("verifyException(", "// verifyException(") + ) + ) + // Fix Windows line separators + .replace("\r\n", "\n") + PsiDocumentManager.getInstance(project).getDocument(outputFile)!!.insertString( selectedClass.rBrace!!.textRange.startOffset, - // Fix Windows line separators - project.service().getTestMethodCodeFromClassWithTestCase( - project.service().formatJavaCode( - it.replace("\r\n", "\n").replace("verifyException(", "// verifyException("), - ), - ), + testMethodCode, ) } From c73151dc9a571296d0c8a13c1127305916f79666 Mon Sep 17 00:00:00 2001 From: Vladislav Artiukhov Date: Wed, 6 Dec 2023 17:14:55 +0200 Subject: [PATCH 8/8] Apply ktlint --- .../services/RunCommandLineService.kt | 21 +++++++++---------- .../services/TestCaseDisplayService.kt | 4 ++-- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/main/kotlin/org/jetbrains/research/testspark/services/RunCommandLineService.kt b/src/main/kotlin/org/jetbrains/research/testspark/services/RunCommandLineService.kt index 6bd95c662..e0b304219 100644 --- a/src/main/kotlin/org/jetbrains/research/testspark/services/RunCommandLineService.kt +++ b/src/main/kotlin/org/jetbrains/research/testspark/services/RunCommandLineService.kt @@ -22,17 +22,16 @@ class RunCommandLineService(private val project: Project) { * Since Windows does not provide bash, use cmd or similar default command line interpreter */ val process = if (Util.isWindows()) { - ProcessBuilder() - .command("cmd", "/c", cmd.joinToString(" ")) - .redirectErrorStream(true) - .start() - } - else { - ProcessBuilder() - .command("bash", "-c", cmd.joinToString(" ")) - .redirectErrorStream(true) - .start() - } + ProcessBuilder() + .command("cmd", "/c", cmd.joinToString(" ")) + .redirectErrorStream(true) + .start() + } else { + ProcessBuilder() + .command("bash", "-c", cmd.joinToString(" ")) + .redirectErrorStream(true) + .start() + } val reader = BufferedReader(InputStreamReader(process.inputStream)) var line: String? diff --git a/src/main/kotlin/org/jetbrains/research/testspark/services/TestCaseDisplayService.kt b/src/main/kotlin/org/jetbrains/research/testspark/services/TestCaseDisplayService.kt index 32756f64a..2ee016ed8 100644 --- a/src/main/kotlin/org/jetbrains/research/testspark/services/TestCaseDisplayService.kt +++ b/src/main/kotlin/org/jetbrains/research/testspark/services/TestCaseDisplayService.kt @@ -467,8 +467,8 @@ class TestCaseDisplayService(private val project: Project) { .getTestMethodCodeFromClassWithTestCase( project.service().formatJavaCode( it.replace("\r\n", "\n") - .replace("verifyException(", "// verifyException(") - ) + .replace("verifyException(", "// verifyException("), + ), ) // Fix Windows line separators .replace("\r\n", "\n")