Skip to content

Commit 2164780

Browse files
committed
[android] Replace URL tests that use hardcoded /tmp
In Android /tmp doesn't exist, and the temporary directory is normally /data/local/tmp. It is not a symlink. The tests were mostly working, but because `resolvingSymlinksInPath` returns a trailing slash if the directory actually exists, in Android it was returning without the final trailing slash in some of the cases. The changes split the large test into smaller pieces that test one of the behaviours of `resolvingSymlinksInPath`, and tries not to use the temporarl directory by itself or suppose anything about it. There are, however, a couple of tests that check behaviours that are only applicable to Darwin, so those tests are only performed in Darwin platforms.
1 parent 76fe3ec commit 2164780

File tree

1 file changed

+109
-50
lines changed

1 file changed

+109
-50
lines changed

TestFoundation/TestURL.swift

Lines changed: 109 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -380,60 +380,103 @@ class TestURL : XCTestCase {
380380
XCTAssertTrue(strncmp(TestURL.gFileDoesNotExistName, relativePath, lengthOfRelativePath) == 0, "fileSystemRepresentation of file path is wrong")
381381
}
382382

383-
func test_URLByResolvingSymlinksInPath() {
384-
let files = [
385-
NSTemporaryDirectory() + "ABC/test_URLByResolvingSymlinksInPath"
386-
]
387-
388-
guard ensureFiles(files) else {
389-
XCTAssert(false, "Could create files for testing.")
390-
return
391-
}
392-
393-
// tmp is special because it is symlinked to /private/tmp and this /private prefix should be dropped,
394-
// so tmp is tmp. On Linux tmp is not symlinked so it would be the same.
395-
do {
396-
let url = URL(fileURLWithPath: "/.//tmp/ABC/..")
397-
let result = url.resolvingSymlinksInPath().absoluteString
398-
XCTAssertEqual(result, "file:///tmp/", "URLByResolvingSymlinksInPath removes extraneous path components and resolve symlinks.")
399-
}
383+
func test_URLByResolvingSymlinksInPathShouldRemoveDuplicatedPathSeparators() {
384+
let url = URL(fileURLWithPath: "//foo///bar////baz/")
385+
let result = url.resolvingSymlinksInPath()
386+
XCTAssertEqual(result, URL(fileURLWithPath: "/foo/bar/baz"))
387+
}
400388

401-
do {
402-
let url = URL(fileURLWithPath: "~")
403-
let result = url.resolvingSymlinksInPath().absoluteString
404-
let expected = "file://" + FileManager.default.currentDirectoryPath + "/~"
405-
XCTAssertEqual(result, expected, "URLByResolvingSymlinksInPath resolves relative paths using current working directory.")
406-
}
389+
func test_URLByResolvingSymlinksInPathShouldRemoveSingleDotsBetweenSeparators() {
390+
let url = URL(fileURLWithPath: "/./foo/./.bar/./baz/./")
391+
let result = url.resolvingSymlinksInPath()
392+
XCTAssertEqual(result, URL(fileURLWithPath: "/foo/.bar/baz"))
393+
}
407394

408-
do {
409-
let url = URL(fileURLWithPath: "anysite.com/search")
410-
let result = url.resolvingSymlinksInPath().absoluteString
411-
let expected = "file://" + FileManager.default.currentDirectoryPath + "/anysite.com/search"
412-
XCTAssertEqual(result, expected)
413-
}
395+
func test_URLByResolvingSymlinksInPathShouldCompressDoubleDotsBetweenSeparators() {
396+
let url = URL(fileURLWithPath: "/foo/../..bar/../baz/")
397+
let result = url.resolvingSymlinksInPath()
398+
XCTAssertEqual(result, URL(fileURLWithPath: "/baz"))
399+
}
414400

415-
// tmp is symlinked on macOS only
416-
#if os(macOS)
417-
do {
418-
let url = URL(fileURLWithPath: "/tmp/..")
419-
let result = url.resolvingSymlinksInPath().absoluteString
420-
XCTAssertEqual(result, "file:///private/")
421-
}
422-
#else
423-
do {
424-
let url = URL(fileURLWithPath: "/tmp/ABC/test_URLByResolvingSymlinksInPath")
425-
let result = url.resolvingSymlinksInPath().absoluteString
426-
XCTAssertEqual(result, "file:///tmp/ABC/test_URLByResolvingSymlinksInPath", "URLByResolvingSymlinksInPath appends trailing slash for existing directories only")
427-
}
428-
#endif
401+
func test_URLByResolvingSymlinksInPathShouldUseTheCurrentDirectory() throws {
402+
let fileManager = FileManager.default
403+
try fileManager.createDirectory(at: writableTestDirectoryURL, withIntermediateDirectories: true)
404+
defer { try? fileManager.removeItem(at: writableTestDirectoryURL) }
429405

430-
do {
431-
let url = URL(fileURLWithPath: "/tmp/ABC/..")
432-
let result = url.resolvingSymlinksInPath().absoluteString
433-
XCTAssertEqual(result, "file:///tmp/")
406+
let previousCurrentDirectory = fileManager.currentDirectoryPath
407+
fileManager.changeCurrentDirectoryPath(writableTestDirectoryURL.path)
408+
defer { fileManager.changeCurrentDirectoryPath(previousCurrentDirectory) }
409+
410+
// In Darwin, because temporary directory is inside /private,
411+
// writableTestDirectoryURL will be something like /var/folders/...,
412+
// but /var points to /private/var, which is only removed if the
413+
// destination exists, so we create the destination to avoid having to
414+
// compare against /private in Darwin.
415+
try fileManager.createDirectory(at: writableTestDirectoryURL.appendingPathComponent("foo/bar"), withIntermediateDirectories: true)
416+
try "".write(to: writableTestDirectoryURL.appendingPathComponent("foo/bar/baz"), atomically: true, encoding: .utf8)
417+
418+
let url = URL(fileURLWithPath: "foo/bar/baz")
419+
let result = url.resolvingSymlinksInPath()
420+
XCTAssertEqual(result, URL(fileURLWithPath: writableTestDirectoryURL.path + "/foo/bar/baz"))
421+
}
422+
423+
func test_resolvingSymlinksInPathShouldAppendTrailingSlashWhenExistingDirectory() throws {
424+
let fileManager = FileManager.default
425+
try fileManager.createDirectory(at: writableTestDirectoryURL, withIntermediateDirectories: true)
426+
defer { try? fileManager.removeItem(at: writableTestDirectoryURL) }
427+
428+
var path = writableTestDirectoryURL.path
429+
if path.hasSuffix("/") {
430+
path.remove(at: path.index(path.endIndex, offsetBy: -1))
434431
}
432+
let url = URL(fileURLWithPath: path)
433+
let result = url.resolvingSymlinksInPath()
434+
XCTAssertEqual(result, URL(fileURLWithPath: path + "/"))
435435
}
436-
436+
437+
func test_resolvingSymlinksInPathShouldResolveSymlinks() throws {
438+
// NOTE: this test only works on file systems that support symlinks.
439+
let fileManager = FileManager.default
440+
try fileManager.createDirectory(at: writableTestDirectoryURL, withIntermediateDirectories: true)
441+
defer { try? fileManager.removeItem(at: writableTestDirectoryURL) }
442+
443+
let symbolicLink = writableTestDirectoryURL.appendingPathComponent("origin")
444+
let destination = writableTestDirectoryURL.appendingPathComponent("destination")
445+
try "".write(to: destination, atomically: true, encoding: .utf8)
446+
try fileManager.createSymbolicLink(at: symbolicLink, withDestinationURL: destination)
447+
448+
let result = symbolicLink.resolvingSymlinksInPath()
449+
XCTAssertEqual(result, URL(fileURLWithPath: writableTestDirectoryURL.path + "/destination"))
450+
}
451+
452+
func test_resolvingSymlinksInPathShouldRemovePrivatePrefix() {
453+
// NOTE: this test only works on Darwin, since the code that removes
454+
// /private relies on /private/tmp existing.
455+
let url = URL(fileURLWithPath: "/private/tmp")
456+
let result = url.resolvingSymlinksInPath()
457+
XCTAssertEqual(result, URL(fileURLWithPath: "/tmp"))
458+
}
459+
460+
func test_resolvingSymlinksInPathShouldNotRemovePrivatePrefixIfOnlyComponent() {
461+
// NOTE: this test only works on Darwin, since only there /tmp is
462+
// symlinked to /private/tmp.
463+
let url = URL(fileURLWithPath: "/tmp/..")
464+
let result = url.resolvingSymlinksInPath()
465+
XCTAssertEqual(result, URL(fileURLWithPath: "/private"))
466+
}
467+
468+
func test_resolvingSymlinksInPathShouldNotChangeNonFileURLs() {
469+
let url = URL(string: "myscheme://server/foo/bar/baz")!
470+
let result = url.resolvingSymlinksInPath().absoluteString
471+
XCTAssertEqual(result, "myscheme://server/foo/bar/baz")
472+
}
473+
474+
func test_resolvingSymlinksInPathShouldNotChangePathlessURLs() {
475+
let url = URL(string: "file://")!
476+
let result = url.resolvingSymlinksInPath().absoluteString
477+
XCTAssertEqual(result, "file://")
478+
}
479+
437480
func test_reachable() {
438481
#if os(Android)
439482
var url = URL(fileURLWithPath: "/data")
@@ -604,13 +647,20 @@ class TestURL : XCTestCase {
604647
}
605648

606649
static var allTests: [(String, (TestURL) -> () throws -> Void)] {
607-
return [
650+
var tests: [(String, (TestURL) -> () throws -> Void)] = [
608651
("test_URLStrings", test_URLStrings),
609652
("test_fileURLWithPath_relativeTo", test_fileURLWithPath_relativeTo ),
610653
// TODO: these tests fail on linux, more investigation is needed
611654
("test_fileURLWithPath", test_fileURLWithPath),
612655
("test_fileURLWithPath_isDirectory", test_fileURLWithPath_isDirectory),
613-
("test_URLByResolvingSymlinksInPath", test_URLByResolvingSymlinksInPath),
656+
("test_URLByResolvingSymlinksInPathShouldRemoveDuplicatedPathSeparators", test_URLByResolvingSymlinksInPathShouldRemoveDuplicatedPathSeparators),
657+
("test_URLByResolvingSymlinksInPathShouldRemoveSingleDotsBetweenSeparators", test_URLByResolvingSymlinksInPathShouldRemoveSingleDotsBetweenSeparators),
658+
("test_URLByResolvingSymlinksInPathShouldCompressDoubleDotsBetweenSeparators", test_URLByResolvingSymlinksInPathShouldCompressDoubleDotsBetweenSeparators),
659+
("test_URLByResolvingSymlinksInPathShouldUseTheCurrentDirectory", test_URLByResolvingSymlinksInPathShouldUseTheCurrentDirectory),
660+
("test_resolvingSymlinksInPathShouldAppendTrailingSlashWhenExistingDirectory", test_resolvingSymlinksInPathShouldAppendTrailingSlashWhenExistingDirectory),
661+
("test_resolvingSymlinksInPathShouldResolveSymlinks", test_resolvingSymlinksInPathShouldResolveSymlinks),
662+
("test_resolvingSymlinksInPathShouldNotChangeNonFileURLs", test_resolvingSymlinksInPathShouldNotChangeNonFileURLs),
663+
("test_resolvingSymlinksInPathShouldNotChangePathlessURLs", test_resolvingSymlinksInPathShouldNotChangePathlessURLs),
614664
("test_reachable", test_reachable),
615665
("test_copy", test_copy),
616666
("test_itemNSCoding", test_itemNSCoding),
@@ -619,6 +669,15 @@ class TestURL : XCTestCase {
619669
("test_URLResourceValues", testExpectedToFail(test_URLResourceValues,
620670
"test_URLResourceValues: Except for .nameKey, we have no testable attributes that work in the environment Swift CI uses, for now. SR-XXXX")),
621671
]
672+
673+
#if canImport(Darwin)
674+
tests += [
675+
("test_resolvingSymlinksInPathShouldRemovePrivatePrefix", test_resolvingSymlinksInPathShouldRemovePrivatePrefix),
676+
("test_resolvingSymlinksInPathShouldNotRemovePrivatePrefixIfOnlyComponent", test_resolvingSymlinksInPathShouldNotRemovePrivatePrefixIfOnlyComponent),
677+
]
678+
#endif
679+
680+
return tests
622681
}
623682
}
624683

0 commit comments

Comments
 (0)