mirror of
https://github.com/apple/container.git
synced 2026-09-12 18:55:43 +00:00
When working on test cases for #827 and #734 the following issues occurred 1. There was no support to pass in `Data` for `stdin` (input pipe added + new argument for the data) 2. Pipes were getting blocked during the `try process.run()` and `process.waitUntilExit()` (order of operations were fixed) 3. We need the binary data for directly piping the `stdout` data to `stdin`, and converting the data to a `string`, returns `""` (added a new value to the tuple) I opened a new PR here for this as I did not want to bloat the other PRs with so many updates. At first I thought of creating a new function named `runStdinStdout`, but that seemed redundant as it pretty much was going to do the same thing as `run`. ## Testing - [x] Tested locally - [x] Added/updated tests - [ ] Added/updated docs --------- Co-authored-by: J Logan <john_logan@apple.com>
111 lines
4.4 KiB
Swift
111 lines
4.4 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
// Copyright © 2025 Apple Inc. and the container project authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// https://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
import Foundation
|
|
import Testing
|
|
|
|
class TestCLIExecCommand: CLITest {
|
|
private func getTestName() -> String {
|
|
Test.current!.name.trimmingCharacters(in: ["(", ")"]).lowercased()
|
|
}
|
|
|
|
@Test func testCreateExecCommand() throws {
|
|
do {
|
|
let name = getTestName()
|
|
try doCreate(name: name)
|
|
defer {
|
|
try? doStop(name: name)
|
|
}
|
|
try doStart(name: name)
|
|
var unameActual = try doExec(name: name, cmd: ["uname"])
|
|
unameActual = unameActual.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
#expect(unameActual == "Linux", "expected OS to be Linux, instead got \(unameActual)")
|
|
try doStop(name: name)
|
|
} catch {
|
|
Issue.record("failed to exec in container \(error)")
|
|
return
|
|
}
|
|
}
|
|
|
|
@Test func testExecDetach() throws {
|
|
do {
|
|
let name = getTestName()
|
|
try doCreate(name: name)
|
|
defer {
|
|
try? doStop(name: name)
|
|
}
|
|
try doStart(name: name)
|
|
|
|
// Run a long-running process in detached mode
|
|
let output = try doExec(name: name, cmd: ["sh", "-c", "touch /tmp/detach_test_marker"], detach: true)
|
|
let containerIdOutput = output.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
try #require(containerIdOutput == name, "exec --detach should print the container ID")
|
|
|
|
// Verify the detached process is running by checking if we can still exec commands
|
|
var lsActual = try doExec(name: name, cmd: ["ls", "/"])
|
|
lsActual = lsActual.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
try #require(lsActual.contains("tmp"), "container should still be running and accepting exec commands")
|
|
|
|
// Retry loop to check if the marker file was created by the detached process
|
|
var markerFound = false
|
|
for _ in 0..<3 {
|
|
let (_, _, _, status) = try run(arguments: [
|
|
"exec",
|
|
name,
|
|
"test", "-f", "/tmp/detach_test_marker",
|
|
])
|
|
if status == 0 {
|
|
markerFound = true
|
|
break
|
|
}
|
|
sleep(1)
|
|
}
|
|
try #require(markerFound, "marker file should be created by detached process within 3 seconds")
|
|
|
|
try doStop(name: name)
|
|
} catch {
|
|
Issue.record("failed to exec with detach in container \(error)")
|
|
return
|
|
}
|
|
}
|
|
|
|
@Test func testExecDetachProcessRunning() throws {
|
|
do {
|
|
let name = getTestName()
|
|
try doCreate(name: name)
|
|
defer {
|
|
try? doStop(name: name)
|
|
}
|
|
try doStart(name: name)
|
|
|
|
// Run a long-running process in detached mode
|
|
let output = try doExec(name: name, cmd: ["sleep", "10"], detach: true)
|
|
let containerIdOutput = output.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
try #require(containerIdOutput == name, "exec --detach should print the container ID")
|
|
|
|
// Immediately check if the process is running using ps
|
|
var psOutput = try doExec(name: name, cmd: ["ps", "aux"])
|
|
psOutput = psOutput.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
try #require(psOutput.contains("sleep 10"), "detached process 'sleep 10' should be visible in ps output")
|
|
|
|
try doStop(name: name)
|
|
} catch {
|
|
Issue.record("failed to verify detached process is running \(error)")
|
|
return
|
|
}
|
|
}
|
|
}
|