Skip to content

Commit c7673b6

Browse files
committed
Tests: Convert Basics/FileSystem/* to Swift Testing
Convert test from XCTest to Swift Testing. - Tests/BasicsTests/FileSystem/FileSystemTests.swift - Tests/BasicsTests/FileSystem/PathShimTests.swift - Tests/BasicsTests/FileSystem/PathTests.swift - Tests/BasicsTests/FileSystem/TemporaryFileTests.swift - Tests/BasicsTests/FileSystem/VFSTests.swift relates to: #8433
1 parent 79d64b3 commit c7673b6

File tree

7 files changed

+752
-459
lines changed

7 files changed

+752
-459
lines changed
+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
This source file is part of the Swift.org open source project
3+
4+
Copyright (c) 2014 - 2025 Apple Inc. and the Swift project authors
5+
Licensed under Apache License v2.0 with Runtime Library Exception
6+
7+
See http://swift.org/LICENSE.txt for license information
8+
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
9+
*/
10+
11+
public import Foundation
12+
13+
public enum OperatingSystem: Hashable, Sendable {
14+
case macOS
15+
case windows
16+
case linux
17+
case android
18+
case unknown
19+
}
20+
21+
extension ProcessInfo {
22+
#if os(macOS)
23+
public static let hostOperatingSystem = OperatingSystem.macOS
24+
#elseif os(Linux)
25+
public static let hostOperatingSystem = OperatingSystem.linux
26+
#elseif os(Windows)
27+
public static let hostOperatingSystem = OperatingSystem.windows
28+
#else
29+
public static let hostOperatingSystem = OperatingSystem.unknown
30+
#endif
31+
32+
#if os(Windows)
33+
public static let EOL = "\r\n"
34+
#else
35+
public static let EOL = "\n"
36+
#endif
37+
38+
#if os(Windows)
39+
public static let exeSuffix = ".exe"
40+
#else
41+
public static let exeSuffix = ""
42+
#endif
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
2+
/*
3+
This source file is part of the Swift.org open source project
4+
5+
Copyright (c) 2014 - 2025 Apple Inc. and the Swift project authors
6+
Licensed under Apache License v2.0 with Runtime Library Exception
7+
8+
See http://swift.org/LICENSE.txt for license information
9+
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
10+
*/
11+
12+
import class Foundation.FileManager
13+
import class Foundation.ProcessInfo
14+
import Testing
15+
16+
extension Trait where Self == Testing.ConditionTrait {
17+
/// Skip test if the host operating system does not match the running OS.
18+
public static func requireHostOS(_ os: OperatingSystem, when condition: Bool = true, sourceLocation: SourceLocation = #_sourceLocation) -> Self {
19+
enabled("This test requires a \(os) host OS.", sourceLocation: sourceLocation) {
20+
ProcessInfo.hostOperatingSystem == os && condition
21+
}
22+
}
23+
24+
/// Skip test if the host operating system matches the running OS.
25+
public static func skipHostOS(_ os: OperatingSystem, _ comment: Comment? = nil, sourceLocation: SourceLocation = #_sourceLocation) -> Self {
26+
disabled(comment ?? "This test cannot run on a \(os) host OS.", sourceLocation: sourceLocation) {
27+
ProcessInfo.hostOperatingSystem == os
28+
}
29+
}
30+
31+
/// Skip test unconditionally
32+
public static func skip(_ comment: Comment? = nil, sourceLocation: SourceLocation = #_sourceLocation) -> Self {
33+
disabled(comment ?? "Unconditional skip, a comment should be added for the reason", sourceLocation: sourceLocation) { true }
34+
}
35+
36+
/// Skip test if the environment is self hosted.
37+
public static func skipSwiftCISelfHosted(_ comment: Comment? = nil, sourceLocation: SourceLocation = #_sourceLocation) -> Self {
38+
disabled(comment ?? "SwiftCI is self hosted", sourceLocation: sourceLocation) {
39+
ProcessInfo.processInfo.environment["SWIFTCI_IS_SELF_HOSTED"] != nil
40+
}
41+
}
42+
43+
/// Skip test if the test environment has a restricted network access, i.e. cannot get to internet.
44+
public static func requireUnrestrictedNetworkAccess(_ comment: Comment? = nil, sourceLocation: SourceLocation = #_sourceLocation) -> Self {
45+
disabled(comment ?? "CI Environment has restricted network access", sourceLocation: sourceLocation) {
46+
ProcessInfo.processInfo.environment["SWIFTCI_RESTRICTED_NETWORK_ACCESS"] != nil
47+
}
48+
}
49+
50+
/// Skip test if built by XCode.
51+
public static func skipIfXcodeBuilt(sourceLocation: SourceLocation = #_sourceLocation) -> Self {
52+
disabled("Tests built by Xcode", sourceLocation: sourceLocation) {
53+
#if Xcode
54+
true
55+
#else
56+
false
57+
#endif
58+
}
59+
}
60+
61+
/// Constructs a condition trait that causes a test to be disabled if the Foundation process spawning implementation
62+
/// is not using `posix_spawn_file_actions_addchdir`.
63+
public static var requireThreadSafeWorkingDirectory: Self {
64+
disabled("Thread-safe process working directory support is unavailable.") {
65+
// Amazon Linux 2 has glibc 2.26, and glibc 2.29 is needed for posix_spawn_file_actions_addchdir_np support
66+
FileManager.default.contents(atPath: "/etc/system-release")
67+
.map { String(decoding: $0, as: UTF8.self) == "Amazon Linux release 2 (Karoo)\n" } ?? false
68+
}
69+
}
70+
}

Tests/BasicsTests/FileSystem/FileSystemTests.swift

+19-17
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@
99
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
1010
//
1111
//===----------------------------------------------------------------------===//
12-
1312
@testable import Basics
1413
import TSCTestSupport
15-
import XCTest
14+
import Testing
1615

17-
final class FileSystemTests: XCTestCase {
18-
func testStripFirstLevelComponent() throws {
16+
struct FileSystemTests {
17+
@Test
18+
func stripFirstLevelComponent() throws {
1919
let fileSystem = InMemoryFileSystem()
2020

2121
let rootPath = AbsolutePath("/root")
@@ -35,29 +35,31 @@ final class FileSystemTests: XCTestCase {
3535

3636
do {
3737
let contents = try fileSystem.getDirectoryContents(.root)
38-
XCTAssertEqual(contents.count, 1)
38+
#expect(contents.count == 1)
3939
}
4040

4141
try fileSystem.stripFirstLevel(of: .root)
4242

4343
do {
4444
let contents = Set(try fileSystem.getDirectoryContents(.root))
45-
XCTAssertEqual(contents.count, totalDirectories + totalFiles)
45+
#expect(contents.count == totalDirectories + totalFiles)
4646

4747
for index in 0 ..< totalDirectories {
48-
XCTAssertTrue(contents.contains("dir\(index)"))
48+
#expect(contents.contains("dir\(index)"))
4949
}
5050
for index in 0 ..< totalFiles {
51-
XCTAssertTrue(contents.contains("file\(index)"))
51+
#expect(contents.contains("file\(index)"))
5252
}
5353
}
5454
}
5555

56-
func testStripFirstLevelComponentErrors() throws {
56+
@Test
57+
func stripFirstLevelComponentErrors() throws {
58+
let functionUnderTest = "stripFirstLevel"
5759
do {
5860
let fileSystem = InMemoryFileSystem()
59-
XCTAssertThrowsError(try fileSystem.stripFirstLevel(of: .root), "expected error") { error in
60-
XCTAssertMatch((error as? StringError)?.description, .contains("requires single top level directory"))
61+
#expect(throws: StringError("\(functionUnderTest) requires single top level directory")) {
62+
try fileSystem.stripFirstLevel(of: .root)
6163
}
6264
}
6365

@@ -67,8 +69,8 @@ final class FileSystemTests: XCTestCase {
6769
let path = AbsolutePath.root.appending("dir\(index)")
6870
try fileSystem.createDirectory(path, recursive: false)
6971
}
70-
XCTAssertThrowsError(try fileSystem.stripFirstLevel(of: .root), "expected error") { error in
71-
XCTAssertMatch((error as? StringError)?.description, .contains("requires single top level directory"))
72+
#expect(throws: StringError("\(functionUnderTest) requires single top level directory")) {
73+
try fileSystem.stripFirstLevel(of: .root)
7274
}
7375
}
7476

@@ -78,17 +80,17 @@ final class FileSystemTests: XCTestCase {
7880
let path = AbsolutePath.root.appending("file\(index)")
7981
try fileSystem.writeFileContents(path, string: "\(index)")
8082
}
81-
XCTAssertThrowsError(try fileSystem.stripFirstLevel(of: .root), "expected error") { error in
82-
XCTAssertMatch((error as? StringError)?.description, .contains("requires single top level directory"))
83+
#expect(throws: StringError("\(functionUnderTest) requires single top level directory")) {
84+
try fileSystem.stripFirstLevel(of: .root)
8385
}
8486
}
8587

8688
do {
8789
let fileSystem = InMemoryFileSystem()
8890
let path = AbsolutePath.root.appending("file")
8991
try fileSystem.writeFileContents(path, string: "")
90-
XCTAssertThrowsError(try fileSystem.stripFirstLevel(of: .root), "expected error") { error in
91-
XCTAssertMatch((error as? StringError)?.description, .contains("requires single top level directory"))
92+
#expect(throws: StringError("\(functionUnderTest) requires single top level directory")) {
93+
try fileSystem.stripFirstLevel(of: .root)
9294
}
9395
}
9496
}

Tests/BasicsTests/FileSystem/PathShimTests.swift

+23-22
Original file line numberDiff line numberDiff line change
@@ -12,64 +12,65 @@
1212

1313
import Basics
1414
import Foundation
15-
import XCTest
15+
import Testing
1616

17-
class PathShimTests: XCTestCase {
18-
func testRescursiveDirectoryCreation() {
19-
// For the tests we'll need a temporary directory.
17+
struct PathShimTests {
18+
@Test
19+
func rescursiveDirectoryCreation() {
2020
try! withTemporaryDirectory(removeTreeOnDeinit: true) { path in
2121
// Create a directory under several ancestor directories.
2222
let dirPath = path.appending(components: "abc", "def", "ghi", "mno", "pqr")
2323
try! makeDirectories(dirPath)
2424

2525
// Check that we were able to actually create the directory.
26-
XCTAssertTrue(localFileSystem.isDirectory(dirPath))
26+
#expect(localFileSystem.isDirectory(dirPath))
2727

2828
// Check that there's no error if we try to create the directory again.
29-
try! makeDirectories(dirPath)
29+
#expect(throws: Never.self) {
30+
try! makeDirectories(dirPath)
31+
}
3032
}
3133
}
3234
}
3335

34-
class WalkTests: XCTestCase {
35-
func testNonRecursive() throws {
36-
#if os(Android)
36+
struct WalkTests {
37+
@Test
38+
func nonRecursive() throws {
39+
#if os(Android)
3740
let root = "/system"
3841
var expected: [AbsolutePath] = [
3942
"\(root)/usr",
4043
"\(root)/bin",
4144
"\(root)/etc",
4245
]
43-
#elseif os(Windows)
46+
let expectedCount = 3
47+
#elseif os(Windows)
4448
let root = ProcessInfo.processInfo.environment["SystemRoot"]!
4549
var expected: [AbsolutePath] = [
4650
"\(root)/System32",
4751
"\(root)/SysWOW64",
4852
]
49-
#else
53+
let expectedCount = (root as NSString).pathComponents.count + 2
54+
#else
5055
let root = ""
5156
var expected: [AbsolutePath] = [
5257
"/usr",
5358
"/bin",
5459
"/sbin",
5560
]
56-
#endif
61+
let expectedCount = 2
62+
#endif
5763
for x in try walk(AbsolutePath(validating: "\(root)/"), recursively: false) {
5864
if let i = expected.firstIndex(of: x) {
5965
expected.remove(at: i)
6066
}
61-
#if os(Android)
62-
XCTAssertEqual(3, x.components.count)
63-
#elseif os(Windows)
64-
XCTAssertEqual((root as NSString).pathComponents.count + 2, x.components.count)
65-
#else
66-
XCTAssertEqual(2, x.components.count)
67-
#endif
67+
#expect(x.components.count == expectedCount, "Actual is not as expected")
6868
}
69-
XCTAssertEqual(expected.count, 0)
69+
#expect(expected.count == 0)
7070
}
7171

72-
func testRecursive() {
72+
@Test
73+
func recursive() {
7374
let root = AbsolutePath(#file).parentDirectory.parentDirectory.parentDirectory.parentDirectory
7475
.appending(component: "Sources")
7576
var expected = [
@@ -82,6 +83,6 @@ class WalkTests: XCTestCase {
8283
expected.remove(at: i)
8384
}
8485
}
85-
XCTAssertEqual(expected, [])
86+
#expect(expected == [])
8687
}
8788
}

0 commit comments

Comments
 (0)