Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Rewrite StreamGobbler #1692

Merged
merged 4 commits into from
Jun 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions diktat-test-framework/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ dependencies {
implementation(libs.apache.commons.cli)
implementation(libs.apache.commons.io)
implementation(libs.kotlin.logging)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.kotlin.multiplatform.diff)
testImplementation(libs.junit.jupiter)
testImplementation(libs.assertj.core)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
package com.saveourtool.diktat.test.framework.common

import mu.KotlinLogging

import java.io.IOException
import java.io.InputStream
import java.nio.charset.Charset
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.runBlocking

/**
* Class that wraps shell [command] and can execute it
*/
class LocalCommandExecutor internal constructor(private val command: String) {
class LocalCommandExecutor internal constructor(
private val command: String,
private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO,
) {
/**
* Execute [command]
*
Expand All @@ -18,17 +29,12 @@ class LocalCommandExecutor internal constructor(private val command: String) {
log.info { "Executing command: $command" }
val process = Runtime.getRuntime().exec(command)
process.outputStream.close()
val inputStream = process.inputStream
val outputGobbler = StreamGobbler(inputStream, "OUTPUT") { msg, ex ->
log.error(ex, msg)
}
outputGobbler.start()
val errorStream = process.errorStream
val errorGobbler = StreamGobbler(errorStream, "ERROR") { msg, ex ->
log.error(ex, msg)
return runBlocking {
ExecutionResult(
process.inputStream.readLinesAsync("OUTPUT", ioDispatcher).toList(),
process.errorStream.readLinesAsync("ERROR", ioDispatcher).toList(),
)
}
errorGobbler.start()
return ExecutionResult(outputGobbler.content, errorGobbler.content)
} catch (ex: IOException) {
log.error("Execution of $command failed", ex)
}
Expand All @@ -37,5 +43,22 @@ class LocalCommandExecutor internal constructor(private val command: String) {

companion object {
private val log = KotlinLogging.logger {}

/**
* @param streamType
* @param ioDispatcher
* @return [Flow] of strings from input stream
*/
fun InputStream.readLinesAsync(streamType: String, ioDispatcher: CoroutineDispatcher): Flow<String> = flow {
try {
val bufferedReader = this@readLinesAsync.bufferedReader(Charset.defaultCharset())
while (true) {
val line = bufferedReader.readLine() ?: break
emit(line)
}
} catch (ex: IOException) {
log.error(ex) { "Failed to consume and display the input stream of type $streamType." }
}
}.flowOn(ioDispatcher)
}
}
5 changes: 4 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ save-cli = "0.3.9"
ktor = "2.2.4"
okio = "3.3.0"
kotlinx-datetime = "0.4.0"
kotlinx-coroutines = "1.6.4"
kotlinx-coroutines = "1.7.1"
assertj = "3.24.2"
diktat = "2.0.0"
jgit = "6.5.0.202303070854-r"
Expand Down Expand Up @@ -102,6 +102,9 @@ kotlinx-serialization-json-jvm = { module = "org.jetbrains.kotlinx:kotlinx-seria
# another serialization
kaml = { module = "com.charleskorn.kaml:kaml", version.ref = "kaml" }

# kotlinx coroutines
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" }

#kotlin libs
kotlin-multiplatform-diff = { module = "io.github.petertrr:kotlin-multiplatform-diff", version.ref = "kotlin-multiplatform-diff" }

Expand Down