Skip to content

Commit 9cfd36d

Browse files
rudolf101tamarinvs19
authored andcommitted
Implement properly streams closure after running cmd in JavaScript (#1768)
* Implemented properly streams closure for JsCmdExec * Fix after update * Update logger info about output absolute path * Add logger for coverage report generation
1 parent aad2215 commit 9cfd36d

File tree

9 files changed

+50
-70
lines changed

9 files changed

+50
-70
lines changed

utbot-cli-js/src/main/kotlin/org/utbot/cli/js/JsRunTestsCommand.kt

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,22 +39,21 @@ class JsRunTestsCommand : CliktCommand(name = "run_js", help = "Runs tests for t
3939
val outputAbsolutePath = output?.let { makeAbsolutePath(it) }
4040
when (testFramework) {
4141
"mocha" -> {
42-
val (textReader, error) = JsCmdExec.runCommand(
42+
val (inputText, errorText) = JsCmdExec.runCommand(
4343
dir = dir,
44+
shouldWait = true,
4445
cmd = arrayOf("mocha", fileWithTestsAbsolutePath)
4546
)
46-
val errorText = error.readText()
4747
if (errorText.isNotEmpty()) {
48-
logger.error { "An error has occurred while running tests for $fileWithTests : $errorText" }
48+
logger.error { "An error has occurred while running tests for $fileWithTests: $errorText" }
4949
} else {
50-
val text = textReader.readText()
5150
outputAbsolutePath?.let {
5251
val file = File(it)
5352
file.createNewFile()
54-
file.writeText(text)
55-
} ?: logger.info { "\n$text" }
53+
file.writeText(inputText)
54+
} ?: logger.info { "Output absolute path is null with text: $inputText" }
5655
}
5756
}
5857
}
5958
}
60-
}
59+
}

