From 40de3430cdec3e64037aff5fa26cf008d4ff7e11 Mon Sep 17 00:00:00 2001 From: Dmitry Kovba Date: Fri, 6 Feb 2026 00:41:29 -0800 Subject: [PATCH] Fix relative path mount tests (#1168) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `make test` occasionally fails with: ``` ✘ Test testHostDNSReinitialize() recorded an issue at HostDNSResolverTest.swift:132:45: Expectation failed: (error → Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory") as? (ContainerizationError → NSError) ✘ Suite HostDNSResolverTest failed after 0.119 seconds with 1 issue. ``` --- .../ContainerAPIService/Client/Parser.swift | 16 +++++----- .../ContainerAPIClientTests/ParserTest.swift | 29 ++++--------------- 2 files changed, 14 insertions(+), 31 deletions(-) diff --git a/Sources/Services/ContainerAPIService/Client/Parser.swift b/Sources/Services/ContainerAPIService/Client/Parser.swift index 1a6c9547..2e7faa06 100644 --- a/Sources/Services/ContainerAPIService/Client/Parser.swift +++ b/Sources/Services/ContainerAPIService/Client/Parser.swift @@ -316,18 +316,18 @@ public struct Parser { return result } - public static func mounts(_ rawMounts: [String]) throws -> [VolumeOrFilesystem] { + public static func mounts(_ rawMounts: [String], relativeTo basePath: URL? = nil) throws -> [VolumeOrFilesystem] { var mounts: [VolumeOrFilesystem] = [] let rawMounts = rawMounts.dedupe() for mount in rawMounts { - let m = try Parser.mount(mount) + let m = try Parser.mount(mount, relativeTo: basePath) try validateMount(m) mounts.append(m) } return mounts } - public static func mount(_ mount: String) throws -> VolumeOrFilesystem { + public static func mount(_ mount: String, relativeTo basePath: URL? = nil) throws -> VolumeOrFilesystem { let parts = mount.split(separator: ",") if parts.count == 0 { throw ContainerizationError(.invalidArgument, message: "invalid mount format: \(mount)") @@ -407,7 +407,7 @@ public struct Parser { switch type { case "virtiofs", "bind": // For bind mounts, resolve both absolute and relative paths - let url = URL(filePath: val) + let url = basePath?.appending(path: val).standardizedFileURL ?? URL(filePath: val) let absolutePath = url.absoluteURL.path var isDirectory: ObjCBool = false @@ -458,17 +458,17 @@ public struct Parser { )) } - public static func volumes(_ rawVolumes: [String]) throws -> [VolumeOrFilesystem] { + public static func volumes(_ rawVolumes: [String], relativeTo basePath: URL? = nil) throws -> [VolumeOrFilesystem] { var mounts: [VolumeOrFilesystem] = [] for volume in rawVolumes { - let m = try Parser.volume(volume) + let m = try Parser.volume(volume, relativeTo: basePath) try Parser.validateMount(m) mounts.append(m) } return mounts } - public static func volume(_ volume: String) throws -> VolumeOrFilesystem { + public static func volume(_ volume: String, relativeTo basePath: URL? = nil) throws -> VolumeOrFilesystem { var vol = volume vol.trimLeft(char: ":") @@ -508,7 +508,7 @@ public struct Parser { options: options )) } - let url = URL(filePath: src) + let url = basePath?.appending(path: src).standardizedFileURL ?? URL(filePath: src) let absolutePath = url.absoluteURL.path var isDirectory: ObjCBool = false diff --git a/Tests/ContainerAPIClientTests/ParserTest.swift b/Tests/ContainerAPIClientTests/ParserTest.swift index 83f761b9..90fd9b07 100644 --- a/Tests/ContainerAPIClientTests/ParserTest.swift +++ b/Tests/ContainerAPIClientTests/ParserTest.swift @@ -329,20 +329,6 @@ struct ParserTest { @Test func testRelativePaths() throws { - let originalDir = FileManager.default.currentDirectoryPath - defer { - FileManager.default.changeCurrentDirectoryPath(originalDir) - } - - func realpath(_ path: String) -> String { - let resolved = UnsafeMutablePointer.allocate(capacity: Int(PATH_MAX)) - defer { resolved.deallocate() } - guard let result = Darwin.realpath(path, resolved) else { - return path - } - return String(cString: result) - } - // Test bind mount with relative path "." do { let tempDir = FileManager.default.temporaryDirectory.appendingPathComponent("test-bind-\(UUID().uuidString)") @@ -351,12 +337,11 @@ struct ParserTest { try? FileManager.default.removeItem(at: tempDir) } - FileManager.default.changeCurrentDirectoryPath(tempDir.path) - let result = try Parser.mount("type=bind,src=.,dst=/foo") + let result = try Parser.mount("type=bind,src=.,dst=/foo", relativeTo: tempDir) switch result { case .filesystem(let fs): - #expect(fs.source == realpath(tempDir.path)) + #expect(fs.source == tempDir.standardizedFileURL.path) #expect(fs.destination == "/foo") #expect(!fs.isVolume) case .volume: @@ -372,12 +357,11 @@ struct ParserTest { try? FileManager.default.removeItem(at: tempDir) } - FileManager.default.changeCurrentDirectoryPath(tempDir.path) - let result = try Parser.volume("./:/foo") + let result = try Parser.volume("./:/foo", relativeTo: tempDir) switch result { case .filesystem(let fs): - let expectedPath = realpath(tempDir.path) + let expectedPath = tempDir.standardizedFileURL.path // Normalize trailing slashes for comparison #expect(fs.source.trimmingCharacters(in: CharacterSet(charactersIn: "/")) == expectedPath.trimmingCharacters(in: CharacterSet(charactersIn: "/"))) #expect(fs.destination == "/foo") @@ -395,12 +379,11 @@ struct ParserTest { try? FileManager.default.removeItem(at: tempDir) } - FileManager.default.changeCurrentDirectoryPath(tempDir.path) - let result = try Parser.volume("./subdir:/foo") + let result = try Parser.volume("./subdir:/foo", relativeTo: tempDir) switch result { case .filesystem(let fs): - let expectedPath = realpath(nestedDir.path) + let expectedPath = nestedDir.standardizedFileURL.path // Normalize trailing slashes for comparison #expect(fs.source.trimmingCharacters(in: CharacterSet(charactersIn: "/")) == expectedPath.trimmingCharacters(in: CharacterSet(charactersIn: "/"))) #expect(fs.destination == "/foo")