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

refactor: Bash command execution #2127

Merged
merged 1 commit into from
Aug 9, 2021
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
10 changes: 10 additions & 0 deletions test_runner/src/main/kotlin/ftl/adapter/CommandRunner.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package ftl.adapter

import ftl.api.Command
import ftl.client.runShellCommand

object CommandRunner :
Command.Fetch,
(Command) -> String by { (cmd, additionalPaths) ->
runShellCommand(cmd, additionalPaths)
}
12 changes: 12 additions & 0 deletions test_runner/src/main/kotlin/ftl/api/Bash.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package ftl.api

import ftl.adapter.CommandRunner

val runCommand: Command.Fetch get() = CommandRunner

data class Command(
val cmd: String,
val additionalPath: List<Pair<String, String>> = emptyList()
) {
interface Fetch : (Command) -> String
}
50 changes: 50 additions & 0 deletions test_runner/src/main/kotlin/ftl/client/RunShellCommand.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package ftl.client

import flank.common.isWindows
import ftl.run.exception.FlankGeneralError
import ftl.util.failed
import ftl.util.waitForResult

sealed class ShellEnvironment(val execution: String) {
object Bash : ShellEnvironment("Bash.exe")
object BinBash : ShellEnvironment("/bin/bash")
object Cmd : ShellEnvironment("cmd.exe")
object Default : ShellEnvironment(if (isWindows) "cmd.exe" else "/bin/bash")
}

fun runShellCommand(
cmd: String,
additionalPath: List<Pair<String, String>>
): String {
val process = ProcessBuilder(shell.execution, command, cmd)
.appendAdditionalPaths(additionalPath)
.redirectOutput(ProcessBuilder.Redirect.PIPE)
.redirectError(ProcessBuilder.Redirect.PIPE)
.start()

val result = process.waitForResult()

if (process.failed()) {
System.err.println("Error: ${result.stderr}")
throw FlankGeneralError("Command failed: $cmd")
}

return result.stdout.trim() + result.stderr.trim()
}

private fun ProcessBuilder.appendAdditionalPaths(
additionalPath: List<Pair<String, String>>
) = apply {
val envs: MutableMap<String, String> = environment()
additionalPath.onEach { (key, value) -> envs[key] = value }
}

private val shell: ShellEnvironment by lazy {
when {
isWindows -> ShellEnvironment.Cmd
else -> ShellEnvironment.BinBash
}
}

private val command: String
get() = if (isWindows) "/c" else "-c"
17 changes: 11 additions & 6 deletions test_runner/src/main/kotlin/ftl/ios/xctest/common/ParseObjTests.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ package ftl.ios.xctest.common
import flank.common.appDataDirectory
import flank.common.isMacOS
import flank.common.isWindows
import ftl.util.Bash
import ftl.api.Command
import ftl.api.runCommand

