Skip to content

Commit 8157adb

Browse files
committed
add missing route + update tests
1 parent 9854ded commit 8157adb

2 files changed

Lines changed: 61 additions & 15 deletions

File tree

Sources/Plugins/RuntimeLinux/RuntimeLinuxHelper+Start.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ extension RuntimeLinuxHelper {
107107
RuntimeRoutes.copyIn.rawValue: XPCServer.route(server.copyIn),
108108
RuntimeRoutes.copyOut.rawValue: XPCServer.route(server.copyOut),
109109
RuntimeRoutes.snapshotDisk.rawValue: XPCServer.route(server.snapshotDisk),
110+
RuntimeRoutes.clean.rawValue: XPCServer.route(server.clean),
110111
],
111112
log: log
112113
)

Tests/IntegrationTests/Containers/TestCLIClean.swift

Lines changed: 60 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,28 +17,55 @@
1717
import Foundation
1818
import Testing
1919

20-
@Suite(.serialSuites)
20+
@Suite
2121
class TestCLIClean: CLITest {
22+
private struct StatusJSON: Codable {
23+
let appRoot: String
24+
}
25+
2226
private func getTestName() -> String {
2327
Test.current!.name.trimmingCharacters(in: ["(", ")"]).lowercased()
2428
}
2529

26-
@Test func testCleanRunningContainer() throws {
27-
let name = getTestName()
28-
try doLongRun(name: name, autoRemove: false)
29-
defer {
30-
try? doStop(name: name)
31-
try? doRemove(name: name)
30+
private func appRoot() throws -> URL {
31+
let result = try run(arguments: ["system", "status", "--format", "json"]).check()
32+
let status = try JSONDecoder().decode(StatusJSON.self, from: result.outputData)
33+
return URL(fileURLWithPath: status.appRoot, isDirectory: true)
34+
}
35+
36+
private func allocatedBytes(at url: URL) throws -> Int64 {
37+
let values = try url.resourceValues(forKeys: [.fileAllocatedSizeKey, .totalFileAllocatedSizeKey])
38+
let allocated = values.totalFileAllocatedSize ?? values.fileAllocatedSize
39+
guard let allocated else {
40+
throw CLIError.executionFailed("failed to read allocated size for \(url.path)")
3241
}
42+
return Int64(allocated)
43+
}
3344

34-
try waitForContainerRunning(name)
45+
private func containerRootfsBlockURL(name: String) throws -> URL {
46+
let id = try getContainerId(name)
47+
return try appRoot()
48+
.appendingPathComponent("containers", isDirectory: true)
49+
.appendingPathComponent(id, isDirectory: true)
50+
.appendingPathComponent("rootfs.ext4", isDirectory: false)
51+
}
3552

36-
// Clean should succeed on running container
37-
try doClean(name: name)
53+
private func volumeBlockURL(name: String) throws -> URL {
54+
try appRoot()
55+
.appendingPathComponent("volumes", isDirectory: true)
56+
.appendingPathComponent(name, isDirectory: true)
57+
.appendingPathComponent("volume.img", isDirectory: false)
58+
}
3859

39-
// Container should still be running after clean
40-
let status = try getContainerStatus(name)
41-
#expect(status == "running")
60+
private func assertCleanReclaimedSpace(beforeWrite: Int64, afterWrite: Int64, afterClean: Int64) {
61+
let writeAllocated = afterWrite - beforeWrite
62+
#expect(writeAllocated > 0)
63+
64+
let reclaimed = afterWrite - afterClean
65+
#expect(reclaimed > 0)
66+
67+
let minExpectedReclaimed = Int64(Double(writeAllocated) * 0.8)
68+
#expect(reclaimed >= minExpectedReclaimed)
4269
}
4370

4471
@Test func testCleanStoppedContainerFails() throws {
@@ -95,12 +122,21 @@ class TestCLIClean: CLITest {
95122

96123
try waitForContainerRunning(name)
97124

125+
let rootfsBlockURL = try containerRootfsBlockURL(name: name)
126+
let beforeWrite = try allocatedBytes(at: rootfsBlockURL)
127+
98128
// Create some files to exercise the filesystem trim path
99-
_ = try doExec(name: name, cmd: ["sh", "-c", "dd if=/dev/zero of=/test-file bs=1M count=10"])
129+
_ = try doExec(name: name, cmd: ["sh", "-c", "dd if=/dev/urandom of=/test-file bs=1M count=10"])
130+
_ = try doExec(name: name, cmd: ["sync"])
131+
let afterWrite = try allocatedBytes(at: rootfsBlockURL)
132+
100133
_ = try doExec(name: name, cmd: ["rm", "/test-file"])
101134

102135
// Clean should succeed
103136
try doClean(name: name)
137+
_ = try doExec(name: name, cmd: ["sync"])
138+
let afterClean = try allocatedBytes(at: rootfsBlockURL)
139+
assertCleanReclaimedSpace(beforeWrite: beforeWrite, afterWrite: afterWrite, afterClean: afterClean)
104140

105141
// Container should still be running
106142
let status = try getContainerStatus(name)
@@ -140,12 +176,21 @@ class TestCLIClean: CLITest {
140176

141177
try waitForContainerRunning(name)
142178

179+
let volumeBlockURL = try volumeBlockURL(name: volumeName)
180+
let beforeWrite = try allocatedBytes(at: volumeBlockURL)
181+
143182
// Write to volume
144-
_ = try doExec(name: name, cmd: ["sh", "-c", "dd if=/dev/zero of=/mnt/vol/test bs=1M count=5"])
183+
_ = try doExec(name: name, cmd: ["sh", "-c", "dd if=/dev/urandom of=/mnt/vol/test bs=1M count=5"])
184+
_ = try doExec(name: name, cmd: ["sync"])
185+
let afterWrite = try allocatedBytes(at: volumeBlockURL)
186+
145187
_ = try doExec(name: name, cmd: ["rm", "/mnt/vol/test"])
146188

147189
// Clean should succeed and also trim the volume
148190
try doClean(name: name)
191+
_ = try doExec(name: name, cmd: ["sync"])
192+
let afterClean = try allocatedBytes(at: volumeBlockURL)
193+
assertCleanReclaimedSpace(beforeWrite: beforeWrite, afterWrite: afterWrite, afterClean: afterClean)
149194

150195
// Container should still be running
151196
let status = try getContainerStatus(name)

0 commit comments

Comments
 (0)