@@ -280,30 +280,85 @@ struct ParserTest {
280280 }
281281
282282 @Test
283- func testMountBindRelativePath( ) throws {
284-
285- let tempDir = FileManager . default. temporaryDirectory. appendingPathComponent ( " test-bind- \( UUID ( ) . uuidString) " )
286- try FileManager . default. createDirectory ( at: tempDir, withIntermediateDirectories: true )
287- defer {
288- try ? FileManager . default. removeItem ( at: tempDir)
289- }
290-
283+ func testRelativePaths( ) throws {
291284 let originalDir = FileManager . default. currentDirectoryPath
292- FileManager . default. changeCurrentDirectoryPath ( tempDir. path)
293285 defer {
294286 FileManager . default. changeCurrentDirectoryPath ( originalDir)
295287 }
296288
297- let result = try Parser . mount ( " type=bind,src=.,dst=/foo " )
289+ func realpath( _ path: String ) -> String {
290+ let resolved = UnsafeMutablePointer< CChar> . allocate( capacity: Int ( PATH_MAX) )
291+ defer { resolved. deallocate ( ) }
292+ guard let result = Darwin . realpath ( path, resolved) else {
293+ return path
294+ }
295+ return String ( cString: result)
296+ }
298297
299- switch result {
300- case . filesystem( let fs) :
301- let expectedPath = URL ( filePath: " . " ) . absoluteURL. path
302- #expect( fs. source == expectedPath)
303- #expect( fs. destination == " /foo " )
304- #expect( !fs. isVolume)
305- case . volume:
306- #expect( Bool ( false ) , " Expected filesystem mount, got volume " )
298+ // Test bind mount with relative path "."
299+ do {
300+ let tempDir = FileManager . default. temporaryDirectory. appendingPathComponent ( " test-bind- \( UUID ( ) . uuidString) " )
301+ try FileManager . default. createDirectory ( at: tempDir, withIntermediateDirectories: true )
302+ defer {
303+ try ? FileManager . default. removeItem ( at: tempDir)
304+ }
305+
306+ FileManager . default. changeCurrentDirectoryPath ( tempDir. path)
307+ let result = try Parser . mount ( " type=bind,src=.,dst=/foo " )
308+
309+ switch result {
310+ case . filesystem( let fs) :
311+ #expect( fs. source == realpath ( tempDir. path) )
312+ #expect( fs. destination == " /foo " )
313+ #expect( !fs. isVolume)
314+ case . volume:
315+ #expect( Bool ( false ) , " Expected filesystem mount, got volume " )
316+ }
317+ }
318+
319+ // Test volume with relative path "./"
320+ do {
321+ let tempDir = FileManager . default. temporaryDirectory. appendingPathComponent ( " test-volume-rel- \( UUID ( ) . uuidString) " )
322+ try FileManager . default. createDirectory ( at: tempDir, withIntermediateDirectories: true )
323+ defer {
324+ try ? FileManager . default. removeItem ( at: tempDir)
325+ }
326+
327+ FileManager . default. changeCurrentDirectoryPath ( tempDir. path)
328+ let result = try Parser . volume ( " ./:/foo " )
329+
330+ switch result {
331+ case . filesystem( let fs) :
332+ let expectedPath = realpath ( tempDir. path)
333+ // Normalize trailing slashes for comparison
334+ #expect( fs. source. trimmingCharacters ( in: CharacterSet ( charactersIn: " / " ) ) == expectedPath. trimmingCharacters ( in: CharacterSet ( charactersIn: " / " ) ) )
335+ #expect( fs. destination == " /foo " )
336+ case . volume:
337+ #expect( Bool ( false ) , " Expected filesystem mount, got volume " )
338+ }
339+ }
340+
341+ // Test volume with nested relative path "./subdir"
342+ do {
343+ let tempDir = FileManager . default. temporaryDirectory. appendingPathComponent ( " test-volume-rel-nested- \( UUID ( ) . uuidString) " )
344+ let nestedDir = tempDir. appendingPathComponent ( " subdir " )
345+ try FileManager . default. createDirectory ( at: nestedDir, withIntermediateDirectories: true )
346+ defer {
347+ try ? FileManager . default. removeItem ( at: tempDir)
348+ }
349+
350+ FileManager . default. changeCurrentDirectoryPath ( tempDir. path)
351+ let result = try Parser . volume ( " ./subdir:/foo " )
352+
353+ switch result {
354+ case . filesystem( let fs) :
355+ let expectedPath = realpath ( nestedDir. path)
356+ // Normalize trailing slashes for comparison
357+ #expect( fs. source. trimmingCharacters ( in: CharacterSet ( charactersIn: " / " ) ) == expectedPath. trimmingCharacters ( in: CharacterSet ( charactersIn: " / " ) ) )
358+ #expect( fs. destination == " /foo " )
359+ case . volume:
360+ #expect( Bool ( false ) , " Expected filesystem mount, got volume " )
361+ }
307362 }
308363 }
309364
@@ -382,61 +437,6 @@ struct ParserTest {
382437 }
383438 }
384439
385- @Test
386- func testVolumeRelativePath( ) throws {
387- let tempDir = FileManager . default. temporaryDirectory. appendingPathComponent ( " test-volume-rel- \( UUID ( ) . uuidString) " )
388- try FileManager . default. createDirectory ( at: tempDir, withIntermediateDirectories: true )
389- defer {
390- try ? FileManager . default. removeItem ( at: tempDir)
391- }
392-
393- let originalDir = FileManager . default. currentDirectoryPath
394- FileManager . default. changeCurrentDirectoryPath ( tempDir. path)
395- defer {
396- FileManager . default. changeCurrentDirectoryPath ( originalDir)
397- }
398-
399- let result = try Parser . volume ( " ./:/foo " )
400-
401- switch result {
402- case . filesystem( let fs) :
403- let expectedPath = URL ( filePath: " . " ) . absoluteURL. path
404- // Normalize trailing slashes for comparison
405- #expect( fs. source. trimmingCharacters ( in: CharacterSet ( charactersIn: " / " ) ) == expectedPath. trimmingCharacters ( in: CharacterSet ( charactersIn: " / " ) ) )
406- #expect( fs. destination == " /foo " )
407- case . volume:
408- #expect( Bool ( false ) , " Expected filesystem mount, got volume " )
409- }
410- }
411-
412- @Test
413- func testVolumeRelativePathNested( ) throws {
414- let tempDir = FileManager . default. temporaryDirectory. appendingPathComponent ( " test-volume-rel-nested- \( UUID ( ) . uuidString) " )
415- let nestedDir = tempDir. appendingPathComponent ( " subdir " )
416- try FileManager . default. createDirectory ( at: nestedDir, withIntermediateDirectories: true )
417- defer {
418- try ? FileManager . default. removeItem ( at: tempDir)
419- }
420-
421- let originalDir = FileManager . default. currentDirectoryPath
422- FileManager . default. changeCurrentDirectoryPath ( tempDir. path)
423- defer {
424- FileManager . default. changeCurrentDirectoryPath ( originalDir)
425- }
426-
427- let result = try Parser . volume ( " ./subdir:/foo " )
428-
429- switch result {
430- case . filesystem( let fs) :
431- let expectedPath = URL ( filePath: " ./subdir " ) . absoluteURL. path
432- // Normalize trailing slashes for comparison
433- #expect( fs. source. trimmingCharacters ( in: CharacterSet ( charactersIn: " / " ) ) == expectedPath. trimmingCharacters ( in: CharacterSet ( charactersIn: " / " ) ) )
434- #expect( fs. destination == " /foo " )
435- case . volume:
436- #expect( Bool ( false ) , " Expected filesystem mount, got volume " )
437- }
438- }
439-
440440 @Test
441441 func testIsValidDomainNameOk( ) throws {
442442 let names = [
0 commit comments