diff options
Diffstat (limited to 'Tests/barTests/phbarTests.swift')
| -rw-r--r-- | Tests/barTests/phbarTests.swift | 53 |
1 files changed, 49 insertions, 4 deletions
diff --git a/Tests/barTests/phbarTests.swift b/Tests/barTests/phbarTests.swift index 6a2c4d5..982e728 100644 --- a/Tests/barTests/phbarTests.swift +++ b/Tests/barTests/phbarTests.swift @@ -1,8 +1,53 @@ +import Foundation +import Synchronization import Testing @testable import bar -@Test func example() async throws { - // Write your test here and use APIs like `#expect(...)` to check expected conditions. - // Swift Testing Documentation - // https://developer.apple.com/documentation/testing +/// Blocking Runner work stays off the cooperative executor. The outer deadline +/// also fails promptly if a regression prevents Runner from returning. +private func runCommand(_ command: String, env: [String: String] = [:]) throws -> (lines: [String], diagnostics: Data) { + let url = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString) + FileManager.default.createFile(atPath: url.path, contents: nil) + let output = try FileHandle(forWritingTo: url) + defer { try? FileManager.default.removeItem(at: url) } + let result = Mutex<[String]?>(nil) + let finished = DispatchSemaphore(value: 0) + DispatchQueue.global(qos: .utility).async { + let lines = Runner.run(command, env: env, errorOutput: output) + try? output.close() + result.withLock { $0 = lines } + finished.signal() + } + let completed = finished.wait(timeout: .now() + 5) == .success + try #require(completed, "Runner exceeded the five-second outer deadline") + return (try #require(result.withLock { $0 }), try Data(contentsOf: url)) +} + +@Test func drainsLargeStderrBeforeStdout() throws { + let result = try runCommand("/usr/bin/head -c 1048576 /dev/zero >&2; printf ' ready \\n'") + #expect(result.lines == [" ready "]) + #expect(result.diagnostics == Data(repeating: 0, count: 1048576)) +} + +@Test func drainsSimultaneousLargeStreams() throws { + let result = try runCommand("/usr/bin/head -c 1048576 /dev/zero >&2 & /usr/bin/head -c 1048576 /dev/zero; wait") + #expect(result.lines == [String(repeating: "\0", count: 1048576)]) + #expect(result.diagnostics == Data(repeating: 0, count: 1048576)) +} + +@Test func emptyCommandOutput() throws { + let result = try runCommand(":") + #expect(result.lines.isEmpty) + #expect(result.diagnostics.isEmpty) +} + +@Test func failedCommandForwardsDiagnostics() throws { + let result = try runCommand("printf 'ignored'; printf 'failure\\n' >&2; exit 7") + #expect(result.lines == ["ERROR"]) + #expect(result.diagnostics == Data("failure\n".utf8)) +} + +@Test func shellEnvironmentAndWhitespaceArePreserved() throws { + let result = try runCommand("printf ' %s \\n\\nlast\\n' \"$BAR_RUNNER_TEST\"; test -n \"$PATH\"", env: ["BAR_RUNNER_TEST": "value"]) + #expect(result.lines == [" value ", "", "last"]) } |
