Skip to content

Commit 3de2933

Browse files
authored
Integration: Add stdio ingest test (#385)
Add a test to ingest 200MiB of data across stdout/stderr. Useful to test how fast we can ingest stdio. The timing will always be a tad off as it times between start and wait returning, and there's quite a lot in the way.. but it's a good enough metric.
1 parent 619354e commit 3de2933

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed

Sources/Integration/ContainerTests.swift

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,18 @@ extension IntegrationSuite {
6464
}
6565
}
6666

67+
final class DiscardingWriter: @unchecked Sendable, Writer {
68+
var count: Int = 0
69+
70+
func write(_ data: Data) throws {
71+
count += data.count
72+
}
73+
74+
func close() throws {
75+
return
76+
}
77+
}
78+
6779
final class BufferWriter: Writer {
6880
// `data` isn't used concurrently.
6981
nonisolated(unsafe) var data = Data()
@@ -1027,4 +1039,67 @@ extension IntegrationSuite {
10271039
try "hello".write(to: dir.appendingPathComponent("hi.txt"), atomically: true, encoding: .utf8)
10281040
return dir
10291041
}
1042+
1043+
func testLargeStdioOutput() async throws {
1044+
let id = "test-large-stdout-stderr-output"
1045+
1046+
let bs = try await bootstrap(id)
1047+
let container = try LinuxContainer(id, rootfs: bs.rootfs, vmm: bs.vmm) { config in
1048+
config.process.arguments = ["/bin/sleep", "1000"]
1049+
config.bootlog = bs.bootlog
1050+
}
1051+
1052+
do {
1053+
try await container.create()
1054+
try await container.start()
1055+
1056+
let stdoutBuffer = DiscardingWriter()
1057+
let stderrBuffer = DiscardingWriter()
1058+
1059+
let exec = try await container.exec("large-output") { config in
1060+
config.arguments = [
1061+
"sh",
1062+
"-c",
1063+
"""
1064+
dd if=/dev/zero bs=1M count=250 status=none && \
1065+
dd if=/dev/zero bs=1M count=250 status=none >&2
1066+
""",
1067+
]
1068+
config.stdout = stdoutBuffer
1069+
config.stderr = stderrBuffer
1070+
}
1071+
1072+
let started = CFAbsoluteTimeGetCurrent()
1073+
1074+
try await exec.start()
1075+
let status = try await exec.wait()
1076+
1077+
let lasted = CFAbsoluteTimeGetCurrent() - started
1078+
print("Test \(id) finished process ingesting stdio in \(lasted)")
1079+
1080+
guard status.exitCode == 0 else {
1081+
throw IntegrationError.assert(msg: "exec process status \(status) != 0")
1082+
}
1083+
1084+
try await exec.delete()
1085+
1086+
let expectedSize = 250 * 1024 * 1024
1087+
guard stdoutBuffer.count == expectedSize else {
1088+
throw IntegrationError.assert(
1089+
msg: "stdout size \(stdoutBuffer.count) != expected \(expectedSize)")
1090+
}
1091+
1092+
guard stderrBuffer.count == expectedSize else {
1093+
throw IntegrationError.assert(
1094+
msg: "stderr size \(stderrBuffer.count) != expected \(expectedSize)")
1095+
}
1096+
1097+
try await container.kill(SIGKILL)
1098+
try await container.wait()
1099+
try await container.stop()
1100+
} catch {
1101+
try? await container.stop()
1102+
throw error
1103+
}
1104+
}
10301105
}

Sources/Integration/Suite.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ struct IntegrationSuite: AsyncParsableCommand {
295295
Test("container no serial console", testNoSerialConsole),
296296
Test("unix socket into guest", testUnixSocketIntoGuest),
297297
Test("container non-closure constructor", testNonClosureConstructor),
298+
Test("container test large stdio ingest", testLargeStdioOutput),
298299

299300
// Pods
300301
Test("pod single container", testPodSingleContainer),

0 commit comments

Comments
 (0)