Template support for input parameters #4
@ -1,75 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
|
|
||||||
struct RunProcessTask {
|
|
||||||
|
|
||||||
// MARK: Type aliases
|
|
||||||
|
|
||||||
typealias Output = String
|
|
||||||
|
|
||||||
// MARK: Properties
|
|
||||||
|
|
||||||
private var process: Processable
|
|
||||||
|
|
||||||
// MARK: Initialisers
|
|
||||||
|
|
||||||
init(process: Processable) {
|
|
||||||
self.process = process
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Functions
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
mutating func callAsFunction(
|
|
||||||
path: String, arguments: [String] = []
|
|
||||||
) async throws (RunProcessError) -> Output {
|
|
||||||
process.executableURL = URL(at: path)
|
|
||||||
process.arguments = arguments
|
|
||||||
|
|
||||||
let pipeError = Pipe()
|
|
||||||
let pipeOutput = Pipe()
|
|
||||||
|
|
||||||
process.standardError = pipeError
|
|
||||||
process.standardOutput = pipeOutput
|
|
||||||
|
|
||||||
async let streamOutput = pipeOutput.availableData.append()
|
|
||||||
async let streamError = pipeError.availableData.append()
|
|
||||||
|
|
||||||
do {
|
|
||||||
try process.run()
|
|
||||||
|
|
||||||
let dataOutput = await streamOutput
|
|
||||||
let dataError = await streamError
|
|
||||||
|
|
||||||
guard dataError.isEmpty else {
|
|
||||||
guard let errorOutput = String(data: dataError, encoding: .utf8) else {
|
|
||||||
throw RunProcessError.unexpected
|
|
||||||
}
|
|
||||||
|
|
||||||
throw RunProcessError.output(errorOutput)
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let output = String(data: dataOutput, encoding: .utf8) else {
|
|
||||||
throw RunProcessError.unexpected
|
|
||||||
}
|
|
||||||
|
|
||||||
return await withCheckedContinuation { continuation in
|
|
||||||
process.terminationHandler = { _ in
|
|
||||||
continuation.resume(returning: output)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch let error as RunProcessError {
|
|
||||||
throw error
|
|
||||||
} catch {
|
|
||||||
throw RunProcessError.captured(error.localizedDescription)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Errors
|
|
||||||
|
|
||||||
public enum RunProcessError: Error, Equatable {
|
|
||||||
case captured(_ output: String)
|
|
||||||
case output(_ output: String)
|
|
||||||
case unexpected
|
|
||||||
}
|
|
@ -1,68 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
import Testing
|
|
||||||
|
|
||||||
@testable import ColibriLibrary
|
|
||||||
|
|
||||||
struct RunProcessTaskTests {
|
|
||||||
|
|
||||||
// MARK: Properties
|
|
||||||
|
|
||||||
private var process: Process
|
|
||||||
|
|
||||||
// MARK: Initialisers
|
|
||||||
|
|
||||||
init() {
|
|
||||||
self.process = Process()
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Functions tests
|
|
||||||
|
|
||||||
@Test(arguments: [Argument.empty, Argument.listAllInFolder])
|
|
||||||
func run(with arguments: [String]) async throws {
|
|
||||||
// GIVEN
|
|
||||||
var task = RunProcessTask(process: process)
|
|
||||||
|
|
||||||
// WHEN
|
|
||||||
let output = try await task(path: .ls, arguments: arguments)
|
|
||||||
|
|
||||||
// THEN
|
|
||||||
#expect(output.isEmpty == false)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(arguments: zip([Argument.help, Argument.listAllInPWD], Throw.outputs))
|
|
||||||
func runThrows(with arguments: [String], throws error: RunProcessError) async throws {
|
|
||||||
// GIVEN
|
|
||||||
var task = RunProcessTask(process: process)
|
|
||||||
|
|
||||||
// WHEN
|
|
||||||
// THEN
|
|
||||||
await #expect(throws: error) {
|
|
||||||
try await task(path: .ls, arguments: arguments)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - String+Constants
|
|
||||||
|
|
||||||
private extension String {
|
|
||||||
static let ls = "/bin/ls"
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Parameters
|
|
||||||
|
|
||||||
private extension RunProcessTaskTests {
|
|
||||||
enum Argument {
|
|
||||||
static let empty: [String] = []
|
|
||||||
static let help: [String] = ["--help"]
|
|
||||||
static let listAllInFolder: [String] = ["-la", "."]
|
|
||||||
static let listAllInPWD: [String] = ["-la", "~"]
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Throw {
|
|
||||||
static let outputs: [RunProcessError] = [
|
|
||||||
.output("ls: unrecognized option `--help\'\nusage: ls [-@ABCFGHILOPRSTUWXabcdefghiklmnopqrstuvwxy1%,] [--color=when] [-D format] [file ...]\n"),
|
|
||||||
.output("ls: ~: No such file or directory\n")
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user