utbot-intellij-js/src/main/kotlin/org/utbot/intellij/plugin/language/js/JsDialogProcessor.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,11 @@ object JsDialogProcessor {
105105
try {
106106
jsTestsModel?.pathToNode = NodeJsLocalInterpreterManager.getInstance()
107107
.interpreters.first().interpreterSystemIndependentPath
108-
val (_, error) = JsCmdExec.runCommand(
108+
val (_, errorText) = JsCmdExec.runCommand(
109109
shouldWait = true,
110110
cmd = arrayOf("node", "-v")
111111
)
112-
if (error.readText().isNotEmpty()) throw NoSuchElementException()
112+
if (errorText.isNotEmpty()) throw NoSuchElementException()
113113
} catch (e: NoSuchElementException) {
114114
Messages.showErrorDialog(
115115
"Node.js interpreter is not found in IDEA settings.\n" +
@@ -266,9 +266,8 @@ fun installMissingRequirement(project: Project, pathToNPM: String, requirement:
266266
if (result == Messages.CANCEL)
267267
return
268268

269-
val (_, errorStream) = installRequirement(pathToNPM, requirement, project.basePath)
269+
val (_, errorText) = installRequirement(pathToNPM, requirement, project.basePath)
270270

271-
val errorText = errorStream.readText()
272271
if (errorText.isNotEmpty()) {
273272
showErrorDialogLater(
274273
project,

utbot-intellij-js/src/main/kotlin/org/utbot/intellij/plugin/language/js/Utils.kt

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,35 +3,30 @@ package org.utbot.intellij.plugin.language.js
33
import com.intellij.openapi.ui.Messages
44
import utils.JsCmdExec
55
import utils.OsProvider
6-
import java.io.BufferedReader
76

87
fun getFrameworkLibraryPath(npmPackageName: String, model: JsTestsModel?): String? {
9-
val (bufferedReader, errorReader) = JsCmdExec.runCommand(
8+
val (inputText, _) = JsCmdExec.runCommand(
109
dir = model?.project?.basePath!!,
1110
shouldWait = true,
1211
timeout = 10,
1312
cmd = arrayOf(OsProvider.getProviderByOs().getAbstractivePathTool(), npmPackageName)
1413
)
15-
val input = bufferedReader.readText()
16-
val error = errorReader.readText()
1714

18-
if ((error.isNotEmpty() or !input.contains(npmPackageName)) && !findFrameworkLibrary(npmPackageName, model)) {
15+
if (!inputText.contains(npmPackageName) && !findFrameworkLibrary(npmPackageName, model)) {
1916
installMissingRequirement(model.project, model.pathToNPM, npmPackageName)
2017
return null
2118
}
22-
return input.substringBefore(npmPackageName) + npmPackageName
19+
return inputText.substringBefore(npmPackageName) + npmPackageName
2320
}
2421

2522
private fun npmListByFlag(model: JsTestsModel, flag: String): String {
26-
val (bufferReader, _) = JsCmdExec.runCommand(
23+
val (inputText, _) = JsCmdExec.runCommand(
2724
dir = model.project.basePath!!,
2825
shouldWait = true,
2926
timeout = 10,
3027
cmd = arrayOf(model.pathToNPM, "list", flag)
3128
)
32-
val packages = bufferReader.readText()
33-
bufferReader.close()
34-
return packages
29+
return inputText
3530
}
3631

3732
fun findFrameworkLibrary(npmPackageName: String, model: JsTestsModel): Boolean {
@@ -48,14 +43,15 @@ fun findFrameworkLibrary(npmPackageName: String, model: JsTestsModel): Boolean {
4843
return packageText.contains(npmPackageName)
4944
}
5045

51-
fun installRequirement(pathToNPM: String, requirement: String, installingDir: String?): Pair<BufferedReader, BufferedReader> {
46+
fun installRequirement(pathToNPM: String, requirement: String, installingDir: String?): Pair<String, String> {
5247
val installationType = if (requirement == "mocha") "-l" else "-g"
5348

54-
val (buf1, buf2) = JsCmdExec.runCommand(
49+
val (inputText, errorText) = JsCmdExec.runCommand(
5550
dir = installingDir,
5651
shouldWait = true,
5752
timeout = 10,
5853
cmd = arrayOf(pathToNPM, "install", installationType) + requirement
5954
)
60-
return buf1 to buf2
55+
56+
return Pair(inputText, errorText)
6157
}

utbot-js/src/main/kotlin/api/JsUtModelConstructor.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ import framework.api.js.JsUndefinedModel
88
import framework.api.js.util.jsErrorClassId
99
import framework.api.js.util.jsUndefinedClassId
1010
import fuzzer.providers.JsObjectModelProvider
11-
import org.utbot.framework.concrete.constructors.UtModelConstructorInterface
1211
import org.utbot.framework.plugin.api.ClassId
1312
import org.utbot.framework.plugin.api.UtAssembleModel
1413
import org.utbot.framework.plugin.api.UtExecutableCallModel
1514
import org.utbot.framework.plugin.api.UtModel
15+
import org.utbot.instrumentation.instrumentation.execution.constructors.UtModelConstructorInterface
1616

1717
class JsUtModelConstructor : UtModelConstructorInterface {
1818

utbot-js/src/main/kotlin/framework/codegen/model/constructor/tree/JsCgMethodConstructor.kt

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package framework.codegen.model.constructor.tree
22

3-
import org.utbot.framework.plugin.api.ConcreteExecutionFailureException
43
import org.utbot.framework.plugin.api.ConstructorId
54
import org.utbot.framework.plugin.api.ExecutableId
65
import org.utbot.framework.plugin.api.MethodId
@@ -10,7 +9,6 @@ import org.utbot.framework.plugin.api.onFailure
109
import org.utbot.framework.plugin.api.onSuccess
1110
import org.utbot.framework.plugin.api.util.voidClassId
1211
import org.utbot.framework.util.isUnit
13-
import java.security.AccessControlException
1412
import org.utbot.framework.codegen.domain.context.CgContext
1513
import org.utbot.framework.codegen.domain.models.CgTestMethod
1614
import org.utbot.framework.codegen.domain.models.CgTestMethodType
@@ -110,24 +108,9 @@ class JsCgMethodConstructor(ctx: CgContext) : CgMethodConstructor(ctx) {
110108
return
111109
}
112110

113-
when (exception) {
114-
is ConcreteExecutionFailureException -> {
115-
methodType = CgTestMethodType.CRASH
116-
writeWarningAboutCrash()
117-
}
118-
119-
is AccessControlException -> {
120-
methodType = CgTestMethodType.CRASH
121-
writeWarningAboutFailureTest(exception)
122-
return
123-
}
124-
125-
else -> {
126-
methodType = CgTestMethodType.FAILING
127-
writeWarningAboutFailureTest(exception)
128-
}
129-
}
111+
methodType = CgTestMethodType.FAILING
112+
writeWarningAboutFailureTest(exception)
130113

131114
methodInvocationBlock()
132115
}
133-
}
116+
}

utbot-js/src/main/kotlin/service/BasicCoverageService.kt

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
package service
22

3-
import java.io.File
4-
import java.util.Collections
53
import org.apache.commons.io.FileUtils
64
import org.json.JSONException
75
import org.json.JSONObject
86
import org.utbot.framework.plugin.api.TimeoutException
97
import settings.JsTestGenerationSettings.tempFileName
108
import utils.JsCmdExec
9+
import java.io.File
10+
import java.util.Collections
1111

1212
// TODO: 1. Make searching for file coverage in coverage report more specific, not just by file name.
1313
class BasicCoverageService(
@@ -102,7 +102,7 @@ class BasicCoverageService(
102102
private fun generateCoverageReport(filePath: String, index: Int) {
103103
try {
104104
with(context) {
105-
val (_, error) =
105+
val (_, errorText) =
106106
JsCmdExec.runCommand(
107107
cmd = arrayOf(
108108
settings.pathToNYC,
@@ -116,9 +116,8 @@ class BasicCoverageService(
116116
dir = context.projectPath,
117117
timeout = settings.timeout,
118118
)
119-
val errText = error.readText()
120-
if (errText.isNotEmpty()) {
121-
println(errText)
119+
if (errorText.isNotEmpty()) {
120+
println(errorText)
122121
}
123122
}
124123
} catch (e: TimeoutException) {
@@ -142,4 +141,4 @@ class BasicCoverageService(
142141
file.writeText(scriptText)
143142
file.createNewFile()
144143
}
145-
}
144+
}

utbot-js/src/main/kotlin/service/FastCoverageService.kt

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
11
package service
22

3-
import java.io.File
4-
import java.util.Collections
3+
import mu.KotlinLogging
54
import org.apache.commons.io.FileUtils
65
import org.json.JSONException
76
import org.json.JSONObject
87
import settings.JsTestGenerationSettings.tempFileName
98
import utils.JsCmdExec
9+
import java.io.File
10+
import java.util.Collections
11+
12+
private val logger = KotlinLogging.logger {}
1013

1114
class FastCoverageService(
1215
private val context: ServiceContext,
1316
private val scriptTexts: List<String>,
1417
private val testCaseIndices: IntRange,
1518
private val baseCoverageScriptText: String,
16-
): ICoverageService {
19+
) : ICoverageService {
1720

1821
private val utbotDirPath = "${context.projectPath}/${context.utbotDir}"
1922
private val coverageList = mutableListOf<Pair<Int, JSONObject>>()
@@ -125,7 +128,7 @@ class FastCoverageService(
125128
private fun generateCoverageReport() {
126129
scriptTexts.indices.toList().parallelStream().forEach { parallelIndex ->
127130
with(context) {
128-
val (_, error) = JsCmdExec.runCommand(
131+
val (_, errorText) = JsCmdExec.runCommand(
129132
cmd = arrayOf(settings.pathToNode, "$utbotDirPath/$tempFileName$parallelIndex.js"),
130133
dir = context.projectPath,
131134
shouldWait = true,
@@ -137,13 +140,12 @@ class FastCoverageService(
137140
resFile.delete()
138141
val json = JSONObject(rawResult)
139142
val index = json.getInt("index")
140-
if (index != i) println("ERROR: index $index != i $i")
143+
if (index != i) logger.error { "ERROR: index $index != i $i" }
141144
coverageList.add(index to json.getJSONObject("s"))
142145
_resultList.add(index to json.get("result").toString())
143146
}
144-
val errText = error.readText()
145-
if (errText.isNotEmpty()) {
146-
println(errText)
147+
if (errorText.isNotEmpty()) {
148+
logger.error { errorText }
147149
}
148150
}
149151
}
@@ -155,4 +157,4 @@ class FastCoverageService(
155157
file.writeText(scriptText)
156158
file.createNewFile()
157159
}
158-
}
160+
}

utbot-js/src/main/kotlin/service/TernService.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import com.google.javascript.rhino.Node
44
import framework.api.js.JsClassId
55
import framework.api.js.JsMultipleClassId
66
import framework.api.js.util.jsUndefinedClassId
7-
import java.io.File
8-
import java.util.Locale
97
import org.json.JSONException
108
import org.json.JSONObject
119
import parser.JsParserUtils
@@ -16,6 +14,8 @@ import parser.JsParserUtils.getConstructor
1614
import utils.JsCmdExec
1715
import utils.MethodTypes
1816
import utils.constructClass
17+
import java.io.File
18+
import java.util.Locale
1919

2020
/*
2121
NOTE: this approach is quite bad, but we failed to implement alternatives.
@@ -80,6 +80,7 @@ test("${context.filePathToInference}")
8080
private fun installDeps(path: String) {
8181
JsCmdExec.runCommand(
8282
dir = path,
83+
shouldWait = true,
8384
cmd = arrayOf(context.settings.pathToNPM, "i", "tern", "-l")
8485
)
8586
}
@@ -92,15 +93,14 @@ test("${context.filePathToInference}")
9293

9394
private fun runTypeInferencer() {
9495
with(context) {
95-
val (reader, _) = JsCmdExec.runCommand(
96+
val (inputText, _) = JsCmdExec.runCommand(
9697
dir = "$projectPath/$utbotDir/",
9798
shouldWait = true,
9899
timeout = 20,
99100
cmd = arrayOf(settings.pathToNode, "${projectPath}/$utbotDir/ternScript.js"),
100101
)
101-
val text = reader.readText().replaceAfterLast("}", "")
102102
json = try {
103-
JSONObject(text)
103+
JSONObject(inputText.replaceAfterLast("}", ""))
104104
} catch (_: Throwable) {
105105
JSONObject()
106106
}
@@ -205,4 +205,4 @@ test("${context.filePathToInference}")
205205
classId
206206
}
207207
}
208-
}
208+
}

utbot-js/src/main/kotlin/utils/JsCmdExec.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package utils
22

33
import org.utbot.framework.plugin.api.TimeoutException
44
import settings.JsTestGenerationSettings.defaultTimeout
5-
import java.io.BufferedReader
65
import java.io.File
76
import java.util.concurrent.TimeUnit
87

@@ -13,7 +12,7 @@ object JsCmdExec {
1312
shouldWait: Boolean = false,
1413
timeout: Long = defaultTimeout,
1514
vararg cmd: String,
16-
): Pair<BufferedReader, BufferedReader> {
15+
): Pair<String, String> {
1716
val builder = ProcessBuilder(*OsProvider.getProviderByOs().getCmdPrefix(), *cmd)
1817
dir?.let {
1918
builder.directory(File(it))
@@ -28,6 +27,9 @@ object JsCmdExec {
2827
throw TimeoutException("")
2928
}
3029
}
31-
return Pair(process.inputStream.bufferedReader(), process.errorStream.bufferedReader())
30+
return Pair(
31+
process.inputStream.bufferedReader().use { it.readText() },
32+
process.errorStream.bufferedReader().use { it.readText() }
33+
)
3234
}
3335
}

0 commit comments

Comments
 (0)