diff --git a/Package.swift b/Package.swift index 2677b10ef65..75b7d7fb74d 100644 --- a/Package.swift +++ b/Package.swift @@ -717,7 +717,12 @@ let package = Package( .testTarget( name: "BasicsTests", - dependencies: ["Basics", "_InternalTestSupport", "tsan_utils"], + dependencies: [ + "Basics", + "_InternalTestSupport", + "tsan_utils", + .product(name: "Numerics", package: "swift-numerics"), + ], exclude: [ "Archiver/Inputs/archive.tar.gz", "Archiver/Inputs/archive.zip", @@ -959,6 +964,8 @@ if ProcessInfo.processInfo.environment["SWIFTCI_USE_LOCAL_DEPS"] == nil { .package(url: "https://github.com/apple/swift-collections.git", "1.0.1" ..< "1.2.0"), .package(url: "https://github.com/apple/swift-certificates.git", "1.0.1" ..< "1.6.0"), .package(url: "https://github.com/swiftlang/swift-toolchain-sqlite.git", from: "1.0.0"), + // Test Dependencies + .package(url: "https://github.com/apple/swift-numerics", exact: "1.0.2") ] } else { package.dependencies += [ @@ -971,5 +978,7 @@ if ProcessInfo.processInfo.environment["SWIFTCI_USE_LOCAL_DEPS"] == nil { .package(path: "../swift-collections"), .package(path: "../swift-certificates"), .package(path: "../swift-toolchain-sqlite"), + // Test Dependencies + .package(path: "../swift-numerics"), ] } diff --git a/Sources/_InternalTestSupport/XCTAssertHelpers.swift b/Sources/_InternalTestSupport/XCTAssertHelpers.swift index e7e3956f2bf..e2ff5c325f1 100644 --- a/Sources/_InternalTestSupport/XCTAssertHelpers.swift +++ b/Sources/_InternalTestSupport/XCTAssertHelpers.swift @@ -43,8 +43,12 @@ public func XCTAssertEqual (_ lhs:(T,U), _ rhs:(T,U), TSCTestSupport.XCTAssertEqual(lhs, rhs, file: file, line: line) } +public func isRunninginCI(file: StaticString = #filePath, line: UInt = #line) -> Bool { + return (ProcessInfo.processInfo.environment["SWIFTCI_USE_LOCAL_DEPS"] != nil || ProcessInfo.processInfo.environment["CI"] != nil) +} + public func XCTSkipIfCI(file: StaticString = #filePath, line: UInt = #line) throws { - if ProcessInfo.processInfo.environment["SWIFTCI_USE_LOCAL_DEPS"] != nil { + if isRunninginCI() { throw XCTSkip("Skipping because the test is being run on CI", file: file, line: line) } } diff --git a/Tests/BasicsTests/Archiver/ZipArchiverTests.swift b/Tests/BasicsTests/Archiver/ZipArchiverTests.swift index c8a5e113f0b..9f28503ab1c 100644 --- a/Tests/BasicsTests/Archiver/ZipArchiverTests.swift +++ b/Tests/BasicsTests/Archiver/ZipArchiverTests.swift @@ -104,56 +104,56 @@ final class ZipArchiverTests: XCTestCase { #endif try await testWithTemporaryDirectory { tmpdir in - let archiver = ZipArchiver(fileSystem: localFileSystem) - - let rootDir = tmpdir.appending(component: UUID().uuidString) - try localFileSystem.createDirectory(rootDir) - try localFileSystem.writeFileContents(rootDir.appending("file1.txt"), string: "Hello World!") - - let dir1 = rootDir.appending("dir1") - try localFileSystem.createDirectory(dir1) - try localFileSystem.writeFileContents(dir1.appending("file2.txt"), string: "Hello World 2!") - - let dir2 = dir1.appending("dir2") - try localFileSystem.createDirectory(dir2) - try localFileSystem.writeFileContents(dir2.appending("file3.txt"), string: "Hello World 3!") - try localFileSystem.writeFileContents(dir2.appending("file4.txt"), string: "Hello World 4!") - - let archivePath = tmpdir.appending(component: UUID().uuidString + ".zip") - try await archiver.compress(directory: rootDir, to: archivePath) - XCTAssertFileExists(archivePath) - - let extractRootDir = tmpdir.appending(component: UUID().uuidString) - try localFileSystem.createDirectory(extractRootDir) - try await archiver.extract(from: archivePath, to: extractRootDir) - try localFileSystem.stripFirstLevel(of: extractRootDir) - - XCTAssertFileExists(extractRootDir.appending("file1.txt")) - XCTAssertEqual( - try? localFileSystem.readFileContents(extractRootDir.appending("file1.txt")), - "Hello World!" - ) - - let extractedDir1 = extractRootDir.appending("dir1") - XCTAssertDirectoryExists(extractedDir1) - XCTAssertFileExists(extractedDir1.appending("file2.txt")) - XCTAssertEqual( - try? localFileSystem.readFileContents(extractedDir1.appending("file2.txt")), - "Hello World 2!" - ) - - let extractedDir2 = extractedDir1.appending("dir2") - XCTAssertDirectoryExists(extractedDir2) - XCTAssertFileExists(extractedDir2.appending("file3.txt")) - XCTAssertEqual( - try? localFileSystem.readFileContents(extractedDir2.appending("file3.txt")), - "Hello World 3!" - ) - XCTAssertFileExists(extractedDir2.appending("file4.txt")) - XCTAssertEqual( - try? localFileSystem.readFileContents(extractedDir2.appending("file4.txt")), - "Hello World 4!" - ) + let archiver = ZipArchiver(fileSystem: localFileSystem) + + let rootDir = tmpdir.appending(component: UUID().uuidString) + try localFileSystem.createDirectory(rootDir) + try localFileSystem.writeFileContents(rootDir.appending("file1.txt"), string: "Hello World!") + + let dir1 = rootDir.appending("dir1") + try localFileSystem.createDirectory(dir1) + try localFileSystem.writeFileContents(dir1.appending("file2.txt"), string: "Hello World 2!") + + let dir2 = dir1.appending("dir2") + try localFileSystem.createDirectory(dir2) + try localFileSystem.writeFileContents(dir2.appending("file3.txt"), string: "Hello World 3!") + try localFileSystem.writeFileContents(dir2.appending("file4.txt"), string: "Hello World 4!") + + let archivePath = tmpdir.appending(component: UUID().uuidString + ".zip") + try await archiver.compress(directory: rootDir, to: archivePath) + XCTAssertFileExists(archivePath) + + let extractRootDir = tmpdir.appending(component: UUID().uuidString) + try localFileSystem.createDirectory(extractRootDir) + try await archiver.extract(from: archivePath, to: extractRootDir) + try localFileSystem.stripFirstLevel(of: extractRootDir) + + XCTAssertFileExists(extractRootDir.appending("file1.txt")) + XCTAssertEqual( + try? localFileSystem.readFileContents(extractRootDir.appending("file1.txt")), + "Hello World!" + ) + + let extractedDir1 = extractRootDir.appending("dir1") + XCTAssertDirectoryExists(extractedDir1) + XCTAssertFileExists(extractedDir1.appending("file2.txt")) + XCTAssertEqual( + try? localFileSystem.readFileContents(extractedDir1.appending("file2.txt")), + "Hello World 2!" + ) + + let extractedDir2 = extractedDir1.appending("dir2") + XCTAssertDirectoryExists(extractedDir2) + XCTAssertFileExists(extractedDir2.appending("file3.txt")) + XCTAssertEqual( + try? localFileSystem.readFileContents(extractedDir2.appending("file3.txt")), + "Hello World 3!" + ) + XCTAssertFileExists(extractedDir2.appending("file4.txt")) + XCTAssertEqual( + try? localFileSystem.readFileContents(extractedDir2.appending("file4.txt")), + "Hello World 4!" + ) } } } diff --git a/Tests/BasicsTests/AsyncProcessTests.swift b/Tests/BasicsTests/AsyncProcessTests.swift index cae5f2cd604..b4ad012cbdd 100644 --- a/Tests/BasicsTests/AsyncProcessTests.swift +++ b/Tests/BasicsTests/AsyncProcessTests.swift @@ -7,11 +7,12 @@ See http://swift.org/LICENSE.txt for license information See http://swift.org/CONTRIBUTORS.txt for Swift project authors */ +import Foundation import _InternalTestSupport import _Concurrency import Basics -import XCTest +import Testing import TSCclibc // for SPM_posix_spawn_file_actions_addchdir_np_supported @@ -22,33 +23,39 @@ import class TSCBasic.Thread import func TSCBasic.withTemporaryFile import func TSCTestSupport.withCustomEnv -final class AsyncProcessTests: XCTestCase { - func testBasics() throws { +@Suite( + // because suite is very flaky otherwise. Need to investigate whether the tests can run in parallel + .serialized +) +struct AsyncProcessTests { + @Test + func basics() throws { do { let process = AsyncProcess(args: "echo", "hello") try process.launch() let result = try process.waitUntilExit() - XCTAssertEqual(try result.utf8Output(), "hello\n") - XCTAssertEqual(result.exitStatus, .terminated(code: 0)) - XCTAssertEqual(result.arguments, process.arguments) + #expect(try result.utf8Output() == "hello\n") + #expect(result.exitStatus == .terminated(code: 0)) + #expect(result.arguments == process.arguments) } do { let process = AsyncProcess(scriptName: "exit4") try process.launch() let result = try process.waitUntilExit() - XCTAssertEqual(result.exitStatus, .terminated(code: 4)) + #expect(result.exitStatus == .terminated(code: 4)) } } - func testPopen() throws { - #if os(Windows) + @Test + func popen() throws { +#if os(Windows) let echo = "echo.exe" - #else +#else let echo = "echo" - #endif +#endif // Test basic echo. - XCTAssertEqual(try AsyncProcess.popen(arguments: [echo, "hello"]).utf8Output(), "hello\n") + #expect(try AsyncProcess.popen(arguments: [echo, "hello"]).utf8Output() == "hello\n") // Test buffer larger than that allocated. try withTemporaryFile { file in @@ -56,24 +63,25 @@ final class AsyncProcessTests: XCTestCase { let stream = BufferedOutputByteStream() stream.send(Format.asRepeating(string: "a", count: count)) try localFileSystem.writeFileContents(file.path, bytes: stream.bytes) - #if os(Windows) +#if os(Windows) let cat = "cat.exe" - #else +#else let cat = "cat" - #endif +#endif let outputCount = try AsyncProcess.popen(args: cat, file.path.pathString).utf8Output().count - XCTAssert(outputCount == count) + #expect(outputCount == count) } } - func testPopenLegacyAsync() throws { - #if os(Windows) + @Test + func popenLegacyAsync() throws { +#if os(Windows) let args = ["where.exe", "where"] let answer = "C:\\Windows\\System32\\where.exe" - #else +#else let args = ["whoami"] let answer = NSUserName() - #endif +#endif var popenResult: Result? let group = DispatchGroup() group.enter() @@ -83,72 +91,75 @@ final class AsyncProcessTests: XCTestCase { } group.wait() switch popenResult { - case .success(let processResult): - let output = try processResult.utf8Output() - XCTAssertTrue(output.hasPrefix(answer)) - case .failure(let error): - XCTFail("error = \(error)") - case nil: - XCTFail() + case .success(let processResult): + let output = try processResult.utf8Output() + #expect(output.hasPrefix(answer)) + case .failure(let error): + throw error + case nil: + Issue.record("AsyncProcess.popen did not yield a result!") } } + @Test @available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) - func testPopenAsync() async throws { - #if os(Windows) + func popenAsync() async throws { +#if os(Windows) let args = ["where.exe", "where"] let answer = "C:\\Windows\\System32\\where.exe" - #else +#else let args = ["whoami"] let answer = NSUserName() - #endif +#endif let processResult: AsyncProcessResult do { processResult = try await AsyncProcess.popen(arguments: args) } catch { - XCTFail("error = \(error)") - return + throw error } let output = try processResult.utf8Output() - XCTAssertTrue(output.hasPrefix(answer)) + #expect(output.hasPrefix(answer)) } - func testCheckNonZeroExit() throws { + @Test + func checkNonZeroExit() throws { do { let output = try AsyncProcess.checkNonZeroExit(args: "echo", "hello") - XCTAssertEqual(output, "hello\n") + #expect(output == "hello\n") } do { let output = try AsyncProcess.checkNonZeroExit(scriptName: "exit4") - XCTFail("Unexpected success \(output)") + Issue.record("Unexpected success \(output)") } catch AsyncProcessResult.Error.nonZeroExit(let result) { - XCTAssertEqual(result.exitStatus, .terminated(code: 4)) + #expect(result.exitStatus == .terminated(code: 4)) } } + @Test @available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) - func testCheckNonZeroExitAsync() async throws { + func checkNonZeroExitAsync() async throws { do { let output = try await AsyncProcess.checkNonZeroExit(args: "echo", "hello") - XCTAssertEqual(output, "hello\n") + #expect(output == "hello\n") } do { let output = try await AsyncProcess.checkNonZeroExit(scriptName: "exit4") - XCTFail("Unexpected success \(output)") + Issue.record("Unexpected success \(output)") } catch AsyncProcessResult.Error.nonZeroExit(let result) { - XCTAssertEqual(result.exitStatus, .terminated(code: 4)) + #expect(result.exitStatus == .terminated(code: 4)) } } - func testFindExecutable() throws { + @Test + func findExecutable() throws { try testWithTemporaryDirectory { tmpdir in // This process should always work. - XCTAssertTrue(AsyncProcess.findExecutable("ls") != nil) + #expect(AsyncProcess.findExecutable("ls") != nil) - XCTAssertEqual(AsyncProcess.findExecutable("nonExistantProgram"), nil) - XCTAssertEqual(AsyncProcess.findExecutable(""), nil) + #expect(AsyncProcess.findExecutable("nonExistantProgram") == nil) + #expect(AsyncProcess.findExecutable("") == nil) // Create a local nonexecutable file to test. let tempExecutable = tmpdir.appending(component: "nonExecutableProgram") @@ -159,12 +170,13 @@ final class AsyncProcessTests: XCTestCase { """) try withCustomEnv(["PATH": tmpdir.pathString]) { - XCTAssertEqual(AsyncProcess.findExecutable("nonExecutableProgram"), nil) + #expect(AsyncProcess.findExecutable("nonExecutableProgram") == nil) } } } - func testNonExecutableLaunch() throws { + @Test + func nonExecutableLaunch() throws { try testWithTemporaryDirectory { tmpdir in // Create a local nonexecutable file to test. let tempExecutable = tmpdir.appending(component: "nonExecutableProgram") @@ -178,15 +190,16 @@ final class AsyncProcessTests: XCTestCase { do { let process = AsyncProcess(args: "nonExecutableProgram") try process.launch() - XCTFail("Should have failed to validate nonExecutableProgram") + Issue.record("Should have failed to validate nonExecutableProgram") } catch AsyncProcess.Error.missingExecutableProgram(let program) { - XCTAssert(program == "nonExecutableProgram") + #expect(program == "nonExecutableProgram") } } } } - func testThreadSafetyOnWaitUntilExit() throws { + @Test + func threadSafetyOnWaitUntilExit() throws { let process = AsyncProcess(args: "echo", "hello") try process.launch() @@ -206,12 +219,13 @@ final class AsyncProcessTests: XCTestCase { t1.join() t2.join() - XCTAssertEqual(result1, "hello\n") - XCTAssertEqual(result2, "hello\n") + #expect(result1 == "hello\n") + #expect(result2 == "hello\n") } + @Test @available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *) - func testThreadSafetyOnWaitUntilExitAsync() async throws { + func threadSafetyOnWaitUntilExitAsync() async throws { let process = AsyncProcess(args: "echo", "hello") try process.launch() @@ -226,11 +240,12 @@ final class AsyncProcessTests: XCTestCase { let result1 = try await t1.value let result2 = try await t2.value - XCTAssertEqual(result1, "hello\n") - XCTAssertEqual(result2, "hello\n") + #expect(result1 == "hello\n") + #expect(result2 == "hello\n") } - func testStdin() throws { + @Test + func stdin() throws { var stdout = [UInt8]() let process = AsyncProcess(scriptName: "in-to-out", outputRedirection: .stream(stdout: { stdoutBytes in stdout += stdoutBytes @@ -244,62 +259,63 @@ final class AsyncProcessTests: XCTestCase { try process.waitUntilExit() - XCTAssertEqual(String(decoding: stdout, as: UTF8.self), "hello\n") + #expect(String(decoding: stdout, as: UTF8.self) == "hello\n") } - func testStdoutStdErr() throws { - // A simple script to check that stdout and stderr are captured separatly. + @Test + func stdoutStdErr() throws { do { let result = try AsyncProcess.popen(scriptName: "simple-stdout-stderr") - XCTAssertEqual(try result.utf8Output(), "simple output\n") - XCTAssertEqual(try result.utf8stderrOutput(), "simple error\n") + #expect(try result.utf8Output() == "simple output\n") + #expect(try result.utf8stderrOutput() == "simple error\n") } // A long stdout and stderr output. do { let result = try AsyncProcess.popen(scriptName: "long-stdout-stderr") let count = 16 * 1024 - XCTAssertEqual(try result.utf8Output(), String(repeating: "1", count: count)) - XCTAssertEqual(try result.utf8stderrOutput(), String(repeating: "2", count: count)) + #expect(try result.utf8Output() == String(repeating: "1", count: count)) + #expect(try result.utf8stderrOutput() == String(repeating: "2", count: count)) } // This script will block if the streams are not read. do { let result = try AsyncProcess.popen(scriptName: "deadlock-if-blocking-io") let count = 16 * 1024 - XCTAssertEqual(try result.utf8Output(), String(repeating: "1", count: count)) - XCTAssertEqual(try result.utf8stderrOutput(), String(repeating: "2", count: count)) + #expect(try result.utf8Output() == String(repeating: "1", count: count)) + #expect(try result.utf8stderrOutput() == String(repeating: "2", count: count)) } } + @Test @available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) - func testStdoutStdErrAsync() async throws { - // A simple script to check that stdout and stderr are captured separatly. + func stdoutStdErrAsync() async throws { + // A simple script to check that stdout and stderr are captured separatly do { let result = try await AsyncProcess.popen(scriptName: "simple-stdout-stderr") - XCTAssertEqual(try result.utf8Output(), "simple output\n") - XCTAssertEqual(try result.utf8stderrOutput(), "simple error\n") + #expect(try result.utf8Output() == "simple output\n") + #expect(try result.utf8stderrOutput() == "simple error\n") } // A long stdout and stderr output. do { let result = try await AsyncProcess.popen(scriptName: "long-stdout-stderr") let count = 16 * 1024 - XCTAssertEqual(try result.utf8Output(), String(repeating: "1", count: count)) - XCTAssertEqual(try result.utf8stderrOutput(), String(repeating: "2", count: count)) + #expect(try result.utf8Output() == String(repeating: "1", count: count)) + #expect(try result.utf8stderrOutput() == String(repeating: "2", count: count)) } // This script will block if the streams are not read. do { let result = try await AsyncProcess.popen(scriptName: "deadlock-if-blocking-io") let count = 16 * 1024 - XCTAssertEqual(try result.utf8Output(), String(repeating: "1", count: count)) - XCTAssertEqual(try result.utf8stderrOutput(), String(repeating: "2", count: count)) + #expect(try result.utf8Output() == String(repeating: "1", count: count)) + #expect(try result.utf8stderrOutput() == String(repeating: "2", count: count)) } } - func testStdoutStdErrRedirected() throws { - // A simple script to check that stdout and stderr are captured in the same location. + @Test + func stdoutStdErrRedirected() throws { do { let process = AsyncProcess( scriptName: "simple-stdout-stderr", @@ -307,8 +323,8 @@ final class AsyncProcessTests: XCTestCase { ) try process.launch() let result = try process.waitUntilExit() - XCTAssertEqual(try result.utf8Output(), "simple error\nsimple output\n") - XCTAssertEqual(try result.utf8stderrOutput(), "") + #expect(try result.utf8Output() == "simple error\nsimple output\n") + #expect(try result.utf8stderrOutput() == "") } // A long stdout and stderr output. @@ -321,12 +337,13 @@ final class AsyncProcessTests: XCTestCase { let result = try process.waitUntilExit() let count = 16 * 1024 - XCTAssertEqual(try result.utf8Output(), String(repeating: "12", count: count)) - XCTAssertEqual(try result.utf8stderrOutput(), "") + #expect(try result.utf8Output() == String(repeating: "12", count: count)) + #expect(try result.utf8stderrOutput() == "") } } - func testStdoutStdErrStreaming() throws { + @Test + func stdoutStdErrStreaming() throws { var stdout = [UInt8]() var stderr = [UInt8]() let process = AsyncProcess(scriptName: "long-stdout-stderr", outputRedirection: .stream(stdout: { stdoutBytes in @@ -338,11 +355,12 @@ final class AsyncProcessTests: XCTestCase { try process.waitUntilExit() let count = 16 * 1024 - XCTAssertEqual(String(bytes: stdout, encoding: .utf8), String(repeating: "1", count: count)) - XCTAssertEqual(String(bytes: stderr, encoding: .utf8), String(repeating: "2", count: count)) + #expect(String(bytes: stdout, encoding: .utf8) == String(repeating: "1", count: count)) + #expect(String(bytes: stderr, encoding: .utf8) == String(repeating: "2", count: count)) } - func testStdoutStdErrStreamingRedirected() throws { + @Test + func stdoutStdErrStreamingRedirected() throws { var stdout = [UInt8]() var stderr = [UInt8]() let process = AsyncProcess(scriptName: "long-stdout-stderr", outputRedirection: .stream(stdout: { stdoutBytes in @@ -354,22 +372,20 @@ final class AsyncProcessTests: XCTestCase { try process.waitUntilExit() let count = 16 * 1024 - XCTAssertEqual(String(bytes: stdout, encoding: .utf8), String(repeating: "12", count: count)) - XCTAssertEqual(stderr, []) + #expect(String(bytes: stdout, encoding: .utf8) == String(repeating: "12", count: count)) + #expect(stderr == []) } - func testWorkingDirectory() throws { - guard #available(macOS 10.15, *) else { - // Skip this test since it's not supported in this OS. - return - } + @Test + @available(macOS 10.15, *) + func workingDirectory() throws { - #if os(Linux) || os(Android) +#if os(Linux) || os(Android) guard SPM_posix_spawn_file_actions_addchdir_np_supported() else { // Skip this test since it's not supported in this OS. return } - #endif +#endif try withTemporaryDirectory(removeTreeOnDeinit: true) { tempDirPath in let parentPath = tempDirPath.appending(component: "file") @@ -383,22 +399,23 @@ final class AsyncProcessTests: XCTestCase { let process = AsyncProcess(arguments: ["cat", "file"], workingDirectory: tempDirPath) try process.launch() let result = try process.waitUntilExit() - XCTAssertEqual(try result.utf8Output(), "parent") + #expect(try result.utf8Output() == "parent") } do { let process = AsyncProcess(arguments: ["cat", "file"], workingDirectory: childPath.parentDirectory) try process.launch() let result = try process.waitUntilExit() - XCTAssertEqual(try result.utf8Output(), "child") + #expect(try result.utf8Output() == "child") } } } - func testAsyncStream() async throws { - // rdar://133548796 - try XCTSkipIfCI() - + @Test( + .disabled(if: isRunninginCI(), "Disabled in CI"), + .bug("rdar://133548796") + ) + func asyncStream() async throws { let (stdoutStream, stdoutContinuation) = AsyncProcess.ReadableStream.makeStream() let (stderrStream, stderrContinuation) = AsyncProcess.ReadableStream.makeStream() @@ -420,14 +437,14 @@ final class AsyncProcessTests: XCTestCase { stdin.flush() for await output in stdoutStream { - XCTAssertEqual(output, .init("Hello \(counter)\n".utf8)) + #expect(output == .init("Hello \(counter)\n".utf8)) counter += 1 stdin.write(.init("Hello \(counter)\n".utf8)) stdin.flush() } - XCTAssertEqual(counter, 5) + #expect(counter == 5) try stdin.close() } @@ -438,7 +455,7 @@ final class AsyncProcessTests: XCTestCase { counter += 1 } - XCTAssertEqual(counter, 0) + #expect(counter == 0) } defer { @@ -449,13 +466,14 @@ final class AsyncProcessTests: XCTestCase { return try await process.waitUntilExit() } - XCTAssertEqual(result.exitStatus, .terminated(code: 0)) + #expect(result.exitStatus == .terminated(code: 0)) } - func testAsyncStreamHighLevelAPI() async throws { - // rdar://133548796 - try XCTSkipIfCI() - + @Test( + .disabled(if: isRunninginCI(), "Disabled in CI"), + .bug("rdar://133548796") + ) + func asyncStreamHighLevelAPI() async throws { let result = try await AsyncProcess.popen( scriptName: "echo", stdout: { stdin, stdout in @@ -464,14 +482,14 @@ final class AsyncProcessTests: XCTestCase { stdin.flush() for await output in stdout { - XCTAssertEqual(output, .init("Hello \(counter)\n".utf8)) + #expect(output == .init("Hello \(counter)\n".utf8)) counter += 1 stdin.write(.init("Hello \(counter)\n".utf8)) stdin.flush() } - XCTAssertEqual(counter, 5) + #expect(counter == 5) try stdin.close() }, @@ -481,11 +499,11 @@ final class AsyncProcessTests: XCTestCase { counter += 1 } - XCTAssertEqual(counter, 0) + #expect(counter == 0) } ) - XCTAssertEqual(result.exitStatus, .terminated(code: 0)) + #expect(result.exitStatus == .terminated(code: 0)) } } diff --git a/Tests/BasicsTests/ByteStringExtensionsTests.swift b/Tests/BasicsTests/ByteStringExtensionsTests.swift index 7659695c0e5..88bde18c450 100644 --- a/Tests/BasicsTests/ByteStringExtensionsTests.swift +++ b/Tests/BasicsTests/ByteStringExtensionsTests.swift @@ -9,18 +9,20 @@ // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// +import Foundation import Basics -import XCTest +import Testing import struct TSCBasic.ByteString -final class ByteStringExtensionsTests: XCTestCase { - func testSHA256Checksum() { +struct ByteStringExtensionsTests { + @Test + func sHA256Checksum() { let byteString = ByteString(encodingAsUTF8: "abc") - XCTAssertEqual(byteString.contents, [0x61, 0x62, 0x63]) + #expect(byteString.contents == [0x61, 0x62, 0x63]) // See https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/examples/sha_all.pdf - XCTAssertEqual(byteString.sha256Checksum, "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad") + #expect(byteString.sha256Checksum == "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad") } } diff --git a/Tests/BasicsTests/ConcurrencyHelpersTests.swift b/Tests/BasicsTests/ConcurrencyHelpersTests.swift index 2efa891fded..8151fa67f9f 100644 --- a/Tests/BasicsTests/ConcurrencyHelpersTests.swift +++ b/Tests/BasicsTests/ConcurrencyHelpersTests.swift @@ -9,15 +9,17 @@ // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// +import Foundation @testable import Basics import TSCTestSupport -import XCTest +import Testing -final class ConcurrencyHelpersTest: XCTestCase { +struct ConcurrencyHelpersTest { let queue = DispatchQueue(label: "ConcurrencyHelpersTest", attributes: .concurrent) - func testThreadSafeKeyValueStore() { + @Test + func threadSafeKeyValueStore() { for _ in 0 ..< 100 { let sync = DispatchGroup() @@ -42,17 +44,18 @@ final class ConcurrencyHelpersTest: XCTestCase { } switch sync.wait(timeout: .now() + .seconds(2)) { - case .timedOut: - XCTFail("timeout") - case .success: - expected.forEach { key, value in - XCTAssertEqual(cache[key], value) - } + case .timedOut: + Issue.record("timeout") + case .success: + expected.forEach { key, value in + #expect(cache[key] == value) + } } } } - func testThreadSafeArrayStore() { + @Test + func threadSafeArrayStore() { for _ in 0 ..< 100 { let sync = DispatchGroup() @@ -72,17 +75,18 @@ final class ConcurrencyHelpersTest: XCTestCase { } switch sync.wait(timeout: .now() + .seconds(2)) { - case .timedOut: - XCTFail("timeout") - case .success: - let expectedSorted = expected.sorted() - let resultsSorted = cache.get().sorted() - XCTAssertEqual(expectedSorted, resultsSorted) + case .timedOut: + Issue.record("timeout") + case .success: + let expectedSorted = expected.sorted() + let resultsSorted = cache.get().sorted() + #expect(expectedSorted == resultsSorted) } } } - func testThreadSafeBox() { + @Test + func threadSafeBox() { for _ in 0 ..< 100 { let sync = DispatchGroup() @@ -109,10 +113,10 @@ final class ConcurrencyHelpersTest: XCTestCase { } switch sync.wait(timeout: .now() + .seconds(2)) { - case .timedOut: - XCTFail("timeout") - case .success: - XCTAssertEqual(cache.get(), winner) + case .timedOut: + Issue.record("timeout") + case .success: + #expect(cache.get() == winner) } } } diff --git a/Tests/BasicsTests/DictionaryTest.swift b/Tests/BasicsTests/DictionaryTest.swift index 88e4cbbd913..b53ae06463a 100644 --- a/Tests/BasicsTests/DictionaryTest.swift +++ b/Tests/BasicsTests/DictionaryTest.swift @@ -11,26 +11,27 @@ //===----------------------------------------------------------------------===// @testable import Basics -import XCTest +import Testing -final class DictionaryTests: XCTestCase { - func testThrowingUniqueKeysWithValues() throws { +struct DictionaryTests { + @Test + func throwingUniqueKeysWithValues() throws { do { let keysWithValues = [("key1", "value1"), ("key2", "value2")] let dictionary = try Dictionary(throwingUniqueKeysWithValues: keysWithValues) - XCTAssertEqual(dictionary["key1"], "value1") - XCTAssertEqual(dictionary["key2"], "value2") + #expect(dictionary["key1"] == "value1") + #expect(dictionary["key2"] == "value2") } do { let keysWithValues = [("key1", "value"), ("key2", "value")] let dictionary = try Dictionary(throwingUniqueKeysWithValues: keysWithValues) - XCTAssertEqual(dictionary["key1"], "value") - XCTAssertEqual(dictionary["key2"], "value") + #expect(dictionary["key1"] == "value") + #expect(dictionary["key2"] == "value") } do { let keysWithValues = [("key", "value1"), ("key", "value2")] - XCTAssertThrowsError(try Dictionary(throwingUniqueKeysWithValues: keysWithValues)) { error in - XCTAssertEqual(error as? StringError, StringError("duplicate key found: 'key'")) + #expect(throws: StringError("duplicate key found: 'key'")) { + try Dictionary(throwingUniqueKeysWithValues: keysWithValues) } } } diff --git a/Tests/BasicsTests/DispatchTimeTests.swift b/Tests/BasicsTests/DispatchTimeTests.swift index 12286be62e4..50ff32f74da 100644 --- a/Tests/BasicsTests/DispatchTimeTests.swift +++ b/Tests/BasicsTests/DispatchTimeTests.swift @@ -9,30 +9,33 @@ // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// +import Foundation import Basics -import XCTest +import Testing -final class DispatchTimeTests: XCTestCase { - func testDifferencePositive() { +struct DispatchTimeTests { + @Test + func differencePositive() { let point: DispatchTime = .now() let future: DispatchTime = point + .seconds(10) let diff1: DispatchTimeInterval = point.distance(to: future) - XCTAssertEqual(diff1.seconds(), 10) + #expect(diff1.seconds() == 10) let diff2: DispatchTimeInterval = future.distance(to: point) - XCTAssertEqual(diff2.seconds(), -10) + #expect(diff2.seconds() == -10) } - func testDifferenceNegative() { + @Test + func differenceNegative() { let point: DispatchTime = .now() let past: DispatchTime = point - .seconds(10) let diff1: DispatchTimeInterval = point.distance(to: past) - XCTAssertEqual(diff1.seconds(), -10) + #expect(diff1.seconds() == -10) let diff2: DispatchTimeInterval = past.distance(to: point) - XCTAssertEqual(diff2.seconds(), 10) + #expect(diff2.seconds() == 10) } } diff --git a/Tests/BasicsTests/Environment/EnvironmentKeyTests.swift b/Tests/BasicsTests/Environment/EnvironmentKeyTests.swift index 60f6b0cb0ee..906f3ec0018 100644 --- a/Tests/BasicsTests/Environment/EnvironmentKeyTests.swift +++ b/Tests/BasicsTests/Environment/EnvironmentKeyTests.swift @@ -9,84 +9,93 @@ // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// +import Foundation @testable import Basics -import XCTest +import Testing -final class EnvironmentKeyTests: XCTestCase { - func test_comparable() { +struct EnvironmentKeyTests { + @Test + func comparable() { let key0 = EnvironmentKey("Test") let key1 = EnvironmentKey("Test1") - XCTAssertLessThan(key0, key1) + #expect(key0 < key1) let key2 = EnvironmentKey("test") - XCTAssertLessThan(key0, key2) + #expect(key0 < key2) } - func test_customStringConvertible() { + @Test + func customStringConvertible() { let key = EnvironmentKey("Test") - XCTAssertEqual(key.description, "Test") + #expect(key.description == "Test") } - func test_encodable() throws { + @Test + func encodable() throws { let key = EnvironmentKey("Test") let data = try JSONEncoder().encode(key) let string = String(data: data, encoding: .utf8) - XCTAssertEqual(string, #""Test""#) + #expect(string == #""Test""#) } - func test_equatable() { + @Test + func equatable() { let key0 = EnvironmentKey("Test") let key1 = EnvironmentKey("Test") - XCTAssertEqual(key0, key1) + #expect(key0 == key1) let key2 = EnvironmentKey("Test2") - XCTAssertNotEqual(key0, key2) + #expect(key0 != key2) - #if os(Windows) +#if os(Windows) // Test case insensitivity on windows let key3 = EnvironmentKey("teSt") - XCTAssertEqual(key0, key3) - #endif + #expect(key0 == key3) +#endif } - func test_expressibleByStringLiteral() { + @Test + func expressibleByStringLiteral() { let key0 = EnvironmentKey("Test") - XCTAssertEqual(key0, "Test") + #expect(key0 == "Test") } - func test_decodable() throws { + @Test + func decodable() throws { let jsonString = #""Test""# let data = jsonString.data(using: .utf8)! let key = try JSONDecoder().decode(EnvironmentKey.self, from: data) - XCTAssertEqual(key.rawValue, "Test") + #expect(key.rawValue == "Test") } - func test_hashable() { + @Test + func hashable() { var set = Set() let key0 = EnvironmentKey("Test") - XCTAssertTrue(set.insert(key0).inserted) + #expect(set.insert(key0).inserted) let key1 = EnvironmentKey("Test") - XCTAssertTrue(set.contains(key1)) - XCTAssertFalse(set.insert(key1).inserted) + #expect(set.contains(key1)) + #expect(!set.insert(key1).inserted) let key2 = EnvironmentKey("Test2") - XCTAssertFalse(set.contains(key2)) - XCTAssertTrue(set.insert(key2).inserted) + #expect(!set.contains(key2)) + #expect(set.insert(key2).inserted) - #if os(Windows) +#if os(Windows) // Test case insensitivity on windows let key3 = EnvironmentKey("teSt") - XCTAssertTrue(set.contains(key3)) - XCTAssertFalse(set.insert(key3).inserted) - #endif + #expect(set.contains(key3)) + #expect(!set.insert(key3).inserted) +#endif - XCTAssertEqual(set, ["Test", "Test2"]) + #expect(set == ["Test", "Test2"]) } - func test_rawRepresentable() { + @Test + func rawRepresentable() { let key = EnvironmentKey(rawValue: "Test") - XCTAssertEqual(key?.rawValue, "Test") + #expect(key?.rawValue == "Test") } } diff --git a/Tests/BasicsTests/Environment/EnvironmentTests.swift b/Tests/BasicsTests/Environment/EnvironmentTests.swift index 837d93706c4..6ff10ef4112 100644 --- a/Tests/BasicsTests/Environment/EnvironmentTests.swift +++ b/Tests/BasicsTests/Environment/EnvironmentTests.swift @@ -9,192 +9,208 @@ // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// +import Foundation @_spi(SwiftPMInternal) @testable import Basics -import XCTest +import Testing -final class EnvironmentTests: XCTestCase { - func test_init() { +struct EnvironmentTests { + @Test + func initialize() { let environment = Environment() - XCTAssertTrue(environment.isEmpty) + #expect(environment.isEmpty) } - func test_subscript() { + @Test + func setting_and_accessing_via_subscript() { var environment = Environment() let key = EnvironmentKey("TestKey") environment[key] = "TestValue" - XCTAssertEqual(environment[key], "TestValue") + #expect(environment[key] == "TestValue") } - func test_initDictionaryFromSelf() { + @Test + func initDictionaryFromSelf() { let dictionary = [ "TestKey": "TestValue", "testKey": "TestValue2", ] let environment = Environment(dictionary) - XCTAssertEqual(environment["TestKey"], "TestValue") - #if os(Windows) - XCTAssertEqual(environment.count, 1) - #else - XCTAssertEqual(environment.count, 2) - #endif + #expect(environment["TestKey"] == "TestValue") +#if os(Windows) + #expect(environment.count == 1) +#else + #expect(environment.count == 2) +#endif } - func test_initSelfFromDictionary() { + @Test + func initSelfFromDictionary() { let dictionary = ["TestKey": "TestValue"] let environment = Environment(dictionary) - XCTAssertEqual(environment["TestKey"], "TestValue") + #expect(environment["TestKey"] == "TestValue") } func path(_ components: String...) -> String { components.joined(separator: Environment.pathEntryDelimiter) } - func test_prependPath() { + @Test + func prependPath() { var environment = Environment() let key = EnvironmentKey(UUID().uuidString) - XCTAssertNil(environment[key]) + #expect(environment[key] == nil) environment.prependPath(key: key, value: "/bin") - XCTAssertEqual(environment[key], path("/bin")) + #expect(environment[key] == path("/bin")) environment.prependPath(key: key, value: "/usr/bin") - XCTAssertEqual(environment[key], path("/usr/bin", "/bin")) + #expect(environment[key] == path("/usr/bin", "/bin")) environment.prependPath(key: key, value: "/usr/local/bin") - XCTAssertEqual(environment[key], path("/usr/local/bin", "/usr/bin", "/bin")) + #expect(environment[key] == path("/usr/local/bin", "/usr/bin", "/bin")) environment.prependPath(key: key, value: "") - XCTAssertEqual(environment[key], path("/usr/local/bin", "/usr/bin", "/bin")) + #expect(environment[key] == path("/usr/local/bin", "/usr/bin", "/bin")) } - func test_appendPath() { + @Test + func appendPath() { var environment = Environment() let key = EnvironmentKey(UUID().uuidString) - XCTAssertNil(environment[key]) + #expect(environment[key] == nil) environment.appendPath(key: key, value: "/bin") - XCTAssertEqual(environment[key], path("/bin")) + #expect(environment[key] == path("/bin")) environment.appendPath(key: key, value: "/usr/bin") - XCTAssertEqual(environment[key], path("/bin", "/usr/bin")) + #expect(environment[key] == path("/bin", "/usr/bin")) environment.appendPath(key: key, value: "/usr/local/bin") - XCTAssertEqual(environment[key], path("/bin", "/usr/bin", "/usr/local/bin")) + #expect(environment[key] == path("/bin", "/usr/bin", "/usr/local/bin")) environment.appendPath(key: key, value: "") - XCTAssertEqual(environment[key], path("/bin", "/usr/bin", "/usr/local/bin")) + #expect(environment[key] == path("/bin", "/usr/bin", "/usr/local/bin")) } - func test_pathEntryDelimiter() { - #if os(Windows) - XCTAssertEqual(Environment.pathEntryDelimiter, ";") - #else - XCTAssertEqual(Environment.pathEntryDelimiter, ":") - #endif + @Test + func pathEntryDelimiter() { +#if os(Windows) + #expect(Environment.pathEntryDelimiter == ";") +#else + #expect(Environment.pathEntryDelimiter == ":") +#endif } /// Important: This test is inherently race-prone, if it is proven to be /// flaky, it should run in a singled threaded environment/removed entirely. - func test_current() { - XCTAssertEqual( - Environment.current["PATH"], - ProcessInfo.processInfo.environment["PATH"]) + @Test + func current() { + #expect(Environment.current["PATH"] == ProcessInfo.processInfo.environment["PATH"]) } /// Important: This test is inherently race-prone, if it is proven to be /// flaky, it should run in a singled threaded environment/removed entirely. - func test_makeCustom() async throws { + @Test + func makeCustom() async throws { let key = EnvironmentKey(UUID().uuidString) let value = "TestValue" var customEnvironment = Environment() customEnvironment[key] = value - XCTAssertNil(Environment.current[key]) + #expect(Environment.current[key] == nil) try Environment.makeCustom(customEnvironment) { - XCTAssertEqual(Environment.current[key], value) + #expect(Environment.current[key] == value) } - XCTAssertNil(Environment.current[key]) + #expect(Environment.current[key] == nil) } /// Important: This test is inherently race-prone, if it is proven to be /// flaky, it should run in a singled threaded environment/removed entirely. - func testProcess() throws { + @Test + func process() throws { let key = EnvironmentKey(UUID().uuidString) let value = "TestValue" var environment = Environment.current - XCTAssertNil(environment[key]) + #expect(environment[key] == nil) try Environment.set(key: key, value: value) environment = Environment.current // reload - XCTAssertEqual(environment[key], value) + #expect(environment[key] == value) try Environment.set(key: key, value: nil) - XCTAssertEqual(environment[key], value) // this is a copy! + #expect(environment[key] == value) // this is a copy! environment = Environment.current // reload - XCTAssertNil(environment[key]) + #expect(environment[key] == nil) } - func test_cachable() { + @Test + func cachable() { let term = EnvironmentKey("TERM") var environment = Environment() environment[.path] = "/usr/bin" environment[term] = "xterm-256color" let cachableEnvironment = environment.cachable - XCTAssertNotNil(cachableEnvironment[.path]) - XCTAssertNil(cachableEnvironment[term]) + #expect(cachableEnvironment[.path] != nil) + #expect(cachableEnvironment[term] == nil) } - func test_collection() { + @Test + func collection() { let environment: Environment = ["TestKey": "TestValue"] - XCTAssertEqual(environment.count, 1) - XCTAssertEqual(environment.first?.key, EnvironmentKey("TestKey")) - XCTAssertEqual(environment.first?.value, "TestValue") + #expect(environment.count == 1) + #expect(environment.first?.key == EnvironmentKey("TestKey")) + #expect(environment.first?.value == "TestValue") } - func test_description() { + @Test + func description() { var environment = Environment() environment[EnvironmentKey("TestKey")] = "TestValue" - XCTAssertEqual(environment.description, #"["TestKey=TestValue"]"#) + #expect(environment.description == #"["TestKey=TestValue"]"#) } - func test_encodable() throws { + @Test + func encodable() throws { var environment = Environment() environment["TestKey"] = "TestValue" let data = try JSONEncoder().encode(environment) let jsonString = String(data: data, encoding: .utf8) - XCTAssertEqual(jsonString, #"{"TestKey":"TestValue"}"#) + #expect(jsonString == #"{"TestKey":"TestValue"}"#) } - func test_equatable() { + @Test + func equatable() { let environment0: Environment = ["TestKey": "TestValue"] let environment1: Environment = ["TestKey": "TestValue"] - XCTAssertEqual(environment0, environment1) + #expect(environment0 == environment1) #if os(Windows) // Test case insensitivity on windows let environment2: Environment = ["testKey": "TestValue"] - XCTAssertEqual(environment0, environment2) + #expect(environment0 == environment2) #endif } - func test_expressibleByDictionaryLiteral() { + @Test + func expressibleByDictionaryLiteral() { let environment: Environment = ["TestKey": "TestValue"] - XCTAssertEqual(environment["TestKey"], "TestValue") + #expect(environment["TestKey"] == "TestValue") } - func test_decodable() throws { + @Test + func decodable() throws { let jsonString = #"{"TestKey":"TestValue"}"# let data = jsonString.data(using: .utf8)! let environment = try JSONDecoder().decode(Environment.self, from: data) - XCTAssertEqual(environment[EnvironmentKey("TestKey")], "TestValue") + #expect(environment[EnvironmentKey("TestKey")] == "TestValue") } } diff --git a/Tests/BasicsTests/FileSystem/FileSystemTests.swift b/Tests/BasicsTests/FileSystem/FileSystemTests.swift index 32c6ddb121d..b48bf702167 100644 --- a/Tests/BasicsTests/FileSystem/FileSystemTests.swift +++ b/Tests/BasicsTests/FileSystem/FileSystemTests.swift @@ -9,13 +9,15 @@ // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// +import Foundation @testable import Basics import TSCTestSupport -import XCTest +import Testing -final class FileSystemTests: XCTestCase { - func testStripFirstLevelComponent() throws { +struct FileSystemTests { + @Test + func stripFirstLevelComponent() throws { let fileSystem = InMemoryFileSystem() let rootPath = AbsolutePath("/root") @@ -35,29 +37,31 @@ final class FileSystemTests: XCTestCase { do { let contents = try fileSystem.getDirectoryContents(.root) - XCTAssertEqual(contents.count, 1) + #expect(contents.count == 1) } try fileSystem.stripFirstLevel(of: .root) do { let contents = Set(try fileSystem.getDirectoryContents(.root)) - XCTAssertEqual(contents.count, totalDirectories + totalFiles) + #expect(contents.count == totalDirectories + totalFiles) for index in 0 ..< totalDirectories { - XCTAssertTrue(contents.contains("dir\(index)")) + #expect(contents.contains("dir\(index)")) } for index in 0 ..< totalFiles { - XCTAssertTrue(contents.contains("file\(index)")) + #expect(contents.contains("file\(index)")) } } } - func testStripFirstLevelComponentErrors() throws { + @Test + func stripFirstLevelComponentErrors() throws { + let functionUnderTest = "stripFirstLevel" do { let fileSystem = InMemoryFileSystem() - XCTAssertThrowsError(try fileSystem.stripFirstLevel(of: .root), "expected error") { error in - XCTAssertMatch((error as? StringError)?.description, .contains("requires single top level directory")) + #expect(throws: StringError("\(functionUnderTest) requires single top level directory")) { + try fileSystem.stripFirstLevel(of: .root) } } @@ -67,8 +71,8 @@ final class FileSystemTests: XCTestCase { let path = AbsolutePath.root.appending("dir\(index)") try fileSystem.createDirectory(path, recursive: false) } - XCTAssertThrowsError(try fileSystem.stripFirstLevel(of: .root), "expected error") { error in - XCTAssertMatch((error as? StringError)?.description, .contains("requires single top level directory")) + #expect(throws: StringError("\(functionUnderTest) requires single top level directory")) { + try fileSystem.stripFirstLevel(of: .root) } } @@ -78,8 +82,8 @@ final class FileSystemTests: XCTestCase { let path = AbsolutePath.root.appending("file\(index)") try fileSystem.writeFileContents(path, string: "\(index)") } - XCTAssertThrowsError(try fileSystem.stripFirstLevel(of: .root), "expected error") { error in - XCTAssertMatch((error as? StringError)?.description, .contains("requires single top level directory")) + #expect(throws: StringError("\(functionUnderTest) requires single top level directory")) { + try fileSystem.stripFirstLevel(of: .root) } } @@ -87,8 +91,8 @@ final class FileSystemTests: XCTestCase { let fileSystem = InMemoryFileSystem() let path = AbsolutePath.root.appending("file") try fileSystem.writeFileContents(path, string: "") - XCTAssertThrowsError(try fileSystem.stripFirstLevel(of: .root), "expected error") { error in - XCTAssertMatch((error as? StringError)?.description, .contains("requires single top level directory")) + #expect(throws: StringError("\(functionUnderTest) requires single top level directory")) { + try fileSystem.stripFirstLevel(of: .root) } } } diff --git a/Tests/BasicsTests/FileSystem/PathShimTests.swift b/Tests/BasicsTests/FileSystem/PathShimTests.swift index 9d254a7ac1c..dec51eaa2e0 100644 --- a/Tests/BasicsTests/FileSystem/PathShimTests.swift +++ b/Tests/BasicsTests/FileSystem/PathShimTests.swift @@ -12,64 +12,65 @@ import Basics import Foundation -import XCTest +import Testing -class PathShimTests: XCTestCase { - func testRescursiveDirectoryCreation() { - // For the tests we'll need a temporary directory. - try! withTemporaryDirectory(removeTreeOnDeinit: true) { path in +struct PathShimTests { + @Test + func rescursiveDirectoryCreation() throws { + try withTemporaryDirectory(removeTreeOnDeinit: true) { path in // Create a directory under several ancestor directories. let dirPath = path.appending(components: "abc", "def", "ghi", "mno", "pqr") try! makeDirectories(dirPath) // Check that we were able to actually create the directory. - XCTAssertTrue(localFileSystem.isDirectory(dirPath)) + #expect(localFileSystem.isDirectory(dirPath)) // Check that there's no error if we try to create the directory again. - try! makeDirectories(dirPath) + #expect(throws: Never.self) { + try makeDirectories(dirPath) + } } } } -class WalkTests: XCTestCase { - func testNonRecursive() throws { - #if os(Android) +struct WalkTests { + @Test + func nonRecursive() throws { +#if os(Android) let root = "/system" var expected: [AbsolutePath] = [ "\(root)/usr", "\(root)/bin", "\(root)/xbin", ] - #elseif os(Windows) + let expectedCount = 3 +#elseif os(Windows) let root = ProcessInfo.processInfo.environment["SystemRoot"]! var expected: [AbsolutePath] = [ "\(root)/System32", "\(root)/SysWOW64", ] - #else + let expectedCount = (root as NSString).pathComponents.count +#else let root = "" var expected: [AbsolutePath] = [ "/usr", "/bin", "/sbin", ] - #endif + let expectedCount = 2 +#endif for x in try walk(AbsolutePath(validating: "\(root)/"), recursively: false) { if let i = expected.firstIndex(of: x) { expected.remove(at: i) } - #if os(Android) - XCTAssertEqual(3, x.components.count) - #elseif os(Windows) - XCTAssertEqual((root as NSString).pathComponents.count + 2, x.components.count) - #else - XCTAssertEqual(2, x.components.count) - #endif + #expect(expectedCount == x.components.count) } - XCTAssertEqual(expected.count, 0) + #expect(expected.count == 0) } - func testRecursive() { + @Test + func recursive() { let root = AbsolutePath(#file).parentDirectory.parentDirectory.parentDirectory.parentDirectory .appending(component: "Sources") var expected = [ @@ -82,6 +83,6 @@ class WalkTests: XCTestCase { expected.remove(at: i) } } - XCTAssertEqual(expected, []) + #expect(expected == []) } } diff --git a/Tests/BasicsTests/FileSystem/PathTests.swift b/Tests/BasicsTests/FileSystem/PathTests.swift index 1f9e7b7b80b..eb2744ccc5a 100644 --- a/Tests/BasicsTests/FileSystem/PathTests.swift +++ b/Tests/BasicsTests/FileSystem/PathTests.swift @@ -6,11 +6,11 @@ See http://swift.org/LICENSE.txt for license information See http://swift.org/CONTRIBUTORS.txt for Swift project authors -*/ + */ import Basics import Foundation -import XCTest +import Testing #if os(Windows) private var windows: Bool { true } @@ -18,330 +18,352 @@ private var windows: Bool { true } private var windows: Bool { false } #endif -class PathTests: XCTestCase { - func testBasics() { - XCTAssertEqual(AbsolutePath("/").pathString, windows ? #"\"# : "/") - XCTAssertEqual(AbsolutePath("/a").pathString, windows ? #"\a"# : "/a") - XCTAssertEqual(AbsolutePath("/a/b/c").pathString, windows ? #"\a\b\c"# : "/a/b/c") - XCTAssertEqual(RelativePath(".").pathString, ".") - XCTAssertEqual(RelativePath("a").pathString, "a") - XCTAssertEqual(RelativePath("a/b/c").pathString, windows ? #"a\b\c"# : "a/b/c") - XCTAssertEqual(RelativePath("~").pathString, "~") // `~` is not special +struct PathTests { + @Test + func basics() { + #expect(AbsolutePath("/").pathString == (windows ? #"\"# : "/")) + #expect(AbsolutePath("/a").pathString == (windows ? #"\a"# : "/a")) + #expect(AbsolutePath("/a/b/c").pathString == (windows ? #"\a\b\c"# : "/a/b/c")) + #expect(RelativePath(".").pathString == ".") + #expect(RelativePath("a").pathString == "a") + #expect(RelativePath("a/b/c").pathString == (windows ? #"a\b\c"# : "a/b/c")) + #expect(RelativePath("~").pathString == "~") // `~` is not special } - func testStringInitialization() throws { + @Test + func stringInitialization() throws { let abs1 = AbsolutePath("/") let abs2 = AbsolutePath(abs1, ".") - XCTAssertEqual(abs1, abs2) + #expect(abs1 == abs2) let rel3 = "." let abs3 = try AbsolutePath(abs2, validating: rel3) - XCTAssertEqual(abs2, abs3) + #expect(abs2 == abs3) let base = AbsolutePath("/base/path") let abs4 = AbsolutePath("/a/b/c", relativeTo: base) - XCTAssertEqual(abs4, AbsolutePath("/a/b/c")) + #expect(abs4 == AbsolutePath("/a/b/c")) let abs5 = AbsolutePath("./a/b/c", relativeTo: base) - XCTAssertEqual(abs5, AbsolutePath("/base/path/a/b/c")) + #expect(abs5 == AbsolutePath("/base/path/a/b/c")) let abs6 = AbsolutePath("~/bla", relativeTo: base) // `~` isn't special - XCTAssertEqual(abs6, AbsolutePath("/base/path/~/bla")) + #expect(abs6 == AbsolutePath("/base/path/~/bla")) } - func testStringLiteralInitialization() { + @Test + func stringLiteralInitialization() { let abs = AbsolutePath("/") - XCTAssertEqual(abs.pathString, windows ? #"\"# : "/") + #expect(abs.pathString == (windows ? #"\"# : "/")) let rel1 = RelativePath(".") - XCTAssertEqual(rel1.pathString, ".") + #expect(rel1.pathString == ".") let rel2 = RelativePath("~") - XCTAssertEqual(rel2.pathString, "~") // `~` is not special + #expect(rel2.pathString == "~") // `~` is not special } - func testRepeatedPathSeparators() { - XCTAssertEqual(AbsolutePath("/ab//cd//ef").pathString, windows ? #"\ab\cd\ef"# : "/ab/cd/ef") - XCTAssertEqual(AbsolutePath("/ab///cd//ef").pathString, windows ? #"\ab\cd\ef"# : "/ab/cd/ef") - XCTAssertEqual(RelativePath("ab//cd//ef").pathString, windows ? #"ab\cd\ef"# : "ab/cd/ef") - XCTAssertEqual(RelativePath("ab//cd///ef").pathString, windows ? #"ab\cd\ef"# : "ab/cd/ef") + @Test + func repeatedPathSeparators() { + #expect(AbsolutePath("/ab//cd//ef").pathString == (windows ? #"\ab\cd\ef"# : "/ab/cd/ef")) + #expect(AbsolutePath("/ab///cd//ef").pathString == (windows ? #"\ab\cd\ef"# : "/ab/cd/ef")) + #expect(RelativePath("ab//cd//ef").pathString == (windows ? #"ab\cd\ef"# : "ab/cd/ef")) + #expect(RelativePath("ab//cd///ef").pathString == (windows ? #"ab\cd\ef"# : "ab/cd/ef")) } - func testTrailingPathSeparators() { - XCTAssertEqual(AbsolutePath("/ab/cd/ef/").pathString, windows ? #"\ab\cd\ef"# : "/ab/cd/ef") - XCTAssertEqual(AbsolutePath("/ab/cd/ef//").pathString, windows ? #"\ab\cd\ef"# : "/ab/cd/ef") - XCTAssertEqual(RelativePath("ab/cd/ef/").pathString, windows ? #"ab\cd\ef"# : "ab/cd/ef") - XCTAssertEqual(RelativePath("ab/cd/ef//").pathString, windows ? #"ab\cd\ef"# : "ab/cd/ef") + @Test + func trailingPathSeparators() { + #expect(AbsolutePath("/ab/cd/ef/").pathString == (windows ? #"\ab\cd\ef"# : "/ab/cd/ef")) + #expect(AbsolutePath("/ab/cd/ef//").pathString == (windows ? #"\ab\cd\ef"# : "/ab/cd/ef")) + #expect(RelativePath("ab/cd/ef/").pathString == (windows ? #"ab\cd\ef"# : "ab/cd/ef")) + #expect(RelativePath("ab/cd/ef//").pathString == (windows ? #"ab\cd\ef"# : "ab/cd/ef")) } - func testDotPathComponents() { - XCTAssertEqual(AbsolutePath("/ab/././cd//ef").pathString, "/ab/cd/ef") - XCTAssertEqual(AbsolutePath("/ab/./cd//ef/.").pathString, "/ab/cd/ef") - XCTAssertEqual(RelativePath("ab/./cd/././ef").pathString, "ab/cd/ef") - XCTAssertEqual(RelativePath("ab/./cd/ef/.").pathString, "ab/cd/ef") + @Test + func dotPathComponents() { + #expect(AbsolutePath("/ab/././cd//ef").pathString == "/ab/cd/ef") + #expect(AbsolutePath("/ab/./cd//ef/.").pathString == "/ab/cd/ef") + #expect(RelativePath("ab/./cd/././ef").pathString == "ab/cd/ef") + #expect(RelativePath("ab/./cd/ef/.").pathString == "ab/cd/ef") } - func testDotDotPathComponents() { - XCTAssertEqual(AbsolutePath("/..").pathString, windows ? #"\"# : "/") - XCTAssertEqual(AbsolutePath("/../../../../..").pathString, windows ? #"\"# : "/") - XCTAssertEqual(AbsolutePath("/abc/..").pathString, windows ? #"\"# : "/") - XCTAssertEqual(AbsolutePath("/abc/../..").pathString, windows ? #"\"# : "/") - XCTAssertEqual(AbsolutePath("/../abc").pathString, windows ? #"\abc"# : "/abc") - XCTAssertEqual(AbsolutePath("/../abc/..").pathString, windows ? #"\"# : "/") - XCTAssertEqual(AbsolutePath("/../abc/../def").pathString, windows ? #"\def"# : "/def") - XCTAssertEqual(RelativePath("..").pathString, "..") - XCTAssertEqual(RelativePath("../..").pathString, "../..") - XCTAssertEqual(RelativePath(".././..").pathString, "../..") - XCTAssertEqual(RelativePath("../abc/..").pathString, "..") - XCTAssertEqual(RelativePath("../abc/.././").pathString, "..") - XCTAssertEqual(RelativePath("abc/..").pathString, ".") + @Test + func dotDotPathComponents() { + #expect(AbsolutePath("/..").pathString == (windows ? #"\"# : "/")) + #expect(AbsolutePath("/../../../../..").pathString == (windows ? #"\"# : "/")) + #expect(AbsolutePath("/abc/..").pathString == (windows ? #"\"# : "/")) + #expect(AbsolutePath("/abc/../..").pathString == (windows ? #"\"# : "/")) + #expect(AbsolutePath("/../abc").pathString == (windows ? #"\abc"# : "/abc")) + #expect(AbsolutePath("/../abc/..").pathString == (windows ? #"\"# : "/")) + #expect(AbsolutePath("/../abc/../def").pathString == (windows ? #"\def"# : "/def")) + #expect(RelativePath("..").pathString == "..") + #expect(RelativePath("../..").pathString == "../..") + #expect(RelativePath(".././..").pathString == "../..") + #expect(RelativePath("../abc/..").pathString == "..") + #expect(RelativePath("../abc/.././").pathString == "..") + #expect(RelativePath("abc/..").pathString == ".") } - func testCombinationsAndEdgeCases() { - XCTAssertEqual(AbsolutePath("///").pathString, windows ? #"\"# : "/") - XCTAssertEqual(AbsolutePath("/./").pathString, windows ? #"\"# : "/") - XCTAssertEqual(RelativePath("").pathString, ".") - XCTAssertEqual(RelativePath(".").pathString, ".") - XCTAssertEqual(RelativePath("./abc").pathString, "abc") - XCTAssertEqual(RelativePath("./abc/").pathString, "abc") - XCTAssertEqual(RelativePath("./abc/../bar").pathString, "bar") - XCTAssertEqual(RelativePath("foo/../bar").pathString, "bar") - XCTAssertEqual(RelativePath("foo///..///bar///baz").pathString, "bar/baz") - XCTAssertEqual(RelativePath("foo/../bar/./").pathString, "bar") - XCTAssertEqual(RelativePath("../abc/def/").pathString, "../abc/def") - XCTAssertEqual(RelativePath("././././.").pathString, ".") - XCTAssertEqual(RelativePath("./././../.").pathString, "..") - XCTAssertEqual(RelativePath("./").pathString, ".") - XCTAssertEqual(RelativePath(".//").pathString, ".") - XCTAssertEqual(RelativePath("./.").pathString, ".") - XCTAssertEqual(RelativePath("././").pathString, ".") - XCTAssertEqual(RelativePath("../").pathString, "..") - XCTAssertEqual(RelativePath("../.").pathString, "..") - XCTAssertEqual(RelativePath("./..").pathString, "..") - XCTAssertEqual(RelativePath("./../.").pathString, "..") - XCTAssertEqual(RelativePath("./////../////./////").pathString, "..") - XCTAssertEqual(RelativePath("../a").pathString, windows ? #"..\a"# : "../a") - XCTAssertEqual(RelativePath("../a/..").pathString, "..") - XCTAssertEqual(RelativePath("a/..").pathString, ".") - XCTAssertEqual(RelativePath("a/../////../////./////").pathString, "..") + @Test + func combinationsAndEdgeCases() { + #expect(AbsolutePath("///").pathString == (windows ? #"\"# : "/")) + #expect(AbsolutePath("/./").pathString == (windows ? #"\"# : "/")) + #expect(RelativePath("").pathString == ".") + #expect(RelativePath(".").pathString == ".") + #expect(RelativePath("./abc").pathString == "abc") + #expect(RelativePath("./abc/").pathString == "abc") + #expect(RelativePath("./abc/../bar").pathString == "bar") + #expect(RelativePath("foo/../bar").pathString == "bar") + #expect(RelativePath("foo///..///bar///baz").pathString == "bar/baz") + #expect(RelativePath("foo/../bar/./").pathString == "bar") + #expect(RelativePath("../abc/def/").pathString == "../abc/def") + #expect(RelativePath("././././.").pathString == ".") + #expect(RelativePath("./././../.").pathString == "..") + #expect(RelativePath("./").pathString == ".") + #expect(RelativePath(".//").pathString == ".") + #expect(RelativePath("./.").pathString == ".") + #expect(RelativePath("././").pathString == ".") + #expect(RelativePath("../").pathString == "..") + #expect(RelativePath("../.").pathString == "..") + #expect(RelativePath("./..").pathString == "..") + #expect(RelativePath("./../.").pathString == "..") + #expect(RelativePath("./////../////./////").pathString == "..") + #expect(RelativePath("../a").pathString == (windows ? #"..\a"# : "../a")) + #expect(RelativePath("../a/..").pathString == "..") + #expect(RelativePath("a/..").pathString == ".") + #expect(RelativePath("a/../////../////./////").pathString == "..") } - func testDirectoryNameExtraction() { - XCTAssertEqual(AbsolutePath("/").dirname, windows ? #"\"# : "/") - XCTAssertEqual(AbsolutePath("/a").dirname, windows ? #"\"# : "/") - XCTAssertEqual(AbsolutePath("/./a").dirname, windows ? #"\"# : "/") - XCTAssertEqual(AbsolutePath("/../..").dirname, windows ? #"\"# : "/") - XCTAssertEqual(AbsolutePath("/ab/c//d/").dirname, windows ? #"\ab\c"# : "/ab/c") - XCTAssertEqual(RelativePath("ab/c//d/").dirname, windows ? #"ab\c"# : "ab/c") - XCTAssertEqual(RelativePath("../a").dirname, "..") - XCTAssertEqual(RelativePath("../a/..").dirname, ".") - XCTAssertEqual(RelativePath("a/..").dirname, ".") - XCTAssertEqual(RelativePath("./..").dirname, ".") - XCTAssertEqual(RelativePath("a/../////../////./////").dirname, ".") - XCTAssertEqual(RelativePath("abc").dirname, ".") - XCTAssertEqual(RelativePath("").dirname, ".") - XCTAssertEqual(RelativePath(".").dirname, ".") + @Test + func directoryNameExtraction() { + #expect(AbsolutePath("/").dirname == (windows ? #"\"# : "/")) + #expect(AbsolutePath("/a").dirname == (windows ? #"\"# : "/")) + #expect(AbsolutePath("/./a").dirname == (windows ? #"\"# : "/")) + #expect(AbsolutePath("/../..").dirname == (windows ? #"\"# : "/")) + #expect(AbsolutePath("/ab/c//d/").dirname == (windows ? #"\ab\c"# : "/ab/c")) + #expect(RelativePath("ab/c//d/").dirname == (windows ? #"ab\c"# : "ab/c")) + #expect(RelativePath("../a").dirname == "..") + #expect(RelativePath("../a/..").dirname == ".") + #expect(RelativePath("a/..").dirname == ".") + #expect(RelativePath("./..").dirname == ".") + #expect(RelativePath("a/../////../////./////").dirname == ".") + #expect(RelativePath("abc").dirname == ".") + #expect(RelativePath("").dirname == ".") + #expect(RelativePath(".").dirname == ".") } - func testBaseNameExtraction() { - XCTAssertEqual(AbsolutePath("/").basename, windows ? #"\"# : "/") - XCTAssertEqual(AbsolutePath("/a").basename, "a") - XCTAssertEqual(AbsolutePath("/./a").basename, "a") - XCTAssertEqual(AbsolutePath("/../..").basename, "/") - XCTAssertEqual(RelativePath("../..").basename, "..") - XCTAssertEqual(RelativePath("../a").basename, "a") - XCTAssertEqual(RelativePath("../a/..").basename, "..") - XCTAssertEqual(RelativePath("a/..").basename, ".") - XCTAssertEqual(RelativePath("./..").basename, "..") - XCTAssertEqual(RelativePath("a/../////../////./////").basename, "..") - XCTAssertEqual(RelativePath("abc").basename, "abc") - XCTAssertEqual(RelativePath("").basename, ".") - XCTAssertEqual(RelativePath(".").basename, ".") + @Test + func baseNameExtraction() { + #expect(AbsolutePath("/").basename == (windows ? #"\"# : "/")) + #expect(AbsolutePath("/a").basename == "a") + #expect(AbsolutePath("/./a").basename == "a") + #expect(AbsolutePath("/../..").basename == "/") + #expect(RelativePath("../..").basename == "..") + #expect(RelativePath("../a").basename == "a") + #expect(RelativePath("../a/..").basename == "..") + #expect(RelativePath("a/..").basename == ".") + #expect(RelativePath("./..").basename == "..") + #expect(RelativePath("a/../////../////./////").basename == "..") + #expect(RelativePath("abc").basename == "abc") + #expect(RelativePath("").basename == ".") + #expect(RelativePath(".").basename == ".") } - func testBaseNameWithoutExt() { - XCTAssertEqual(AbsolutePath("/").basenameWithoutExt, windows ? #"\"# : "/") - XCTAssertEqual(AbsolutePath("/a").basenameWithoutExt, "a") - XCTAssertEqual(AbsolutePath("/./a").basenameWithoutExt, "a") - XCTAssertEqual(AbsolutePath("/../..").basenameWithoutExt, "/") - XCTAssertEqual(RelativePath("../..").basenameWithoutExt, "..") - XCTAssertEqual(RelativePath("../a").basenameWithoutExt, "a") - XCTAssertEqual(RelativePath("../a/..").basenameWithoutExt, "..") - XCTAssertEqual(RelativePath("a/..").basenameWithoutExt, ".") - XCTAssertEqual(RelativePath("./..").basenameWithoutExt, "..") - XCTAssertEqual(RelativePath("a/../////../////./////").basenameWithoutExt, "..") - XCTAssertEqual(RelativePath("abc").basenameWithoutExt, "abc") - XCTAssertEqual(RelativePath("").basenameWithoutExt, ".") - XCTAssertEqual(RelativePath(".").basenameWithoutExt, ".") - - XCTAssertEqual(AbsolutePath("/a.txt").basenameWithoutExt, "a") - XCTAssertEqual(AbsolutePath("/./a.txt").basenameWithoutExt, "a") - XCTAssertEqual(RelativePath("../a.bc").basenameWithoutExt, "a") - XCTAssertEqual(RelativePath("abc.swift").basenameWithoutExt, "abc") - XCTAssertEqual(RelativePath("../a.b.c").basenameWithoutExt, "a.b") - XCTAssertEqual(RelativePath("abc.xyz.123").basenameWithoutExt, "abc.xyz") + @Test + func baseNameWithoutExt() { + #expect(AbsolutePath("/").basenameWithoutExt == (windows ? #"\"# : "/")) + #expect(AbsolutePath("/a").basenameWithoutExt == "a") + #expect(AbsolutePath("/./a").basenameWithoutExt == "a") + #expect(AbsolutePath("/../..").basenameWithoutExt == "/") + #expect(RelativePath("../..").basenameWithoutExt == "..") + #expect(RelativePath("../a").basenameWithoutExt == "a") + #expect(RelativePath("../a/..").basenameWithoutExt == "..") + #expect(RelativePath("a/..").basenameWithoutExt == ".") + #expect(RelativePath("./..").basenameWithoutExt == "..") + #expect(RelativePath("a/../////../////./////").basenameWithoutExt == "..") + #expect(RelativePath("abc").basenameWithoutExt == "abc") + #expect(RelativePath("").basenameWithoutExt == ".") + #expect(RelativePath(".").basenameWithoutExt == ".") + + #expect(AbsolutePath("/a.txt").basenameWithoutExt == "a") + #expect(AbsolutePath("/./a.txt").basenameWithoutExt == "a") + #expect(RelativePath("../a.bc").basenameWithoutExt == "a") + #expect(RelativePath("abc.swift").basenameWithoutExt == "abc") + #expect(RelativePath("../a.b.c").basenameWithoutExt == "a.b") + #expect(RelativePath("abc.xyz.123").basenameWithoutExt == "abc.xyz") } - func testSuffixExtraction() { - XCTAssertEqual(RelativePath("a").suffix, nil) - XCTAssertEqual(RelativePath("a").extension, nil) - XCTAssertEqual(RelativePath("a.").suffix, nil) - XCTAssertEqual(RelativePath("a.").extension, nil) - XCTAssertEqual(RelativePath(".a").suffix, nil) - XCTAssertEqual(RelativePath(".a").extension, nil) - XCTAssertEqual(RelativePath("").suffix, nil) - XCTAssertEqual(RelativePath("").extension, nil) - XCTAssertEqual(RelativePath(".").suffix, nil) - XCTAssertEqual(RelativePath(".").extension, nil) - XCTAssertEqual(RelativePath("..").suffix, nil) - XCTAssertEqual(RelativePath("..").extension, nil) - XCTAssertEqual(RelativePath("a.foo").suffix, ".foo") - XCTAssertEqual(RelativePath("a.foo").extension, "foo") - XCTAssertEqual(RelativePath(".a.foo").suffix, ".foo") - XCTAssertEqual(RelativePath(".a.foo").extension, "foo") - XCTAssertEqual(RelativePath(".a.foo.bar").suffix, ".bar") - XCTAssertEqual(RelativePath(".a.foo.bar").extension, "bar") - XCTAssertEqual(RelativePath("a.foo.bar").suffix, ".bar") - XCTAssertEqual(RelativePath("a.foo.bar").extension, "bar") - XCTAssertEqual(RelativePath(".a.foo.bar.baz").suffix, ".baz") - XCTAssertEqual(RelativePath(".a.foo.bar.baz").extension, "baz") + @Test + func suffixExtraction() { + #expect(RelativePath("a").suffix == nil) + #expect(RelativePath("a").extension == nil) + #expect(RelativePath("a.").suffix == nil) + #expect(RelativePath("a.").extension == nil) + #expect(RelativePath(".a").suffix == nil) + #expect(RelativePath(".a").extension == nil) + #expect(RelativePath("").suffix == nil) + #expect(RelativePath("").extension == nil) + #expect(RelativePath(".").suffix == nil) + #expect(RelativePath(".").extension == nil) + #expect(RelativePath("..").suffix == nil) + #expect(RelativePath("..").extension == nil) + #expect(RelativePath("a.foo").suffix == ".foo") + #expect(RelativePath("a.foo").extension == "foo") + #expect(RelativePath(".a.foo").suffix == ".foo") + #expect(RelativePath(".a.foo").extension == "foo") + #expect(RelativePath(".a.foo.bar").suffix == ".bar") + #expect(RelativePath(".a.foo.bar").extension == "bar") + #expect(RelativePath("a.foo.bar").suffix == ".bar") + #expect(RelativePath("a.foo.bar").extension == "bar") + #expect(RelativePath(".a.foo.bar.baz").suffix == ".baz") + #expect(RelativePath(".a.foo.bar.baz").extension == "baz") } - func testParentDirectory() { - XCTAssertEqual(AbsolutePath("/").parentDirectory, AbsolutePath("/")) - XCTAssertEqual(AbsolutePath("/").parentDirectory.parentDirectory, AbsolutePath("/")) - XCTAssertEqual(AbsolutePath("/bar").parentDirectory, AbsolutePath("/")) - XCTAssertEqual(AbsolutePath("/bar/../foo/..//").parentDirectory.parentDirectory, AbsolutePath("/")) - XCTAssertEqual(AbsolutePath("/bar/../foo/..//yabba/a/b").parentDirectory.parentDirectory, AbsolutePath("/yabba")) + @Test + func parentDirectory() { + #expect(AbsolutePath("/").parentDirectory == AbsolutePath("/")) + #expect(AbsolutePath("/").parentDirectory.parentDirectory == AbsolutePath("/")) + #expect(AbsolutePath("/bar").parentDirectory == AbsolutePath("/")) + #expect(AbsolutePath("/bar/../foo/..//").parentDirectory.parentDirectory == AbsolutePath("/")) + #expect(AbsolutePath("/bar/../foo/..//yabba/a/b").parentDirectory.parentDirectory == AbsolutePath("/yabba")) } + @Test @available(*, deprecated) - func testConcatenation() { - XCTAssertEqual(AbsolutePath(AbsolutePath("/"), RelativePath("")).pathString, windows ? #"\"# : "/") - XCTAssertEqual(AbsolutePath(AbsolutePath("/"), RelativePath(".")).pathString, windows ? #"\"# : "/") - XCTAssertEqual(AbsolutePath(AbsolutePath("/"), RelativePath("..")).pathString, windows ? #"\"# : "/") - XCTAssertEqual(AbsolutePath(AbsolutePath("/"), RelativePath("bar")).pathString, windows ? #"\bar"# : "/bar") - XCTAssertEqual(AbsolutePath(AbsolutePath("/foo/bar"), RelativePath("..")).pathString, windows ? #"\foo"# : "/foo") - XCTAssertEqual(AbsolutePath(AbsolutePath("/bar"), RelativePath("../foo")).pathString, windows ? #"\foo"# : "/foo") - XCTAssertEqual(AbsolutePath(AbsolutePath("/bar"), RelativePath("../foo/..//")).pathString, windows ? #"\"# : "/") - XCTAssertEqual(AbsolutePath(AbsolutePath("/bar/../foo/..//yabba/"), RelativePath("a/b")).pathString, windows ? #"\yabba\a\b"# : "/yabba/a/b") - - XCTAssertEqual(AbsolutePath("/").appending(RelativePath("")).pathString, windows ? #"\"# : "/") - XCTAssertEqual(AbsolutePath("/").appending(RelativePath(".")).pathString, windows ? #"\"# : "/") - XCTAssertEqual(AbsolutePath("/").appending(RelativePath("..")).pathString, windows ? #"\"# : "/") - XCTAssertEqual(AbsolutePath("/").appending(RelativePath("bar")).pathString, windows ? #"\bar"# : "/bar") - XCTAssertEqual(AbsolutePath("/foo/bar").appending(RelativePath("..")).pathString, windows ? #"\foo"# : "/foo") - XCTAssertEqual(AbsolutePath("/bar").appending(RelativePath("../foo")).pathString, windows ? #"\foo"# : "/foo") - XCTAssertEqual(AbsolutePath("/bar").appending(RelativePath("../foo/..//")).pathString, windows ? #"\"# : "/") - XCTAssertEqual(AbsolutePath("/bar/../foo/..//yabba/").appending(RelativePath("a/b")).pathString, windows ? #"\yabba\a\b"# : "/yabba/a/b") - - XCTAssertEqual(AbsolutePath("/").appending(component: "a").pathString, windows ? #"\a"# : "/a") - XCTAssertEqual(AbsolutePath("/a").appending(component: "b").pathString, windows ? #"\a\b"# : "/a/b") - XCTAssertEqual(AbsolutePath("/").appending(components: "a", "b").pathString, windows ? #"\a\b"# : "/a/b") - XCTAssertEqual(AbsolutePath("/a").appending(components: "b", "c").pathString, windows ? #"\a\b\c"# : "/a/b/c") - - XCTAssertEqual(AbsolutePath("/a/b/c").appending(components: "", "c").pathString, windows ? #"\a\b\c\c"# : "/a/b/c/c") - XCTAssertEqual(AbsolutePath("/a/b/c").appending(components: "").pathString, windows ? #"\a\b\c"# : "/a/b/c") - XCTAssertEqual(AbsolutePath("/a/b/c").appending(components: ".").pathString, windows ? #"\a\b\c"# : "/a/b/c") - XCTAssertEqual(AbsolutePath("/a/b/c").appending(components: "..").pathString, windows ? #"\a\b"# : "/a/b") - XCTAssertEqual(AbsolutePath("/a/b/c").appending(components: "..", "d").pathString, windows ? #"\a\b\d"# : "/a/b/d") - XCTAssertEqual(AbsolutePath("/").appending(components: "..").pathString, windows ? #"\"# : "/") - XCTAssertEqual(AbsolutePath("/").appending(components: ".").pathString, windows ? #"\"# : "/") - XCTAssertEqual(AbsolutePath("/").appending(components: "..", "a").pathString, windows ? #"\a"# : "/a") - - XCTAssertEqual(RelativePath("hello").appending(components: "a", "b", "c", "..").pathString, windows ? #"hello\a\b"# : "hello/a/b") - XCTAssertEqual(RelativePath("hello").appending(RelativePath("a/b/../c/d")).pathString, windows ? #"hello\a\c\d"# : "hello/a/c/d") + func concatenation() { + #expect(AbsolutePath(AbsolutePath("/"), RelativePath("")).pathString == (windows ? #"\"# : "/")) + #expect(AbsolutePath(AbsolutePath("/"), RelativePath(".")).pathString == (windows ? #"\"# : "/")) + #expect(AbsolutePath(AbsolutePath("/"), RelativePath("..")).pathString == (windows ? #"\"# : "/")) + #expect(AbsolutePath(AbsolutePath("/"), RelativePath("bar")).pathString == (windows ? #"\bar"# : "/bar")) + #expect(AbsolutePath(AbsolutePath("/foo/bar"), RelativePath("..")).pathString == (windows ? #"\foo"# : "/foo")) + #expect(AbsolutePath(AbsolutePath("/bar"), RelativePath("../foo")).pathString == (windows ? #"\foo"# : "/foo")) + #expect(AbsolutePath(AbsolutePath("/bar"), RelativePath("../foo/..//")).pathString == (windows ? #"\"# : "/")) + #expect(AbsolutePath(AbsolutePath("/bar/../foo/..//yabba/"), RelativePath("a/b")).pathString == (windows ? #"\yabba\a\b"# : "/yabba/a/b")) + + #expect(AbsolutePath("/").appending(RelativePath("")).pathString == (windows ? #"\"# : "/")) + #expect(AbsolutePath("/").appending(RelativePath(".")).pathString == (windows ? #"\"# : "/")) + #expect(AbsolutePath("/").appending(RelativePath("..")).pathString == (windows ? #"\"# : "/")) + #expect(AbsolutePath("/").appending(RelativePath("bar")).pathString == (windows ? #"\bar"# : "/bar")) + #expect(AbsolutePath("/foo/bar").appending(RelativePath("..")).pathString == (windows ? #"\foo"# : "/foo")) + #expect(AbsolutePath("/bar").appending(RelativePath("../foo")).pathString == (windows ? #"\foo"# : "/foo")) + #expect(AbsolutePath("/bar").appending(RelativePath("../foo/..//")).pathString == (windows ? #"\"# : "/")) + #expect(AbsolutePath("/bar/../foo/..//yabba/").appending(RelativePath("a/b")).pathString == (windows ? #"\yabba\a\b"# : "/yabba/a/b")) + + #expect(AbsolutePath("/").appending(component: "a").pathString == (windows ? #"\a"# : "/a")) + #expect(AbsolutePath("/a").appending(component: "b").pathString == (windows ? #"\a\b"# : "/a/b")) + #expect(AbsolutePath("/").appending(components: "a", "b").pathString == (windows ? #"\a\b"# : "/a/b")) + #expect(AbsolutePath("/a").appending(components: "b", "c").pathString == (windows ? #"\a\b\c"# : "/a/b/c")) + + #expect(AbsolutePath("/a/b/c").appending(components: "", "c").pathString == (windows ? #"\a\b\c\c"# : "/a/b/c/c")) + #expect(AbsolutePath("/a/b/c").appending(components: "").pathString == (windows ? #"\a\b\c"# : "/a/b/c")) + #expect(AbsolutePath("/a/b/c").appending(components: ".").pathString == (windows ? #"\a\b\c"# : "/a/b/c")) + #expect(AbsolutePath("/a/b/c").appending(components: "..").pathString == (windows ? #"\a\b"# : "/a/b")) + #expect(AbsolutePath("/a/b/c").appending(components: "..", "d").pathString == (windows ? #"\a\b\d"# : "/a/b/d")) + #expect(AbsolutePath("/").appending(components: "..").pathString == (windows ? #"\"# : "/")) + #expect(AbsolutePath("/").appending(components: ".").pathString == (windows ? #"\"# : "/")) + #expect(AbsolutePath("/").appending(components: "..", "a").pathString == (windows ? #"\a"# : "/a")) + + #expect(RelativePath("hello").appending(components: "a", "b", "c", "..").pathString == (windows ? #"hello\a\b"# : "hello/a/b")) + #expect(RelativePath("hello").appending(RelativePath("a/b/../c/d")).pathString == (windows ? #"hello\a\c\d"# : "hello/a/c/d")) } - func testPathComponents() { - XCTAssertEqual(AbsolutePath("/").components, ["/"]) - XCTAssertEqual(AbsolutePath("/.").components, ["/"]) - XCTAssertEqual(AbsolutePath("/..").components, ["/"]) - XCTAssertEqual(AbsolutePath("/bar").components, ["/", "bar"]) - XCTAssertEqual(AbsolutePath("/foo/bar/..").components, ["/", "foo"]) - XCTAssertEqual(AbsolutePath("/bar/../foo").components, ["/", "foo"]) - XCTAssertEqual(AbsolutePath("/bar/../foo/..//").components, ["/"]) - XCTAssertEqual(AbsolutePath("/bar/../foo/..//yabba/a/b/").components, ["/", "yabba", "a", "b"]) - - XCTAssertEqual(RelativePath("").components, ["."]) - XCTAssertEqual(RelativePath(".").components, ["."]) - XCTAssertEqual(RelativePath("..").components, [".."]) - XCTAssertEqual(RelativePath("bar").components, ["bar"]) - XCTAssertEqual(RelativePath("foo/bar/..").components, ["foo"]) - XCTAssertEqual(RelativePath("bar/../foo").components, ["foo"]) - XCTAssertEqual(RelativePath("bar/../foo/..//").components, ["."]) - XCTAssertEqual(RelativePath("bar/../foo/..//yabba/a/b/").components, ["yabba", "a", "b"]) - XCTAssertEqual(RelativePath("../..").components, ["..", ".."]) - XCTAssertEqual(RelativePath(".././/..").components, ["..", ".."]) - XCTAssertEqual(RelativePath("../a").components, ["..", "a"]) - XCTAssertEqual(RelativePath("../a/..").components, [".."]) - XCTAssertEqual(RelativePath("a/..").components, ["."]) - XCTAssertEqual(RelativePath("./..").components, [".."]) - XCTAssertEqual(RelativePath("a/../////../////./////").components, [".."]) - XCTAssertEqual(RelativePath("abc").components, ["abc"]) + @Test + func pathComponents() { + #expect(AbsolutePath("/").components == ["/"]) + #expect(AbsolutePath("/.").components == ["/"]) + #expect(AbsolutePath("/..").components == ["/"]) + #expect(AbsolutePath("/bar").components == ["/", "bar"]) + #expect(AbsolutePath("/foo/bar/..").components == ["/", "foo"]) + #expect(AbsolutePath("/bar/../foo").components == ["/", "foo"]) + #expect(AbsolutePath("/bar/../foo/..//").components == ["/"]) + #expect(AbsolutePath("/bar/../foo/..//yabba/a/b/").components == ["/", "yabba", "a", "b"]) + + #expect(RelativePath("").components == ["."]) + #expect(RelativePath(".").components == ["."]) + #expect(RelativePath("..").components == [".."]) + #expect(RelativePath("bar").components == ["bar"]) + #expect(RelativePath("foo/bar/..").components == ["foo"]) + #expect(RelativePath("bar/../foo").components == ["foo"]) + #expect(RelativePath("bar/../foo/..//").components == ["."]) + #expect(RelativePath("bar/../foo/..//yabba/a/b/").components == ["yabba", "a", "b"]) + #expect(RelativePath("../..").components == ["..", ".."]) + #expect(RelativePath(".././/..").components == ["..", ".."]) + #expect(RelativePath("../a").components == ["..", "a"]) + #expect(RelativePath("../a/..").components == [".."]) + #expect(RelativePath("a/..").components == ["."]) + #expect(RelativePath("./..").components == [".."]) + #expect(RelativePath("a/../////../////./////").components == [".."]) + #expect(RelativePath("abc").components == ["abc"]) } - func testRelativePathFromAbsolutePaths() { - XCTAssertEqual(AbsolutePath("/").relative(to: AbsolutePath("/")), RelativePath(".")); - XCTAssertEqual(AbsolutePath("/a/b/c/d").relative(to: AbsolutePath("/")), RelativePath("a/b/c/d")); - XCTAssertEqual(AbsolutePath("/").relative(to: AbsolutePath("/a/b/c")), RelativePath("../../..")); - XCTAssertEqual(AbsolutePath("/a/b/c/d").relative(to: AbsolutePath("/a/b")), RelativePath("c/d")); - XCTAssertEqual(AbsolutePath("/a/b/c/d").relative(to: AbsolutePath("/a/b/c")), RelativePath("d")); - XCTAssertEqual(AbsolutePath("/a/b/c/d").relative(to: AbsolutePath("/a/c/d")), RelativePath("../../b/c/d")); - XCTAssertEqual(AbsolutePath("/a/b/c/d").relative(to: AbsolutePath("/b/c/d")), RelativePath("../../../a/b/c/d")); + @Test + func relativePathFromAbsolutePaths() { + #expect(AbsolutePath("/").relative(to: AbsolutePath("/")) == RelativePath(".")); + #expect(AbsolutePath("/a/b/c/d").relative(to: AbsolutePath("/")) == RelativePath("a/b/c/d")); + #expect(AbsolutePath("/").relative(to: AbsolutePath("/a/b/c")) == RelativePath("../../..")); + #expect(AbsolutePath("/a/b/c/d").relative(to: AbsolutePath("/a/b")) == RelativePath("c/d")); + #expect(AbsolutePath("/a/b/c/d").relative(to: AbsolutePath("/a/b/c")) == RelativePath("d")); + #expect(AbsolutePath("/a/b/c/d").relative(to: AbsolutePath("/a/c/d")) == RelativePath("../../b/c/d")); + #expect(AbsolutePath("/a/b/c/d").relative(to: AbsolutePath("/b/c/d")) == RelativePath("../../../a/b/c/d")); } - func testComparison() { - XCTAssertTrue(AbsolutePath("/") <= AbsolutePath("/")); - XCTAssertTrue(AbsolutePath("/abc") < AbsolutePath("/def")); - XCTAssertTrue(AbsolutePath("/2") <= AbsolutePath("/2.1")); - XCTAssertTrue(AbsolutePath("/3.1") > AbsolutePath("/2")); - XCTAssertTrue(AbsolutePath("/2") >= AbsolutePath("/2")); - XCTAssertTrue(AbsolutePath("/2.1") >= AbsolutePath("/2")); + @Test + func comparison() { + #expect(AbsolutePath("/") <= AbsolutePath("/")); + #expect(AbsolutePath("/abc") < AbsolutePath("/def")); + #expect(AbsolutePath("/2") <= AbsolutePath("/2.1")); + #expect(AbsolutePath("/3.1") > AbsolutePath("/2")); + #expect(AbsolutePath("/2") >= AbsolutePath("/2")); + #expect(AbsolutePath("/2.1") >= AbsolutePath("/2")); } - func testAncestry() { - XCTAssertTrue(AbsolutePath("/a/b/c/d/e/f").isDescendantOfOrEqual(to: AbsolutePath("/a/b/c/d"))) - XCTAssertTrue(AbsolutePath("/a/b/c/d/e/f.swift").isDescendantOfOrEqual(to: AbsolutePath("/a/b/c"))) - XCTAssertTrue(AbsolutePath("/").isDescendantOfOrEqual(to: AbsolutePath("/"))) - XCTAssertTrue(AbsolutePath("/foo/bar").isDescendantOfOrEqual(to: AbsolutePath("/"))) - XCTAssertFalse(AbsolutePath("/foo/bar").isDescendantOfOrEqual(to: AbsolutePath("/foo/bar/baz"))) - XCTAssertFalse(AbsolutePath("/foo/bar").isDescendantOfOrEqual(to: AbsolutePath("/bar"))) - - XCTAssertFalse(AbsolutePath("/foo/bar").isDescendant(of: AbsolutePath("/foo/bar"))) - XCTAssertTrue(AbsolutePath("/foo/bar").isDescendant(of: AbsolutePath("/foo"))) - - XCTAssertTrue(AbsolutePath("/a/b/c/d").isAncestorOfOrEqual(to: AbsolutePath("/a/b/c/d/e/f"))) - XCTAssertTrue(AbsolutePath("/a/b/c").isAncestorOfOrEqual(to: AbsolutePath("/a/b/c/d/e/f.swift"))) - XCTAssertTrue(AbsolutePath("/").isAncestorOfOrEqual(to: AbsolutePath("/"))) - XCTAssertTrue(AbsolutePath("/").isAncestorOfOrEqual(to: AbsolutePath("/foo/bar"))) - XCTAssertFalse(AbsolutePath("/foo/bar/baz").isAncestorOfOrEqual(to: AbsolutePath("/foo/bar"))) - XCTAssertFalse(AbsolutePath("/bar").isAncestorOfOrEqual(to: AbsolutePath("/foo/bar"))) - - XCTAssertFalse(AbsolutePath("/foo/bar").isAncestor(of: AbsolutePath("/foo/bar"))) - XCTAssertTrue(AbsolutePath("/foo").isAncestor(of: AbsolutePath("/foo/bar"))) + @Test + func ancestry() { + #expect(AbsolutePath("/a/b/c/d/e/f").isDescendantOfOrEqual(to: AbsolutePath("/a/b/c/d"))) + #expect(AbsolutePath("/a/b/c/d/e/f.swift").isDescendantOfOrEqual(to: AbsolutePath("/a/b/c"))) + #expect(AbsolutePath("/").isDescendantOfOrEqual(to: AbsolutePath("/"))) + #expect(AbsolutePath("/foo/bar").isDescendantOfOrEqual(to: AbsolutePath("/"))) + #expect(!AbsolutePath("/foo/bar").isDescendantOfOrEqual(to: AbsolutePath("/foo/bar/baz"))) + #expect(!AbsolutePath("/foo/bar").isDescendantOfOrEqual(to: AbsolutePath("/bar"))) + + #expect(!AbsolutePath("/foo/bar").isDescendant(of: AbsolutePath("/foo/bar"))) + #expect(AbsolutePath("/foo/bar").isDescendant(of: AbsolutePath("/foo"))) + + #expect(AbsolutePath("/a/b/c/d").isAncestorOfOrEqual(to: AbsolutePath("/a/b/c/d/e/f"))) + #expect(AbsolutePath("/a/b/c").isAncestorOfOrEqual(to: AbsolutePath("/a/b/c/d/e/f.swift"))) + #expect(AbsolutePath("/").isAncestorOfOrEqual(to: AbsolutePath("/"))) + #expect(AbsolutePath("/").isAncestorOfOrEqual(to: AbsolutePath("/foo/bar"))) + #expect(!AbsolutePath("/foo/bar/baz").isAncestorOfOrEqual(to: AbsolutePath("/foo/bar"))) + #expect(!AbsolutePath("/bar").isAncestorOfOrEqual(to: AbsolutePath("/foo/bar"))) + + #expect(!AbsolutePath("/foo/bar").isAncestor(of: AbsolutePath("/foo/bar"))) + #expect(AbsolutePath("/foo").isAncestor(of: AbsolutePath("/foo/bar"))) } - func testAbsolutePathValidation() { - XCTAssertNoThrow(try AbsolutePath(validating: "/a/b/c/d")) + @Test + func absolutePathValidation() { + #expect(throws: Never.self) { + try AbsolutePath(validating: "/a/b/c/d") + } - XCTAssertThrowsError(try AbsolutePath(validating: "~/a/b/d")) { error in - XCTAssertEqual("\(error)", "invalid absolute path '~/a/b/d'; absolute path must begin with '/'") + #expect {try AbsolutePath(validating: "~/a/b/d")} throws: { error in + ("\(error)" == "invalid absolute path '~/a/b/d'; absolute path must begin with '/'") } - XCTAssertThrowsError(try AbsolutePath(validating: "a/b/d")) { error in - XCTAssertEqual("\(error)", "invalid absolute path 'a/b/d'") + #expect {try AbsolutePath(validating: "a/b/d") } throws: { error in + ("\(error)" == "invalid absolute path 'a/b/d'") } } - func testRelativePathValidation() { - XCTAssertNoThrow(try RelativePath(validating: "a/b/c/d")) + @Test + func relativePathValidation() { + #expect(throws: Never.self) { + try RelativePath(validating: "a/b/c/d") + } - XCTAssertThrowsError(try RelativePath(validating: "/a/b/d")) { error in - XCTAssertEqual("\(error)", "invalid relative path '/a/b/d'; relative path should not begin with '/'") + #expect {try RelativePath(validating: "/a/b/d")} throws: { error in + ("\(error)" == "invalid relative path '/a/b/d'; relative path should not begin with '/'") //XCTAssertEqual("\(error)", "invalid relative path '/a/b/d'; relative path should not begin with '/' or '~'") } - /*XCTAssertThrowsError(try RelativePath(validating: "~/a/b/d")) { error in - XCTAssertEqual("\(error)", "invalid relative path '~/a/b/d'; relative path should not begin with '/' or '~'") - }*/ } - func testCodable() throws { + @Test + func codable() throws { struct Foo: Codable, Equatable { var path: AbsolutePath } @@ -358,48 +380,56 @@ class PathTests: XCTestCase { let foo = Foo(path: "/path/to/foo") let data = try JSONEncoder().encode(foo) let decodedFoo = try JSONDecoder().decode(Foo.self, from: data) - XCTAssertEqual(foo, decodedFoo) + #expect(foo == decodedFoo) } do { let foo = Foo(path: "/path/to/../to/foo") let data = try JSONEncoder().encode(foo) let decodedFoo = try JSONDecoder().decode(Foo.self, from: data) - XCTAssertEqual(foo, decodedFoo) - XCTAssertEqual(foo.path.pathString, windows ? #"\path\to\foo"# : "/path/to/foo") - XCTAssertEqual(decodedFoo.path.pathString, windows ? #"\path\to\foo"# : "/path/to/foo") + #expect(foo == decodedFoo) + #expect(foo.path.pathString == (windows ? #"\path\to\foo"# : "/path/to/foo")) + #expect(decodedFoo.path.pathString == (windows ? #"\path\to\foo"# : "/path/to/foo")) } do { let bar = Bar(path: "path/to/bar") let data = try JSONEncoder().encode(bar) let decodedBar = try JSONDecoder().decode(Bar.self, from: data) - XCTAssertEqual(bar, decodedBar) + #expect(bar == decodedBar) } do { let bar = Bar(path: "path/to/../to/bar") let data = try JSONEncoder().encode(bar) let decodedBar = try JSONDecoder().decode(Bar.self, from: data) - XCTAssertEqual(bar, decodedBar) - XCTAssertEqual(bar.path.pathString, "path/to/bar") - XCTAssertEqual(decodedBar.path.pathString, "path/to/bar") + #expect(bar == decodedBar) + #expect(bar.path.pathString == "path/to/bar") + #expect(decodedBar.path.pathString == "path/to/bar") } do { let data = try JSONEncoder().encode(Baz(path: "")) - XCTAssertThrowsError(try JSONDecoder().decode(Foo.self, from: data)) - XCTAssertNoThrow(try JSONDecoder().decode(Bar.self, from: data)) // empty string is a valid relative path + #expect(throws: (any Error).self) { + try JSONDecoder().decode(Foo.self, from: data) + } + #expect(throws: Never.self) { + try JSONDecoder().decode(Bar.self, from: data) + } // empty string is a valid relative path } do { let data = try JSONEncoder().encode(Baz(path: "foo")) - XCTAssertThrowsError(try JSONDecoder().decode(Foo.self, from: data)) + #expect(throws: (any Error).self) { + try JSONDecoder().decode(Foo.self, from: data) + } } do { let data = try JSONEncoder().encode(Baz(path: "/foo")) - XCTAssertThrowsError(try JSONDecoder().decode(Bar.self, from: data)) + #expect(throws: (any Error).self) { + try JSONDecoder().decode(Bar.self, from: data) + } } } diff --git a/Tests/BasicsTests/FileSystem/TemporaryFileTests.swift b/Tests/BasicsTests/FileSystem/TemporaryFileTests.swift index 5460faf901d..cb5b80206f8 100644 --- a/Tests/BasicsTests/FileSystem/TemporaryFileTests.swift +++ b/Tests/BasicsTests/FileSystem/TemporaryFileTests.swift @@ -9,83 +9,84 @@ // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// +import Foundation -import XCTest +import Testing import Basics -class TemporaryAsyncFileTests: XCTestCase { - func testBasicTemporaryDirectory() async throws { - // Test can create and remove temp directory. +struct TemporaryAsyncFileTests { + @Test + func basicTemporaryDirectory() async throws { let path1: AbsolutePath = try await withTemporaryDirectory(removeTreeOnDeinit: true) { tempDirPath in // Do some async task try await Task.sleep(nanoseconds: 1_000) - - XCTAssertTrue(localFileSystem.isDirectory(tempDirPath)) + + #expect(localFileSystem.isDirectory(tempDirPath)) return tempDirPath }.value - XCTAssertFalse(localFileSystem.isDirectory(path1)) - + #expect(!localFileSystem.isDirectory(path1)) + // Test temp directory is not removed when its not empty. let path2: AbsolutePath = try await withTemporaryDirectory { tempDirPath in - XCTAssertTrue(localFileSystem.isDirectory(tempDirPath)) + #expect(localFileSystem.isDirectory(tempDirPath)) // Create a file inside the temp directory. let filePath = tempDirPath.appending("somefile") // Do some async task try await Task.sleep(nanoseconds: 1_000) - + try localFileSystem.writeFileContents(filePath, bytes: []) return tempDirPath }.value - XCTAssertTrue(localFileSystem.isDirectory(path2)) + #expect(localFileSystem.isDirectory(path2)) // Cleanup. try localFileSystem.removeFileTree(path2) - XCTAssertFalse(localFileSystem.isDirectory(path2)) - + #expect(!localFileSystem.isDirectory(path2)) + // Test temp directory is removed when its not empty and removeTreeOnDeinit is enabled. let path3: AbsolutePath = try await withTemporaryDirectory(removeTreeOnDeinit: true) { tempDirPath in - XCTAssertTrue(localFileSystem.isDirectory(tempDirPath)) + #expect(localFileSystem.isDirectory(tempDirPath)) let filePath = tempDirPath.appending("somefile") // Do some async task try await Task.sleep(nanoseconds: 1_000) - + try localFileSystem.writeFileContents(filePath, bytes: []) return tempDirPath }.value - XCTAssertFalse(localFileSystem.isDirectory(path3)) + #expect(!localFileSystem.isDirectory(path3)) } - - func testCanCreateUniqueTempDirectories() async throws { + + @Test + func canCreateUniqueTempDirectories() async throws { let (pathOne, pathTwo): (AbsolutePath, AbsolutePath) = try await withTemporaryDirectory(removeTreeOnDeinit: true) { pathOne in let pathTwo: AbsolutePath = try await withTemporaryDirectory(removeTreeOnDeinit: true) { pathTwo in // Do some async task try await Task.sleep(nanoseconds: 1_000) - - XCTAssertTrue(localFileSystem.isDirectory(pathOne)) - XCTAssertTrue(localFileSystem.isDirectory(pathTwo)) + + #expect(localFileSystem.isDirectory(pathOne)) + #expect(localFileSystem.isDirectory(pathTwo)) // Their paths should be different. - XCTAssertTrue(pathOne != pathTwo) + #expect(pathOne != pathTwo) return pathTwo }.value return (pathOne, pathTwo) }.value - XCTAssertFalse(localFileSystem.isDirectory(pathOne)) - XCTAssertFalse(localFileSystem.isDirectory(pathTwo)) + #expect(!localFileSystem.isDirectory(pathOne)) + #expect(!localFileSystem.isDirectory(pathTwo)) } - - func testCancelOfTask() async throws { + + @Test + func cancelOfTask() async throws { let task: Task = try withTemporaryDirectory { path in - + try await Task.sleep(nanoseconds: 1_000_000_000) - XCTAssertTrue(Task.isCancelled) - XCTAssertFalse(localFileSystem.isDirectory(path)) + #expect(Task.isCancelled) + #expect(!localFileSystem.isDirectory(path)) return path } task.cancel() - do { - // The correct path is to throw an error here - let _ = try await task.value - XCTFail("The correct path here is to throw an error") - } catch {} + await #expect(throws: (any Error).self, "Error did not error when accessing `task.value`") { + try await task.value + } } } diff --git a/Tests/BasicsTests/FileSystem/VFSTests.swift b/Tests/BasicsTests/FileSystem/VFSTests.swift index 83b8513fa69..3d7bec951b4 100644 --- a/Tests/BasicsTests/FileSystem/VFSTests.swift +++ b/Tests/BasicsTests/FileSystem/VFSTests.swift @@ -9,10 +9,11 @@ // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// +import Foundation import Basics import func TSCBasic.withTemporaryFile -import XCTest +import Testing import struct TSCBasic.ByteString @@ -34,19 +35,19 @@ func testWithTemporaryDirectory( }.value } -class VFSTests: XCTestCase { - func testLocalBasics() throws { - // tiny PE binary from: https://archive.is/w01DO +struct VFSTests { + @Test + func localBasics() throws { let contents: [UInt8] = [ - 0x4d, 0x5a, 0x00, 0x00, 0x50, 0x45, 0x00, 0x00, 0x4c, 0x01, 0x01, 0x00, - 0x6a, 0x2a, 0x58, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x03, 0x01, 0x0b, 0x01, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x68, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02 + 0x4d, 0x5a, 0x00, 0x00, 0x50, 0x45, 0x00, 0x00, 0x4c, 0x01, 0x01, 0x00, + 0x6a, 0x2a, 0x58, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x03, 0x01, 0x0b, 0x01, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x68, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02 ] let fs = localFileSystem @@ -76,63 +77,65 @@ class VFSTests: XCTestCase { let vfs = try VirtualFileSystem(path: vfsPath.path, fs: fs) // exists() - XCTAssertTrue(vfs.exists(AbsolutePath("/"))) - XCTAssertFalse(vfs.exists(AbsolutePath("/does-not-exist"))) + #expect(vfs.exists(AbsolutePath("/"))) + #expect(!vfs.exists(AbsolutePath("/does-not-exist"))) // isFile() let filePath = AbsolutePath("/best") - XCTAssertTrue(vfs.exists(filePath)) - XCTAssertTrue(vfs.isFile(filePath)) - XCTAssertEqual(try vfs.getFileInfo(filePath).fileType, .typeRegular) - XCTAssertFalse(vfs.isDirectory(filePath)) - XCTAssertFalse(vfs.isFile(AbsolutePath("/does-not-exist"))) - XCTAssertFalse(vfs.isSymlink(AbsolutePath("/does-not-exist"))) - XCTAssertThrowsError(try vfs.getFileInfo(AbsolutePath("/does-not-exist"))) + #expect(vfs.exists(filePath)) + #expect(vfs.isFile(filePath)) + #expect(try vfs.getFileInfo(filePath).fileType == .typeRegular) + #expect(!vfs.isDirectory(filePath)) + #expect(!vfs.isFile(AbsolutePath("/does-not-exist"))) + #expect(!vfs.isSymlink(AbsolutePath("/does-not-exist"))) + #expect(throws: (any Error).self) { + try vfs.getFileInfo(AbsolutePath("/does-not-exist")) + } // isSymlink() let symPath = AbsolutePath("/hello") - XCTAssertTrue(vfs.isSymlink(symPath)) - XCTAssertTrue(vfs.isFile(symPath)) - XCTAssertEqual(try vfs.getFileInfo(symPath).fileType, .typeSymbolicLink) - XCTAssertFalse(vfs.isDirectory(symPath)) + #expect(vfs.isSymlink(symPath)) + #expect(vfs.isFile(symPath)) + #expect(try vfs.getFileInfo(symPath).fileType == .typeSymbolicLink) + #expect(!vfs.isDirectory(symPath)) // isExecutableFile let executablePath = AbsolutePath("/exec-foo") let executableSymPath = AbsolutePath("/exec-sym") - XCTAssertTrue(vfs.isExecutableFile(executablePath)) - XCTAssertTrue(vfs.isExecutableFile(executableSymPath)) - XCTAssertTrue(vfs.isSymlink(executableSymPath)) - XCTAssertFalse(vfs.isExecutableFile(symPath)) - XCTAssertFalse(vfs.isExecutableFile(filePath)) - XCTAssertFalse(vfs.isExecutableFile(AbsolutePath("/does-not-exist"))) - XCTAssertFalse(vfs.isExecutableFile(AbsolutePath("/"))) + #expect(vfs.isExecutableFile(executablePath)) + #expect(vfs.isExecutableFile(executableSymPath)) + #expect(vfs.isSymlink(executableSymPath)) + #expect(!vfs.isExecutableFile(symPath)) + #expect(!vfs.isExecutableFile(filePath)) + #expect(!vfs.isExecutableFile(AbsolutePath("/does-not-exist"))) + #expect(!vfs.isExecutableFile(AbsolutePath("/"))) // readFileContents let execFileContents = try vfs.readFileContents(executablePath) - XCTAssertEqual(execFileContents, ByteString(contents)) + #expect(execFileContents == ByteString(contents)) // isDirectory() - XCTAssertTrue(vfs.isDirectory(AbsolutePath("/"))) - XCTAssertFalse(vfs.isDirectory(AbsolutePath("/does-not-exist"))) + #expect(vfs.isDirectory(AbsolutePath("/"))) + #expect(!vfs.isDirectory(AbsolutePath("/does-not-exist"))) // getDirectoryContents() - do { - _ = try vfs.getDirectoryContents(AbsolutePath("/does-not-exist")) - XCTFail("Unexpected success") - } catch { - XCTAssertEqual(error.localizedDescription, "no such file or directory: \(AbsolutePath("/does-not-exist"))") + let dirContents = try vfs.getDirectoryContents(AbsolutePath("/")) + #expect(dirContents == ["exec-sym", "best", "exec-foo", "dir", "hello"]) + #expect {try vfs.getDirectoryContents(AbsolutePath("/does-not-exist"))} throws: { error in + (error.localizedDescription == "no such file or directory: \(AbsolutePath("/does-not-exist"))") } + let thisDirectoryContents = try vfs.getDirectoryContents(AbsolutePath("/")) - XCTAssertFalse(thisDirectoryContents.contains(where: { $0 == "." })) - XCTAssertFalse(thisDirectoryContents.contains(where: { $0 == ".." })) - XCTAssertEqual(thisDirectoryContents.sorted(), ["best", "dir", "exec-foo", "exec-sym", "hello"]) + #expect(!thisDirectoryContents.contains(where: { $0 == "." })) + #expect(!thisDirectoryContents.contains(where: { $0 == ".." })) + #expect(thisDirectoryContents.sorted() == ["best", "dir", "exec-foo", "exec-sym", "hello"]) let contents = try vfs.getDirectoryContents(AbsolutePath("/dir")) - XCTAssertEqual(contents, ["file"]) + #expect(contents == ["file"]) let fileContents = try vfs.readFileContents(AbsolutePath("/dir/file")) - XCTAssertEqual(fileContents, "") + #expect(fileContents == "") } } } diff --git a/Tests/BasicsTests/Graph/AdjacencyMatrixTests.swift b/Tests/BasicsTests/Graph/AdjacencyMatrixTests.swift index c19178ef410..376bc09d3d9 100644 --- a/Tests/BasicsTests/Graph/AdjacencyMatrixTests.swift +++ b/Tests/BasicsTests/Graph/AdjacencyMatrixTests.swift @@ -9,30 +9,33 @@ // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// +import Foundation @testable import Basics -import XCTest +import Testing -final class AdjacencyMatrixTests: XCTestCase { - func testEmpty() { +struct AdjacencyMatrixTests { + @Test + func empty() { var matrix = AdjacencyMatrix(rows: 0, columns: 0) - XCTAssertEqual(matrix.bitCount, 0) + #expect(matrix.bitCount == 0) matrix = AdjacencyMatrix(rows: 0, columns: 42) - XCTAssertEqual(matrix.bitCount, 0) + #expect(matrix.bitCount == 0) matrix = AdjacencyMatrix(rows: 42, columns: 0) - XCTAssertEqual(matrix.bitCount, 0) + #expect(matrix.bitCount == 0) } - func testBits() { + @Test + func bits() { for count in 1..<10 { var matrix = AdjacencyMatrix(rows: count, columns: count) for row in 0..() let maxAttempts = 5 @@ -236,7 +246,7 @@ final class HTTPClientTests: XCTestCase { let count = await counter.value! let expectedDelta = pow(2.0, Double(count - 1)) * delay.timeInterval()! let delta = await lastCall.value.flatMap { Date().timeIntervalSince($0) } ?? 0 - XCTAssertEqual(delta, expectedDelta, accuracy: 0.1) + #expect(delta.isApproximatelyEqual(to: expectedDelta, absoluteTolerance: 0.1)) await counter.increment() await lastCall.resetDate() @@ -246,12 +256,13 @@ final class HTTPClientTests: XCTestCase { request.options.retryStrategy = .exponentialBackoff(maxAttempts: maxAttempts, baseDelay: delay) let response = try await httpClient.execute(request) - XCTAssertEqual(response.statusCode, errorCode) + #expect(response.statusCode == errorCode) let count = await counter.value - XCTAssertEqual(count, maxAttempts, "retries should match") + #expect(count == maxAttempts, "retries should match") } - func testHostCircuitBreaker() async throws { + @Test + func hostCircuitBreaker() async throws { let maxErrors = 5 let errorCode = Int.random(in: 500 ..< 600) let age = SendableTimeInterval.seconds(5) @@ -268,31 +279,29 @@ final class HTTPClientTests: XCTestCase { for index in (0 ..< maxErrors) { let response = try await httpClient.get(URL("\(host)/\(index)/foo")) await counter.increment() - XCTAssertEqual(response.statusCode, errorCode) + #expect(response.statusCode == errorCode) } let count = await counter.value - XCTAssertEqual(count, maxErrors, "expected results count to match") + #expect(count == maxErrors, "expected results count to match") } // these should all circuit break let counter = SendableBox(0) let total = Int.random(in: 10 ..< 20) for index in (0 ..< total) { - do { - let response = try await httpClient.get(URL("\(host)/\(index)/foo")) - XCTFail("unexpected success \(response)") - } catch { - XCTAssertEqual(error as? HTTPClientError, .circuitBreakerTriggered, "expected error to match") + await #expect(throws: HTTPClientError.circuitBreakerTriggered) { + let _ = try await httpClient.get(URL("\(host)/\(index)/foo")) } await counter.increment() } let count = await counter.value - XCTAssertEqual(count, total, "expected results count to match") + #expect(count == total, "expected results count to match") } - func testHostCircuitBreakerAging() async throws { + @Test + func hostCircuitBreakerAging() async throws { let maxErrors = 5 let errorCode = Int.random(in: 500 ..< 600) let ageInMilliseconds = 100 @@ -320,10 +329,10 @@ final class HTTPClientTests: XCTestCase { for index in (0 ..< maxErrors) { let response = try await httpClient.get(URL("\(host)/\(index)/error")) await counter.increment() - XCTAssertEqual(response.statusCode, errorCode) + #expect(response.statusCode == errorCode) } let count = await counter.value - XCTAssertEqual(count, maxErrors, "expected results count to match") + #expect(count == maxErrors, "expected results count to match") } // these should not circuit break since they are deliberately aged @@ -336,49 +345,51 @@ final class HTTPClientTests: XCTestCase { try await Task.sleep(nanoseconds: UInt64(sleepInterval.nanoseconds()!)) let response = try await httpClient.get("\(host)/\(index)/okay") count.increment() - XCTAssertEqual(response.statusCode, 200, "expected status code to match") + #expect(response.statusCode == 200, "expected status code to match") } - XCTAssertEqual(count.get(), total, "expected results count to match") + #expect(count.get() == total, "expected status code to match") } - func testHTTPClientHeaders() async throws { + @Test + func hTTPClientHeaders() async throws { var headers = HTTPClientHeaders() let items = (1 ... Int.random(in: 10 ... 20)).map { index in HTTPClientHeaders.Item(name: "header-\(index)", value: UUID().uuidString) } headers.add(items) - XCTAssertEqual(headers.count, items.count, "headers count should match") + #expect(headers.count == items.count, "headers count should match") items.forEach { item in - XCTAssertEqual(headers.get(item.name).first, item.value, "headers value should match") + #expect(headers.get(item.name).first == item.value, "headers value should match") } headers.add(items.first!) - XCTAssertEqual(headers.count, items.count, "headers count should match (no duplicates)") + #expect(headers.count == items.count, "headers count should match (no duplicates)") let name = UUID().uuidString let values = (1 ... Int.random(in: 10 ... 20)).map { "value-\($0)" } values.forEach { value in headers.add(name: name, value: value) } - XCTAssertEqual(headers.count, items.count + 1, "headers count should match (no duplicates)") - XCTAssertEqual(values, headers.get(name), "multiple headers value should match") + #expect(headers.count == items.count + 1, "headers count should match (no duplicates)") + #expect(values == headers.get(name), "multiple headers value should match") } - func testExceedsDownloadSizeLimitProgress() async throws { + @Test + func exceedsDownloadSizeLimitProgress() async throws { let maxSize: Int64 = 50 let httpClient = HTTPClient { request, progress in switch request.method { - case .head: - return .init( - statusCode: 200, - headers: .init([.init(name: "Content-Length", value: "0")]) - ) - case .get: - try progress?(Int64(maxSize * 2), 0) - default: - XCTFail("method should match") + case .head: + return .init( + statusCode: 200, + headers: .init([.init(name: "Content-Length", value: "0")]) + ) + case .get: + try progress?(Int64(maxSize * 2), 0) + default: + Issue.record("method should match. Received: \(request.method)") } fatalError("unreachable") @@ -387,15 +398,13 @@ final class HTTPClientTests: XCTestCase { var request = HTTPClient.Request(url: "http://test") request.options.maximumResponseSizeInBytes = 10 - do { - let response = try await httpClient.execute(request) - XCTFail("unexpected success \(response)") - } catch { - XCTAssertEqual(error as? HTTPClientError, .responseTooLarge(maxSize * 2), "expected error to match") + await #expect(throws: HTTPClientError.responseTooLarge(maxSize * 2)) { + let _ = try await httpClient.execute(request) } } - func testMaxConcurrency() async throws { + @Test + func maxConcurrency() async throws { let maxConcurrentRequests = 2 let concurrentRequests = SendableBox(0) @@ -405,7 +414,7 @@ final class HTTPClientTests: XCTestCase { await concurrentRequests.increment() if await concurrentRequests.value! > maxConcurrentRequests { - XCTFail("too many concurrent requests \(concurrentRequests), expected \(maxConcurrentRequests)") + Issue.record("too many concurrent requests \(concurrentRequests), expected \(maxConcurrentRequests)") } await concurrentRequests.decrement() @@ -426,10 +435,10 @@ final class HTTPClientTests: XCTestCase { results.append(result) } - XCTAssertEqual(results.count, total, "expected number of results to match") + #expect(results.count == total, "expected number of results to match") for result in results { - XCTAssertEqual(result.statusCode, 200, "expected '200 okay' response") + #expect(result.statusCode == 200, "expected '200 okay' response") } } } @@ -437,9 +446,9 @@ final class HTTPClientTests: XCTestCase { private func assertRequestHeaders(_ headers: HTTPClientHeaders, expected: HTTPClientHeaders) { let noAgent = HTTPClientHeaders(headers.filter { $0.name != "User-Agent" }) - XCTAssertEqual(noAgent, expected, "expected headers to match") + #expect(noAgent == expected, "expected headers to match") } private func assertResponseHeaders(_ headers: HTTPClientHeaders, expected: HTTPClientHeaders) { - XCTAssertEqual(headers, expected, "expected headers to match") + #expect(headers == expected, "expected headers to match") } diff --git a/Tests/BasicsTests/NetrcTests.swift b/Tests/BasicsTests/NetrcTests.swift index d9cde729ce2..6b2db3e43f0 100644 --- a/Tests/BasicsTests/NetrcTests.swift +++ b/Tests/BasicsTests/NetrcTests.swift @@ -11,30 +11,32 @@ //===----------------------------------------------------------------------===// import Basics -import XCTest +import Testing -class NetrcTests: XCTestCase { +struct NetrcTests { /// should load machines for a given inline format - func testLoadMachinesInline() throws { + @Test + func loadMachinesInline() throws { let content = "machine example.com login anonymous password qwerty" let netrc = try NetrcParser.parse(content) - XCTAssertEqual(netrc.machines.count, 1) + #expect(netrc.machines.count == 1) let machine = netrc.machines.first - XCTAssertEqual(machine?.name, "example.com") - XCTAssertEqual(machine?.login, "anonymous") - XCTAssertEqual(machine?.password, "qwerty") + #expect(machine?.name == "example.com") + #expect(machine?.login == "anonymous") + #expect(machine?.password == "qwerty") let authorization = netrc.authorization(for: "http://example.com/resource.zip") - XCTAssertEqual(authorization, Netrc.Authorization(login: "anonymous", password: "qwerty")) + #expect(authorization == Netrc.Authorization(login: "anonymous", password: "qwerty")) - XCTAssertNil(netrc.authorization(for: "http://example2.com/resource.zip")) - XCTAssertNil(netrc.authorization(for: "http://www.example2.com/resource.zip")) + #expect(netrc.authorization(for: "http://example2.com/resource.zip") == nil) + #expect(netrc.authorization(for: "http://www.example2.com/resource.zip") == nil) } /// should load machines for a given multi-line format - func testLoadMachinesMultiLine() throws { + @Test + func loadMachinesMultiLine() throws { let content = """ machine example.com login anonymous @@ -42,22 +44,23 @@ class NetrcTests: XCTestCase { """ let netrc = try NetrcParser.parse(content) - XCTAssertEqual(netrc.machines.count, 1) + #expect(netrc.machines.count == 1) let machine = netrc.machines.first - XCTAssertEqual(machine?.name, "example.com") - XCTAssertEqual(machine?.login, "anonymous") - XCTAssertEqual(machine?.password, "qwerty") + #expect(machine?.name == "example.com") + #expect(machine?.login == "anonymous") + #expect(machine?.password == "qwerty") let authorization = netrc.authorization(for: "http://example.com/resource.zip") - XCTAssertEqual(authorization, Netrc.Authorization(login: "anonymous", password: "qwerty")) + #expect(authorization == Netrc.Authorization(login: "anonymous", password: "qwerty")) - XCTAssertNil(netrc.authorization(for: "http://example2.com/resource.zip")) - XCTAssertNil(netrc.authorization(for: "http://www.example2.com/resource.zip")) + #expect(netrc.authorization(for: "http://example2.com/resource.zip") == nil) + #expect(netrc.authorization(for: "http://www.example2.com/resource.zip") == nil) } /// Should fall back to default machine when not matching host - func testLoadDefaultMachine() throws { + @Test + func loadDefaultMachine() throws { let content = """ machine example.com login anonymous @@ -69,23 +72,24 @@ class NetrcTests: XCTestCase { """ let netrc = try NetrcParser.parse(content) - XCTAssertEqual(netrc.machines.count, 2) + #expect(netrc.machines.count == 2) let machine = netrc.machines.first - XCTAssertEqual(machine?.name, "example.com") - XCTAssertEqual(machine?.login, "anonymous") - XCTAssertEqual(machine?.password, "qwerty") + #expect(machine?.name == "example.com") + #expect(machine?.login == "anonymous") + #expect(machine?.password == "qwerty") let machine2 = netrc.machines.last - XCTAssertEqual(machine2?.name, "default") - XCTAssertEqual(machine2?.login, "id") - XCTAssertEqual(machine2?.password, "secret") + #expect(machine2?.name == "default") + #expect(machine2?.login == "id") + #expect(machine2?.password == "secret") let authorization = netrc.authorization(for: "http://example2.com/resource.zip") - XCTAssertEqual(authorization, Netrc.Authorization(login: "id", password: "secret")) + #expect(authorization == Netrc.Authorization(login: "id", password: "secret")) } - func testRegexParsing() throws { + @Test + func regexParsing() throws { let content = """ machine machine login login @@ -109,25 +113,26 @@ class NetrcTests: XCTestCase { """ let netrc = try NetrcParser.parse(content) - XCTAssertEqual(netrc.machines.count, 3) + #expect(netrc.machines.count == 3) - XCTAssertEqual(netrc.machines[0].name, "machine") - XCTAssertEqual(netrc.machines[0].login, "login") - XCTAssertEqual(netrc.machines[0].password, "password") + #expect(netrc.machines[0].name == "machine") + #expect(netrc.machines[0].login == "login") + #expect(netrc.machines[0].password == "password") - XCTAssertEqual(netrc.machines[1].name, "login") - XCTAssertEqual(netrc.machines[1].login, "password") - XCTAssertEqual(netrc.machines[1].password, "machine") + #expect(netrc.machines[1].name == "login") + #expect(netrc.machines[1].login == "password") + #expect(netrc.machines[1].password == "machine") - XCTAssertEqual(netrc.machines[2].name, "default") - XCTAssertEqual(netrc.machines[2].login, "id") - XCTAssertEqual(netrc.machines[2].password, "secret") + #expect(netrc.machines[2].name == "default") + #expect(netrc.machines[2].login == "id") + #expect(netrc.machines[2].password == "secret") let authorization = netrc.authorization(for: "http://example2.com/resource.zip") - XCTAssertEqual(authorization, Netrc.Authorization(login: "id", password: "secret")) + #expect(authorization == Netrc.Authorization(login: "id", password: "secret")) } - func testOutOfOrderDefault() { + @Test + func outOfOrderDefault() { let content = """ machine machine login login @@ -146,12 +151,13 @@ class NetrcTests: XCTestCase { password secret """ - XCTAssertThrowsError(try NetrcParser.parse(content)) { error in - XCTAssertEqual(error as? NetrcError, .invalidDefaultMachinePosition) + #expect(throws: NetrcError.invalidDefaultMachinePosition) { + try NetrcParser.parse(content) } } - func testErrorOnMultipleDefault() { + @Test + func errorOnMultipleDefault() { let content = """ machine machine login login @@ -174,13 +180,14 @@ class NetrcTests: XCTestCase { password terces """ - XCTAssertThrowsError(try NetrcParser.parse(content)) { error in - XCTAssertEqual(error as? NetrcError, .invalidDefaultMachinePosition) + #expect(throws: NetrcError.invalidDefaultMachinePosition) { + try NetrcParser.parse(content) } } /// should load machines for a given multi-line format with comments - func testLoadMachinesMultilineComments() throws { + @Test + func loadMachinesMultilineComments() throws { let content = """ ## This is a comment # This is another comment @@ -190,48 +197,51 @@ class NetrcTests: XCTestCase { """ let machines = try NetrcParser.parse(content).machines - XCTAssertEqual(machines.count, 1) + #expect(machines.count == 1) let machine = machines.first - XCTAssertEqual(machine?.name, "example.com") - XCTAssertEqual(machine?.login, "anonymous") - XCTAssertEqual(machine?.password, "qwerty") + #expect(machine?.name == "example.com") + #expect(machine?.login == "anonymous") + #expect(machine?.password == "qwerty") } /// should load machines for a given multi-line + whitespaces format - func testLoadMachinesMultilineWhitespaces() throws { + @Test + func loadMachinesMultilineWhitespaces() throws { let content = """ machine example.com login anonymous password qwerty """ let machines = try NetrcParser.parse(content).machines - XCTAssertEqual(machines.count, 1) + #expect(machines.count == 1) let machine = machines.first - XCTAssertEqual(machine?.name, "example.com") - XCTAssertEqual(machine?.login, "anonymous") - XCTAssertEqual(machine?.password, "qwerty") + #expect(machine?.name == "example.com") + #expect(machine?.login == "anonymous") + #expect(machine?.password == "qwerty") } /// should load multiple machines for a given inline format - func testLoadMultipleMachinesInline() throws { + @Test + func loadMultipleMachinesInline() throws { let content = "machine example.com login anonymous password qwerty machine example2.com login anonymous2 password qwerty2" let netrc = try NetrcParser.parse(content) - XCTAssertEqual(netrc.machines.count, 2) + #expect(netrc.machines.count == 2) - XCTAssertEqual(netrc.machines[0].name, "example.com") - XCTAssertEqual(netrc.machines[0].login, "anonymous") - XCTAssertEqual(netrc.machines[0].password, "qwerty") + #expect(netrc.machines[0].name == "example.com") + #expect(netrc.machines[0].login == "anonymous") + #expect(netrc.machines[0].password == "qwerty") - XCTAssertEqual(netrc.machines[1].name, "example2.com") - XCTAssertEqual(netrc.machines[1].login, "anonymous2") - XCTAssertEqual(netrc.machines[1].password, "qwerty2") + #expect(netrc.machines[1].name == "example2.com") + #expect(netrc.machines[1].login == "anonymous2") + #expect(netrc.machines[1].password == "qwerty2") } /// should load multiple machines for a given multi-line format - func testLoadMultipleMachinesMultiline() throws { + @Test + func loadMultipleMachinesMultiline() throws { let content = """ machine example.com login anonymous password qwerty @@ -241,90 +251,98 @@ class NetrcTests: XCTestCase { """ let machines = try NetrcParser.parse(content).machines - XCTAssertEqual(machines.count, 2) + #expect(machines.count == 2) var machine = machines[0] - XCTAssertEqual(machine.name, "example.com") - XCTAssertEqual(machine.login, "anonymous") - XCTAssertEqual(machine.password, "qwerty") + #expect(machine.name == "example.com") + #expect(machine.login == "anonymous") + #expect(machine.password == "qwerty") machine = machines[1] - XCTAssertEqual(machine.name, "example2.com") - XCTAssertEqual(machine.login, "anonymous2") - XCTAssertEqual(machine.password, "qwerty2") + #expect(machine.name == "example2.com") + #expect(machine.login == "anonymous2") + #expect(machine.password == "qwerty2") } /// should throw error when machine parameter is missing - func testErrorMachineParameterMissing() throws { + @Test + func errorMachineParameterMissing() throws { let content = "login anonymous password qwerty" - XCTAssertThrowsError(try NetrcParser.parse(content)) { error in - XCTAssertEqual(error as? NetrcError, .machineNotFound) + #expect(throws: NetrcError.machineNotFound) { + try NetrcParser.parse(content) } } /// should throw error for an empty machine values - func testErrorEmptyMachineValue() throws { + @Test + func errorEmptyMachineValue() throws { let content = "machine" - XCTAssertThrowsError(try NetrcParser.parse(content)) { error in - XCTAssertEqual(error as? NetrcError, .machineNotFound) + #expect(throws: NetrcError.machineNotFound) { + try NetrcParser.parse(content) } } /// should throw error for an empty machine values - func testEmptyMachineValueFollowedByDefaultNoError() throws { + @Test + func emptyMachineValueFollowedByDefaultNoError() throws { let content = "machine default login id password secret" let netrc = try NetrcParser.parse(content) let authorization = netrc.authorization(for: "http://example.com/resource.zip") - XCTAssertEqual(authorization, Netrc.Authorization(login: "id", password: "secret")) + #expect(authorization == Netrc.Authorization(login: "id", password: "secret")) } /// should return authorization when config contains a given machine - func testReturnAuthorizationForMachineMatch() throws { + @Test + func returnAuthorizationForMachineMatch() throws { let content = "machine example.com login anonymous password qwerty" let netrc = try NetrcParser.parse(content) let authorization = netrc.authorization(for: "http://example.com/resource.zip") - XCTAssertEqual(authorization, Netrc.Authorization(login: "anonymous", password: "qwerty")) + #expect(authorization == Netrc.Authorization(login: "anonymous", password: "qwerty")) } - func testReturnNoAuthorizationForUnmatched() throws { + @Test + func returnNoAuthorizationForUnmatched() throws { let content = "machine example.com login anonymous password qwerty" let netrc = try NetrcParser.parse(content) - XCTAssertNil(netrc.authorization(for: "http://www.example.com/resource.zip")) - XCTAssertNil(netrc.authorization(for: "ftp.example.com/resource.zip")) - XCTAssertNil(netrc.authorization(for: "http://example2.com/resource.zip")) - XCTAssertNil(netrc.authorization(for: "http://www.example2.com/resource.zip")) + #expect(netrc.authorization(for: "http://www.example.com/resource.zip") == nil) + #expect(netrc.authorization(for: "ftp.example.com/resource.zip") == nil) + #expect(netrc.authorization(for: "http://example2.com/resource.zip") == nil) + #expect(netrc.authorization(for: "http://www.example2.com/resource.zip") == nil) } /// should not return authorization when config does not contain a given machine - func testNoReturnAuthorizationForNoMachineMatch() throws { + @Test + func noReturnAuthorizationForNoMachineMatch() throws { let content = "machine example.com login anonymous password qwerty" let netrc = try NetrcParser.parse(content) - XCTAssertNil(netrc.authorization(for: "https://example99.com")) - XCTAssertNil(netrc.authorization(for: "http://www.example.com/resource.zip")) - XCTAssertNil(netrc.authorization(for: "ftp.example.com/resource.zip")) - XCTAssertNil(netrc.authorization(for: "http://example2.com/resource.zip")) - XCTAssertNil(netrc.authorization(for: "http://www.example2.com/resource.zip")) + #expect(netrc.authorization(for: "https://example99.com") == nil) + #expect(netrc.authorization(for: "http://www.example.com/resource.zip") == nil) + #expect(netrc.authorization(for: "ftp.example.com/resource.zip") == nil) + #expect(netrc.authorization(for: "http://example2.com/resource.zip") == nil) + #expect(netrc.authorization(for: "http://www.example2.com/resource.zip") == nil) } /// Test case: https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/filesreference/netrc.html - func testIBMDocumentation() throws { + @Test + func iBMDocumentation() throws { let content = "machine host1.austin.century.com login fred password bluebonnet" let netrc = try NetrcParser.parse(content) let machine = netrc.machines.first - XCTAssertEqual(machine?.name, "host1.austin.century.com") - XCTAssertEqual(machine?.login, "fred") - XCTAssertEqual(machine?.password, "bluebonnet") + #expect(machine?.name == "host1.austin.century.com") + #expect(machine?.login == "fred") + #expect(machine?.password == "bluebonnet") } /// Should not fail on presence of `account`, `macdef`, `default` /// test case: https://gist.github.com/tpope/4247721 - func testNoErrorTrailingAccountMacdefDefault() throws { + @Test + func noErrorTrailingAccountMacdefDefault() throws { let content = """ machine api.heroku.com login my@email.com @@ -341,28 +359,29 @@ class NetrcTests: XCTestCase { let netrc = try NetrcParser.parse(content) - XCTAssertEqual(netrc.machines.count, 4) + #expect(netrc.machines.count == 4) - XCTAssertEqual(netrc.machines[0].name, "api.heroku.com") - XCTAssertEqual(netrc.machines[0].login, "my@email.com") - XCTAssertEqual(netrc.machines[0].password, "01230123012301230123012301230123") + #expect(netrc.machines[0].name == "api.heroku.com") + #expect(netrc.machines[0].login == "my@email.com") + #expect(netrc.machines[0].password == "01230123012301230123012301230123") - XCTAssertEqual(netrc.machines[1].name, "api.github.com") - XCTAssertEqual(netrc.machines[1].login, "somebody") - XCTAssertEqual(netrc.machines[1].password, "something") + #expect(netrc.machines[1].name == "api.github.com") + #expect(netrc.machines[1].login == "somebody") + #expect(netrc.machines[1].password == "something") - XCTAssertEqual(netrc.machines[2].name, "ftp.server") - XCTAssertEqual(netrc.machines[2].login, "abc") - XCTAssertEqual(netrc.machines[2].password, "def") + #expect(netrc.machines[2].name == "ftp.server") + #expect(netrc.machines[2].login == "abc") + #expect(netrc.machines[2].password == "def") - XCTAssertEqual(netrc.machines[3].name, "default") - XCTAssertEqual(netrc.machines[3].login, "anonymous") - XCTAssertEqual(netrc.machines[3].password, "my@email.com") + #expect(netrc.machines[3].name == "default") + #expect(netrc.machines[3].login == "anonymous") + #expect(netrc.machines[3].password == "my@email.com") } /// Should not fail on presence of `account`, `macdef`, `default` /// test case: https://gist.github.com/tpope/4247721 - func testNoErrorMixedAccount() throws { + @Test + func noErrorMixedAccount() throws { let content = """ machine api.heroku.com login my@email.com @@ -379,28 +398,29 @@ class NetrcTests: XCTestCase { let netrc = try NetrcParser.parse(content) - XCTAssertEqual(netrc.machines.count, 4) + #expect(netrc.machines.count == 4) - XCTAssertEqual(netrc.machines[0].name, "api.heroku.com") - XCTAssertEqual(netrc.machines[0].login, "my@email.com") - XCTAssertEqual(netrc.machines[0].password, "01230123012301230123012301230123") + #expect(netrc.machines[0].name == "api.heroku.com") + #expect(netrc.machines[0].login == "my@email.com") + #expect(netrc.machines[0].password == "01230123012301230123012301230123") - XCTAssertEqual(netrc.machines[1].name, "api.github.com") - XCTAssertEqual(netrc.machines[1].login, "somebody") - XCTAssertEqual(netrc.machines[1].password, "something") + #expect(netrc.machines[1].name == "api.github.com") + #expect(netrc.machines[1].login == "somebody") + #expect(netrc.machines[1].password == "something") - XCTAssertEqual(netrc.machines[2].name, "ftp.server") - XCTAssertEqual(netrc.machines[2].login, "abc") - XCTAssertEqual(netrc.machines[2].password, "def") + #expect(netrc.machines[2].name == "ftp.server") + #expect(netrc.machines[2].login == "abc") + #expect(netrc.machines[2].password == "def") - XCTAssertEqual(netrc.machines[3].name, "default") - XCTAssertEqual(netrc.machines[3].login, "anonymous") - XCTAssertEqual(netrc.machines[3].password, "my@email.com") + #expect(netrc.machines[3].name == "default") + #expect(netrc.machines[3].login == "anonymous") + #expect(netrc.machines[3].password == "my@email.com") } /// Should not fail on presence of `account`, `macdef`, `default` /// test case: https://renenyffenegger.ch/notes/Linux/fhs/home/username/_netrc - func testNoErrorMultipleMacdefAndComments() throws { + @Test + func noErrorMultipleMacdefAndComments() throws { let content = """ machine ftp.foobar.baz login john @@ -421,15 +441,15 @@ class NetrcTests: XCTestCase { let netrc = try NetrcParser.parse(content) - XCTAssertEqual(netrc.machines.count, 2) + #expect(netrc.machines.count == 2) - XCTAssertEqual(netrc.machines[0].name, "ftp.foobar.baz") - XCTAssertEqual(netrc.machines[0].login, "john") - XCTAssertEqual(netrc.machines[0].password, "5ecr3t") + #expect(netrc.machines[0].name == "ftp.foobar.baz") + #expect(netrc.machines[0].login == "john") + #expect(netrc.machines[0].password == "5ecr3t") - XCTAssertEqual(netrc.machines[1].name, "other.server.org") - XCTAssertEqual(netrc.machines[1].login, "fred") - XCTAssertEqual(netrc.machines[1].password, "sunshine4ever") + #expect(netrc.machines[1].name == "other.server.org") + #expect(netrc.machines[1].login == "fred") + #expect(netrc.machines[1].password == "sunshine4ever") } } diff --git a/Tests/BasicsTests/ObservabilitySystemTests.swift b/Tests/BasicsTests/ObservabilitySystemTests.swift index 300c988f8bb..f8001848c64 100644 --- a/Tests/BasicsTests/ObservabilitySystemTests.swift +++ b/Tests/BasicsTests/ObservabilitySystemTests.swift @@ -9,16 +9,18 @@ // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// +import Foundation @testable import Basics import _InternalTestSupport -import XCTest +import Testing // TODO: remove when transition to new diagnostics system is complete typealias Diagnostic = Basics.Diagnostic -final class ObservabilitySystemTest: XCTestCase { - func testScopes() throws { +struct ObservabilitySystemTest { + @Test + func scopes() throws { let collector = Collector() let observabilitySystem = ObservabilitySystem(collector) @@ -35,14 +37,14 @@ final class ObservabilitySystemTest: XCTestCase { testDiagnostics(collector.diagnostics) { result in let diagnostic1 = result.check(diagnostic: "error 1", severity: .error) - XCTAssertEqual(diagnostic1?.metadata?.testKey1, metadata1.testKey1) - XCTAssertEqual(diagnostic1?.metadata?.testKey2, metadata1.testKey2) - XCTAssertEqual(diagnostic1?.metadata?.testKey3, metadata1.testKey3) + #expect(diagnostic1?.metadata?.testKey1 == metadata1.testKey1) + #expect(diagnostic1?.metadata?.testKey2 == metadata1.testKey2) + #expect(diagnostic1?.metadata?.testKey3 == metadata1.testKey3) let diagnostic1_5 = result.check(diagnostic: "error 1.5", severity: .error) - XCTAssertEqual(diagnostic1_5?.metadata?.testKey1, metadata1.testKey1) - XCTAssertEqual(diagnostic1_5?.metadata?.testKey2, metadata1.testKey2) - XCTAssertEqual(diagnostic1_5?.metadata?.testKey3, metadata1.testKey3) + #expect(diagnostic1_5?.metadata?.testKey1 == metadata1.testKey1) + #expect(diagnostic1_5?.metadata?.testKey2 == metadata1.testKey2) + #expect(diagnostic1_5?.metadata?.testKey3 == metadata1.testKey3) } collector.clear() @@ -52,9 +54,9 @@ final class ObservabilitySystemTest: XCTestCase { metadata2.testKey2 = Int.random(in: Int.min..