From 97ad94713ce094c28ce9d9f0877ea23a7525bb88 Mon Sep 17 00:00:00 2001 From: saehejkang Date: Sat, 1 Nov 2025 20:18:44 -0700 Subject: [PATCH] refactor run function for stdin/stdout support --- .../Subcommands/Build/CLIBuildBase.swift | 6 +-- .../Subcommands/Images/TestCLIImages.swift | 10 ++-- .../Plugins/TestCLIPluginErrors.swift | 2 +- .../Subcommands/Run/TestCLIRunLifecycle.swift | 4 +- .../Subcommands/Run/TestCLIRunOptions.swift | 2 +- .../Subcommands/System/TestKernelSet.swift | 4 +- .../Volumes/TestCLIAnonymousVolumes.swift | 34 +++++++------- .../Subcommands/Volumes/TestCLIVolumes.swift | 46 +++++++++---------- Tests/CLITests/Utilities/CLITest.swift | 38 +++++++++------ 9 files changed, 77 insertions(+), 69 deletions(-) diff --git a/Tests/CLITests/Subcommands/Build/CLIBuildBase.swift b/Tests/CLITests/Subcommands/Build/CLIBuildBase.swift index d8c6305c..27e240da 100644 --- a/Tests/CLITests/Subcommands/Build/CLIBuildBase.swift +++ b/Tests/CLITests/Subcommands/Build/CLIBuildBase.swift @@ -252,7 +252,7 @@ class TestCLIBuildBase: CLITest { } func builderStart(cpus: Int64 = 2, memoryInGBs: Int64 = 2) throws { - let (_, error, status) = try run(arguments: [ + let (_, _, error, status) = try run(arguments: [ "builder", "start", "-c", @@ -266,7 +266,7 @@ class TestCLIBuildBase: CLITest { } func builderStop() throws { - let (_, error, status) = try run(arguments: [ + let (_, _, error, status) = try run(arguments: [ "builder", "stop", ]) @@ -276,7 +276,7 @@ class TestCLIBuildBase: CLITest { } func builderDelete(force: Bool = false) throws { - let (_, error, status) = try run( + let (_, _, error, status) = try run( arguments: [ "builder", "delete", diff --git a/Tests/CLITests/Subcommands/Images/TestCLIImages.swift b/Tests/CLITests/Subcommands/Images/TestCLIImages.swift index 7a54891b..4a936ab4 100644 --- a/Tests/CLITests/Subcommands/Images/TestCLIImages.swift +++ b/Tests/CLITests/Subcommands/Images/TestCLIImages.swift @@ -32,7 +32,7 @@ class TestCLIImagesCommand: CLITest { args.append("--all") } - let (_, error, status) = try run(arguments: args) + let (_, _, error, status) = try run(arguments: args) if status != 0 { throw CLIError.executionFailed("command failed: \(error)") } @@ -49,7 +49,7 @@ class TestCLIImagesCommand: CLITest { } func doListImages() throws -> [Image] { - let (output, error, status) = try run(arguments: [ + let (_, output, error, status) = try run(arguments: [ "image", "list", "--format", @@ -75,7 +75,7 @@ class TestCLIImagesCommand: CLITest { newName, ] - let (_, error, status) = try run(arguments: tagArgs) + let (_, _, error, status) = try run(arguments: tagArgs) if status != 0 { throw CLIError.executionFailed("command failed: \(error)") } @@ -323,7 +323,7 @@ extension TestCLIImagesCommand { "--output", tempFile.path(), ] - let (_, error, status) = try run(arguments: saveArgs) + let (_, _, error, status) = try run(arguments: saveArgs) if status != 0 { throw CLIError.executionFailed("command failed: \(error)") } @@ -344,7 +344,7 @@ extension TestCLIImagesCommand { "-i", tempFile.path(), ] - let (_, loadErr, loadStatus) = try run(arguments: loadArgs) + let (_, _, loadErr, loadStatus) = try run(arguments: loadArgs) if loadStatus != 0 { throw CLIError.executionFailed("command failed: \(loadErr)") } diff --git a/Tests/CLITests/Subcommands/Plugins/TestCLIPluginErrors.swift b/Tests/CLITests/Subcommands/Plugins/TestCLIPluginErrors.swift index ea891fd9..4d6694b5 100644 --- a/Tests/CLITests/Subcommands/Plugins/TestCLIPluginErrors.swift +++ b/Tests/CLITests/Subcommands/Plugins/TestCLIPluginErrors.swift @@ -23,7 +23,7 @@ struct TestCLIPluginErrors { // without the APIServer started, so DefaultCommand will fail to create // a PluginLoader and emit the improved guidance. let cli = try CLITest() - let (_, stderr, status) = try cli.run(arguments: ["nosuchplugin"]) // non-existent plugin name + let (_, _, stderr, status) = try cli.run(arguments: ["nosuchplugin"]) // non-existent plugin name #expect(status != 0) #expect(stderr.contains("container system start")) diff --git a/Tests/CLITests/Subcommands/Run/TestCLIRunLifecycle.swift b/Tests/CLITests/Subcommands/Run/TestCLIRunLifecycle.swift index bef9fb83..1a4128b3 100644 --- a/Tests/CLITests/Subcommands/Run/TestCLIRunLifecycle.swift +++ b/Tests/CLITests/Subcommands/Run/TestCLIRunLifecycle.swift @@ -55,7 +55,7 @@ class TestCLIRunLifecycle: CLITest { } try self.waitForContainerRunning(name) - let (output, _, status) = try self.run(arguments: ["start", name]) + let (_, output, _, status) = try self.run(arguments: ["start", name]) #expect(status == 0, "expected start to succeed on already running container") #expect(output.trimmingCharacters(in: .whitespacesAndNewlines) == name, "expected output to be container name") @@ -76,7 +76,7 @@ class TestCLIRunLifecycle: CLITest { } try self.waitForContainerRunning(name) - let (_, error, status) = try self.run(arguments: ["start", "-a", name]) + let (_, _, error, status) = try self.run(arguments: ["start", "-a", name]) #expect(status != 0, "expected start with attach to fail on already running container") #expect(error.contains("attach is currently unsupported on already running containers"), "expected error message about attach not supported") diff --git a/Tests/CLITests/Subcommands/Run/TestCLIRunOptions.swift b/Tests/CLITests/Subcommands/Run/TestCLIRunOptions.swift index 8f82a91a..92504b44 100644 --- a/Tests/CLITests/Subcommands/Run/TestCLIRunOptions.swift +++ b/Tests/CLITests/Subcommands/Run/TestCLIRunOptions.swift @@ -528,7 +528,7 @@ class TestCLIRunCommand: CLITest { } func getDefaultDomain() throws -> String? { - let (output, err, status) = try run(arguments: ["system", "property", "get", "dns.domain"]) + let (_, output, err, status) = try run(arguments: ["system", "property", "get", "dns.domain"]) try #require(status == 0, "default DNS domain retrieval returned status \(status): \(err)") let trimmedOutput = output.trimmingCharacters(in: .whitespacesAndNewlines) if trimmedOutput == "" { diff --git a/Tests/CLITests/Subcommands/System/TestKernelSet.swift b/Tests/CLITests/Subcommands/System/TestKernelSet.swift index 1ffea121..522d0d9c 100644 --- a/Tests/CLITests/Subcommands/System/TestKernelSet.swift +++ b/Tests/CLITests/Subcommands/System/TestKernelSet.swift @@ -41,7 +41,7 @@ class TestCLIKernelSet: CLITest { "--recommended", "--force", ] - let (_, error, status) = try run(arguments: arguments) + let (_, _, error, status) = try run(arguments: arguments) if status != 0 { throw CLIError.executionFailed("failed to reset kernel to recommended: \(error)") } @@ -56,7 +56,7 @@ class TestCLIKernelSet: CLITest { ] arguments.append(contentsOf: extraArgs) - let (_, error, status) = try run(arguments: arguments) + let (_, _, error, status) = try run(arguments: arguments) if status != 0 { throw CLIError.executionFailed("failed to set kernel: \(error)") } diff --git a/Tests/CLITests/Subcommands/Volumes/TestCLIAnonymousVolumes.swift b/Tests/CLITests/Subcommands/Volumes/TestCLIAnonymousVolumes.swift index fd21af6a..0c234335 100644 --- a/Tests/CLITests/Subcommands/Volumes/TestCLIAnonymousVolumes.swift +++ b/Tests/CLITests/Subcommands/Volumes/TestCLIAnonymousVolumes.swift @@ -29,7 +29,7 @@ class TestCLIAnonymousVolumes: CLITest { private func cleanupAllTestResources() { // Clean up test containers (force remove) - if let (output, _, status) = try? run(arguments: ["ls", "-a"]), status == 0 { + if let (_, output, _, status) = try? run(arguments: ["ls", "-a"]), status == 0 { let containers = output.components(separatedBy: .newlines) .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } .filter { $0.lowercased().starts(with: "test") } @@ -40,7 +40,7 @@ class TestCLIAnonymousVolumes: CLITest { } // Clean up test volumes (both anonymous and named) - if let (output, _, status) = try? run(arguments: ["volume", "list", "--quiet"]), status == 0 { + if let (_, output, _, status) = try? run(arguments: ["volume", "list", "--quiet"]), status == 0 { let volumes = output.components(separatedBy: .newlines) .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } .filter { isValidUUID($0) || $0.lowercased().starts(with: "test") } @@ -56,7 +56,7 @@ class TestCLIAnonymousVolumes: CLITest { } func getAnonymousVolumeNames() throws -> [String] { - let (output, error, status) = try run(arguments: ["volume", "list", "--quiet"]) + let (_, output, error, status) = try run(arguments: ["volume", "list", "--quiet"]) guard status == 0 else { throw CLIError.executionFailed("volume list failed: \(error)") } @@ -66,7 +66,7 @@ class TestCLIAnonymousVolumes: CLITest { } func volumeExists(name: String) throws -> Bool { - let (output, _, status) = try run(arguments: ["volume", "list", "--quiet"]) + let (_, output, _, status) = try run(arguments: ["volume", "list", "--quiet"]) guard status == 0 else { return false } let volumes = output.components(separatedBy: .newlines) .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } @@ -80,14 +80,14 @@ class TestCLIAnonymousVolumes: CLITest { } func doVolumeCreate(name: String) throws { - let (_, error, status) = try run(arguments: ["volume", "create", name]) + let (_, _, error, status) = try run(arguments: ["volume", "create", name]) if status != 0 { throw CLIError.executionFailed("volume create failed: \(error)") } } func doVolumeDeleteIfExists(name: String) { - let (_, _, _) = (try? run(arguments: ["volume", "rm", name])) ?? ("", "", 1) + let (_, _, _, _) = (try? run(arguments: ["volume", "rm", name])) ?? (nil, "", "", 1) } func doRemoveIfExists(name: String, force: Bool = false) { @@ -96,7 +96,7 @@ class TestCLIAnonymousVolumes: CLITest { args.append("--force") } args.append(name) - let (_, _, _) = (try? run(arguments: args)) ?? ("", "", 1) + let (_, _, _, _) = (try? run(arguments: args)) ?? (nil, "", "", 1) } @Test func testAnonymousVolumeCreationAndPersistence() async throws { @@ -115,7 +115,7 @@ class TestCLIAnonymousVolumes: CLITest { let beforeCount = try getAnonymousVolumeNames().count // Run container with --rm and anonymous volume - let (_, _, status) = try run(arguments: [ + let (_, _, _, status) = try run(arguments: [ "run", "--rm", "--name", @@ -133,7 +133,7 @@ class TestCLIAnonymousVolumes: CLITest { try await Task.sleep(for: .seconds(1)) // Verify container was removed - let (lsOutput, _, _) = try run(arguments: ["ls", "-a"]) + let (_, lsOutput, _, _) = try run(arguments: ["ls", "-a"]) let containers = lsOutput.components(separatedBy: .newlines) .filter { $0.contains(containerName) } #expect(containers.isEmpty, "container should be removed with --rm") @@ -206,7 +206,7 @@ class TestCLIAnonymousVolumes: CLITest { let beforeCount = try getAnonymousVolumeNames().count // Run with multiple anonymous volumes - let (_, _, status) = try run(arguments: [ + let (_, _, _, status) = try run(arguments: [ "run", "--rm", "--name", @@ -243,7 +243,7 @@ class TestCLIAnonymousVolumes: CLITest { let beforeCount = try getAnonymousVolumeNames().count // Use --mount syntax - let (_, _, status) = try run(arguments: [ + let (_, _, _, status) = try run(arguments: [ "run", "--rm", "--name", @@ -314,7 +314,7 @@ class TestCLIAnonymousVolumes: CLITest { let volumeName = volumeNames[0] // Inspect volume in JSON format - let (output, error, status) = try run(arguments: ["volume", "list", "--format", "json"]) + let (_, output, error, status) = try run(arguments: ["volume", "list", "--format", "json"]) #expect(status == 0, "volume list should succeed: \(error)") // Parse JSON to verify metadata @@ -351,7 +351,7 @@ class TestCLIAnonymousVolumes: CLITest { try waitForContainerRunning(containerName) // List volumes - let (output, error, status) = try run(arguments: ["volume", "list"]) + let (_, output, error, status) = try run(arguments: ["volume", "list"]) #expect(status == 0, "volume list should succeed: \(error)") // Verify TYPE column exists and shows both types @@ -381,7 +381,7 @@ class TestCLIAnonymousVolumes: CLITest { let beforeAnonCount = try getAnonymousVolumeNames().count // Run with both named and anonymous volumes, with --rm - let (_, _, status) = try run(arguments: [ + let (_, _, _, status) = try run(arguments: [ "run", "--rm", "--name", @@ -427,7 +427,7 @@ class TestCLIAnonymousVolumes: CLITest { doRemoveIfExists(name: containerName, force: true) // Manual deletion should succeed (volume is unmounted) - let (_, error, status) = try run(arguments: ["volume", "rm", volumeID]) + let (_, _, error, status) = try run(arguments: ["volume", "rm", volumeID]) #expect(status == 0, "manual deletion of unmounted anonymous volume should succeed: \(error)") // Verify volume is gone @@ -450,7 +450,7 @@ class TestCLIAnonymousVolumes: CLITest { let beforeCount = try getAnonymousVolumeNames().count // Run in detached mode with --rm - let (_, _, status) = try run(arguments: [ + let (_, _, _, status) = try run(arguments: [ "run", "-d", "--rm", @@ -467,7 +467,7 @@ class TestCLIAnonymousVolumes: CLITest { try await Task.sleep(for: .seconds(3)) // Container should be removed - let (lsOutput, _, _) = try run(arguments: ["ls", "-a"]) + let (_, lsOutput, _, _) = try run(arguments: ["ls", "-a"]) let containers = lsOutput.components(separatedBy: .newlines) .filter { $0.contains(containerName) } #expect(containers.isEmpty, "container should be auto-removed") diff --git a/Tests/CLITests/Subcommands/Volumes/TestCLIVolumes.swift b/Tests/CLITests/Subcommands/Volumes/TestCLIVolumes.swift index 49f83379..ad423195 100644 --- a/Tests/CLITests/Subcommands/Volumes/TestCLIVolumes.swift +++ b/Tests/CLITests/Subcommands/Volumes/TestCLIVolumes.swift @@ -22,21 +22,21 @@ import Testing class TestCLIVolumes: CLITest { func doVolumeCreate(name: String) throws { - let (_, error, status) = try run(arguments: ["volume", "create", name]) + let (_, _, error, status) = try run(arguments: ["volume", "create", name]) if status != 0 { throw CLIError.executionFailed("volume create failed: \(error)") } } func doVolumeDelete(name: String) throws { - let (_, error, status) = try run(arguments: ["volume", "rm", name]) + let (_, _, error, status) = try run(arguments: ["volume", "rm", name]) if status != 0 { throw CLIError.executionFailed("volume delete failed: \(error)") } } func doVolumeDeleteIfExists(name: String) { - let (_, _, _) = (try? run(arguments: ["volume", "rm", name])) ?? ("", "", 1) + let (_, _, _, _) = (try? run(arguments: ["volume", "rm", name])) ?? (nil, "", "", 1) } func doRemoveIfExists(name: String, force: Bool = false) { @@ -45,11 +45,11 @@ class TestCLIVolumes: CLITest { args.append("--force") } args.append(name) - let (_, _, _) = (try? run(arguments: args)) ?? ("", "", 1) + let (_, _, _, _) = (try? run(arguments: args)) ?? (nil, "", "", 1) } func doesVolumeDeleteFail(name: String) throws -> Bool { - let (_, _, status) = try run(arguments: ["volume", "rm", name]) + let (_, _, _, status) = try run(arguments: ["volume", "rm", name]) return status != 0 } @@ -134,7 +134,7 @@ class TestCLIVolumes: CLITest { try waitForContainerRunning(container1Name) // Try to run second container with same volume - should fail - let (_, _, status) = try run(arguments: ["run", "--name", container2Name, "-v", "\(volumeName):/data", alpine] + defaultContainerArgs) + let (_, _, _, status) = try run(arguments: ["run", "--name", container2Name, "-v", "\(volumeName):/data", alpine] + defaultContainerArgs) #expect(status != 0, "second container should fail when trying to use volume already in use") @@ -230,7 +230,7 @@ class TestCLIVolumes: CLITest { try doVolumeCreate(name: volumeName) // List volumes and verify it exists - let (output, error, status) = try run(arguments: ["volume", "list", "--quiet"]) + let (_, output, error, status) = try run(arguments: ["volume", "list", "--quiet"]) if status != 0 { throw CLIError.executionFailed("volume list failed: \(error)") } @@ -242,7 +242,7 @@ class TestCLIVolumes: CLITest { #expect(volumes.contains(volumeName), "created volume should appear in list") // Inspect volume - let (inspectOutput, inspectError, inspectStatus) = try run(arguments: ["volume", "inspect", volumeName]) + let (_, inspectOutput, inspectError, inspectStatus) = try run(arguments: ["volume", "inspect", volumeName]) if inspectStatus != 0 { throw CLIError.executionFailed("volume inspect failed: \(inspectError)") } @@ -264,12 +264,12 @@ class TestCLIVolumes: CLITest { } // Verify volume doesn't exist yet - let (listOutput, _, _) = try run(arguments: ["volume", "list", "--quiet"]) + let (_, listOutput, _, _) = try run(arguments: ["volume", "list", "--quiet"]) let volumeExistsBefore = listOutput.contains(volumeName) #expect(!volumeExistsBefore, "volume should not exist initially") // Run container with non-existent named volume - should auto-create - let (output, _, status) = try run(arguments: [ + let (_, output, _, status) = try run(arguments: [ "run", "--name", containerName, @@ -283,7 +283,7 @@ class TestCLIVolumes: CLITest { #expect(output.contains("test"), "container should run successfully") // Volume should now exist - let (listOutputAfter, _, _) = try run(arguments: ["volume", "list", "--quiet"]) + let (_, listOutputAfter, _, _) = try run(arguments: ["volume", "list", "--quiet"]) let volumeExistsAfter = listOutputAfter.contains(volumeName) #expect(volumeExistsAfter, "volume should be created") } @@ -301,7 +301,7 @@ class TestCLIVolumes: CLITest { } // First container - should auto-create volume - let (_, _, status1) = try run(arguments: [ + let (_, _, _, status1) = try run(arguments: [ "run", "--name", containerName1, @@ -313,7 +313,7 @@ class TestCLIVolumes: CLITest { #expect(status1 == 0, "first container should succeed") // Second container - should reuse existing volume - let (_, _, status2) = try run(arguments: [ + let (_, _, _, status2) = try run(arguments: [ "run", "--name", containerName2, @@ -327,7 +327,7 @@ class TestCLIVolumes: CLITest { @Test func testVolumePruneNoVolumes() throws { // Prune with no volumes should succeed with 0 reclaimed - let (output, error, status) = try run(arguments: ["volume", "prune"]) + let (_, output, error, status) = try run(arguments: ["volume", "prune"]) if status != 0 { throw CLIError.executionFailed("volume prune failed: \(error)") } @@ -351,13 +351,13 @@ class TestCLIVolumes: CLITest { try doVolumeCreate(name: volumeName1) try doVolumeCreate(name: volumeName2) - let (listBefore, _, statusBefore) = try run(arguments: ["volume", "list", "--quiet"]) + let (_, listBefore, _, statusBefore) = try run(arguments: ["volume", "list", "--quiet"]) #expect(statusBefore == 0) #expect(listBefore.contains(volumeName1)) #expect(listBefore.contains(volumeName2)) // Prune should remove both - let (output, error, status) = try run(arguments: ["volume", "prune"]) + let (_, output, error, status) = try run(arguments: ["volume", "prune"]) if status != 0 { throw CLIError.executionFailed("volume prune failed: \(error)") } @@ -367,7 +367,7 @@ class TestCLIVolumes: CLITest { #expect(output.contains("Reclaimed"), "should show reclaimed space") // Verify volumes are gone - let (listAfter, _, statusAfter) = try run(arguments: ["volume", "list", "--quiet"]) + let (_, listAfter, _, statusAfter) = try run(arguments: ["volume", "list", "--quiet"]) #expect(statusAfter == 0) #expect(!listAfter.contains(volumeName1), "volume1 should be pruned") #expect(!listAfter.contains(volumeName2), "volume2 should be pruned") @@ -397,13 +397,13 @@ class TestCLIVolumes: CLITest { try waitForContainerRunning(containerName) // Prune should only remove the unused volume - let (_, error, status) = try run(arguments: ["volume", "prune"]) + let (_, _, error, status) = try run(arguments: ["volume", "prune"]) if status != 0 { throw CLIError.executionFailed("volume prune failed: \(error)") } // Verify in-use volume still exists - let (listAfter, _, statusAfter) = try run(arguments: ["volume", "list", "--quiet"]) + let (_, listAfter, _, statusAfter) = try run(arguments: ["volume", "list", "--quiet"]) #expect(statusAfter == 0) #expect(listAfter.contains(volumeInUse), "volume in use should NOT be pruned") #expect(!listAfter.contains(volumeUnused), "unused volume should be pruned") @@ -432,23 +432,23 @@ class TestCLIVolumes: CLITest { try await Task.sleep(for: .seconds(1)) // Prune should NOT remove the volume (container exists, even if stopped) - let (_, error, status) = try run(arguments: ["volume", "prune"]) + let (_, _, error, status) = try run(arguments: ["volume", "prune"]) if status != 0 { throw CLIError.executionFailed("volume prune failed: \(error)") } - let (listAfter, _, statusAfter) = try run(arguments: ["volume", "list", "--quiet"]) + let (_, listAfter, _, statusAfter) = try run(arguments: ["volume", "list", "--quiet"]) #expect(statusAfter == 0) #expect(listAfter.contains(volumeName), "volume attached to stopped container should NOT be pruned") doRemoveIfExists(name: containerName, force: true) - let (_, error2, status2) = try run(arguments: ["volume", "prune"]) + let (_, _, error2, status2) = try run(arguments: ["volume", "prune"]) if status2 != 0 { throw CLIError.executionFailed("volume prune failed: \(error2)") } // Verify volume is gone - let (listFinal, _, statusFinal) = try run(arguments: ["volume", "list", "--quiet"]) + let (_, listFinal, _, statusFinal) = try run(arguments: ["volume", "list", "--quiet"]) #expect(statusFinal == 0) #expect(!listFinal.contains(volumeName), "volume should be pruned after container is deleted") } diff --git a/Tests/CLITests/Utilities/CLITest.swift b/Tests/CLITests/Utilities/CLITest.swift index 42fd7dc2..0203cfb1 100644 --- a/Tests/CLITests/Utilities/CLITest.swift +++ b/Tests/CLITests/Utilities/CLITest.swift @@ -110,7 +110,7 @@ class CLITest { } } - func run(arguments: [String], currentDirectory: URL? = nil) throws -> (output: String, error: String, status: Int32) { + func run(arguments: [String], stdin: Data? = nil, currentDirectory: URL? = nil) throws -> (outputData: Data, output: String, error: String, status: Int32) { let process = Process() process.executableURL = try executablePath process.arguments = arguments @@ -118,24 +118,32 @@ class CLITest { process.currentDirectoryURL = directory } + let inputPipe = Pipe() let outputPipe = Pipe() let errorPipe = Pipe() + process.standardInput = inputPipe process.standardOutput = outputPipe process.standardError = errorPipe + let outputData: Data + let errorData: Data do { try process.run() + if let data = stdin { + inputPipe.fileHandleForWriting.write(data) + } + inputPipe.fileHandleForWriting.closeFile() + outputData = outputPipe.fileHandleForReading.readDataToEndOfFile() + errorData = errorPipe.fileHandleForReading.readDataToEndOfFile() process.waitUntilExit() } catch { throw CLIError.executionFailed("Failed to run CLI: \(error)") } - let outputData = outputPipe.fileHandleForReading.readDataToEndOfFile() - let errorData = errorPipe.fileHandleForReading.readDataToEndOfFile() let output = String(data: outputData, encoding: .utf8) ?? "" let error = String(data: errorData, encoding: .utf8) ?? "" - return (output: output, error: error, status: process.terminationStatus) + return (outputData: outputData, output: output, error: error, status: process.terminationStatus) } func runInteractive(arguments: [String], currentDirectory: URL? = nil) throws -> Terminal { @@ -220,7 +228,7 @@ class CLITest { runArgs.append(contentsOf: defaultContainerArgs) } - let (_, error, status) = try run(arguments: runArgs) + let (_, _, error, status) = try run(arguments: runArgs) if status != 0 { throw CLIError.executionFailed("command failed: \(error)") } @@ -232,7 +240,7 @@ class CLITest { name, ] execArgs.append(contentsOf: cmd) - let (resp, error, status) = try run(arguments: execArgs) + let (_, resp, error, status) = try run(arguments: execArgs) if status != 0 { throw CLIError.executionFailed("command failed: \(error)") } @@ -240,7 +248,7 @@ class CLITest { } func doStop(name: String, signal: String = "SIGKILL") throws { - let (_, error, status) = try run(arguments: [ + let (_, _, error, status) = try run(arguments: [ "stop", "-s", signal, @@ -275,14 +283,14 @@ class CLITest { arguments += [image] + args - let (_, error, status) = try run(arguments: arguments) + let (_, _, error, status) = try run(arguments: arguments) if status != 0 { throw CLIError.executionFailed("command failed: \(error)") } } func doStart(name: String) throws { - let (_, error, status) = try run(arguments: [ + let (_, _, error, status) = try run(arguments: [ "start", name, ]) @@ -368,7 +376,7 @@ class CLITest { } pullArgs.append(imageName) - let (_, error, status) = try run(arguments: pullArgs) + let (_, _, error, status) = try run(arguments: pullArgs) if status != 0 { throw CLIError.executionFailed("command failed: \(error)") } @@ -381,7 +389,7 @@ class CLITest { "-q", ] - let (out, error, status) = try run(arguments: args) + let (_, out, error, status) = try run(arguments: args) if status != 0 { throw CLIError.executionFailed("command failed: \(error)") } @@ -389,7 +397,7 @@ class CLITest { } func doInspectImages(image: String) throws -> [ImageInspectOutput] { - let (output, error, status) = try run(arguments: [ + let (_, output, error, status) = try run(arguments: [ "image", "inspect", image, @@ -415,7 +423,7 @@ class CLITest { "registry.domain", domain, ] - let (_, error, status) = try run(arguments: args) + let (_, _, error, status) = try run(arguments: args) if status != 0 { throw CLIError.executionFailed("command failed: \(error)") } @@ -428,7 +436,7 @@ class CLITest { "clear", "registry.domain", ] - let (_, error, status) = try run(arguments: args) + let (_, _, error, status) = try run(arguments: args) if status != 0 { throw CLIError.executionFailed("command failed: \(error)") } @@ -441,7 +449,7 @@ class CLITest { } args.append(name) - let (_, error, status) = try run(arguments: args) + let (_, _, error, status) = try run(arguments: args) if status != 0 { throw CLIError.executionFailed("command failed: \(error)") }