internal fun parseObjcTests(binary: String): List<String> {
installBinaries
Expand All @@ -15,12 +16,16 @@ internal fun parseObjcTests(binary: String): List<String> {
var cmd = if (!isWindows) "nm -U ${binary.quote()}" else "llvm-nm.exe -U ${binary.quote()}"
if (!isMacOS) cmd = if (isWindows) cmd.replace("\\", "/") else "PATH=~/.flank $cmd"

val path = if (isWindows) listOf(Pair("Path", "$appDataDirectory\\.flank\\;C:\\Windows\\System32\\"))
else emptyList()

val output = Bash.execute(cmd, path)
val command = Command(
cmd = cmd,
additionalPath = if (isWindows) {
listOf(Pair("Path", "$appDataDirectory\\.flank\\;C:\\Windows\\System32\\"))
} else {
emptyList()
}
)

output.lines().forEach { line ->
runCommand(command).lines().forEach { line ->
// 000089b0 t -[EarlGreyExampleTests testLayout]
// 00008330 t -[EarlGreyExampleTests testCustomAction]
val pattern = """.+\st\s-\[(.+\stest.+)]""".toRegex()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import flank.common.appDataDirectory
import flank.common.isLinux
import flank.common.isMacOS
import flank.common.isWindows
import ftl.util.Bash
import ftl.util.ShellEnvironment
import ftl.api.Command
import ftl.api.runCommand

internal fun parseSwiftTests(binary: String): List<String> {
installBinaries
Expand All @@ -25,14 +25,13 @@ internal fun parseSwiftTests(binary: String): List<String> {
}

val path = if (isWindows) {
listOf(Pair("Path", "$appDataDirectory\\.flank\\;C:\\Windows\\System32\\"), Pair("LD_LIBRARY_PATH", "$appDataDirectory\\.flank\\"))
listOf(
Pair("Path", "$appDataDirectory\\.flank\\;C:\\Windows\\System32\\"),
Pair("LD_LIBRARY_PATH", "$appDataDirectory\\.flank\\")
)
} else emptyList()

// https://github.com/linkedin/bluepill/blob/37e7efa42472222b81adaa0e88f2bd82aa289b44/Source/Shared/BPXCTestFile.m#L17-18
val shell = if (isWindows) ShellEnvironment.Cmd else ShellEnvironment.Default

val demangledOutput = Bash.execute(cmd, path, shell)
demangledOutput.lines().forEach { line ->
runCommand(Command(cmd, path)).lines().forEach { line ->
// _T025EarlGreyExampleTestsSwift0abceD0C10testLayoutyyF ---> EarlGreyExampleTestsSwift.EarlGreyExampleSwiftTests.testLayout() -> ()
// _T025EarlGreyExampleTestsSwift0abceD0C16testCustomActionyyF ---> EarlGreyExampleTestsSwift.EarlGreyExampleSwiftTests.testCustomAction() -> ()
// _$S25EarlGreyExampleTestsSwift0abceD0C14testThatThrowsyyKF ---> EarlGreyExampleTestsSwift.EarlGreyExampleSwiftTests.testThatThrows() throws -> ()
Expand Down
7 changes: 4 additions & 3 deletions test_runner/src/main/kotlin/ftl/mock/MockServer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,13 @@ import com.google.testing.model.TestExecution
import com.google.testing.model.TestMatrix
import com.google.testing.model.ToolResultsExecution
import com.google.testing.model.ToolResultsStep
import ftl.api.Command
import ftl.api.runCommand
import ftl.client.google.run.toClientInfoDetailList
import ftl.config.FtlConstants
import ftl.config.FtlConstants.JSON_FACTORY
import ftl.log.LogbackLogger
import ftl.run.exception.FlankGeneralError
import ftl.util.Bash
import ftl.util.StepOutcome.failure
import ftl.util.StepOutcome.flaky
import ftl.util.StepOutcome.inconclusive
Expand Down Expand Up @@ -420,9 +421,9 @@ object MockServer {
try {
server.start(wait = false)
} catch (e: BindException) {
val lsofOutput = Bash.execute("lsof -i :$port")
val lsofOutput = runCommand(Command("lsof -i :$port"))
val pid = lsofOutput.split("\n").last().split(Regex("\\s+"))[1]
Bash.execute("kill -9 $pid")
runCommand(Command("kill -9 $pid"))
Thread.sleep(2000)
server.start(wait = false)
}
Expand Down
45 changes: 0 additions & 45 deletions test_runner/src/main/kotlin/ftl/util/Bash.kt

This file was deleted.

21 changes: 12 additions & 9 deletions test_runner/src/test/kotlin/ftl/util/BashTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ package ftl.util
import com.google.common.truth.Truth.assertThat
import flank.common.isMacOS
import flank.common.isWindows
import ftl.api.Command
import ftl.api.runCommand
import ftl.run.exception.FlankGeneralError
import ftl.test.util.FlankTestRunner
import org.junit.Assume.assumeFalse
import org.junit.Test
import org.junit.runner.RunWith
import java.io.File
Expand All @@ -14,31 +17,31 @@ class BashTest {

@Test
fun executeStderr() {
if (isWindows) return
assertThat(Bash.execute("echo a 1>&2")).isEqualTo("a")
assumeFalse(isWindows)
assertThat(runCommand(Command("echo a 1>&2"))).isEqualTo("a")
}

@Test(expected = FlankGeneralError::class)
fun executeStderrExitCode1() {
if (isWindows) throw FlankGeneralError("Failure as is windows")
assertThat(Bash.execute("echo not an error 1>&2; exit 1")).isEmpty()
assertThat(runCommand(Command("echo not an error 1>&2; exit 1"))).isEmpty()
}

@Test
fun executeNoOutput() {
if (isWindows) return
assertThat(Bash.execute(" ")).isEmpty()
assumeFalse(isWindows)
assertThat(runCommand(Command(" "))).isEmpty()
}

@Test
fun executeSmallOutput() {
if (isWindows) return
assertThat(Bash.execute("echo ok")).isEqualTo("ok")
assumeFalse(isWindows)
assertThat(runCommand(Command("echo ok"))).isEqualTo("ok")
}

@Test
fun executeLargeOutput() {
if (isWindows) return
assumeFalse(isWindows)
// gohello is a binary that outputs 100k 'hi' to stdout
val os = if (isMacOS) {
"mac"
Expand All @@ -48,6 +51,6 @@ class BashTest {
val cmd = "./src/test/kotlin/ftl/fixtures/tmp/gohello/bin/$os/gohello"
// ensure binary is marked executable. unzip may have removed the executable bit.
File(cmd).setExecutable(true)
assertThat(Bash.execute(cmd).length).isEqualTo(200_000)
assertThat(runCommand(Command(cmd)).length).isEqualTo(200_000)
}
}