Skip to content

Commit 17a0250

Browse files
committed
Add tests for SwiftHeaderToolTaskAction.
1 parent 17536f7 commit 17a0250

File tree

1 file changed

+136
-0
lines changed

1 file changed

+136
-0
lines changed
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift open source project
4+
//
5+
// Copyright (c) 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 the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import Testing
14+
import SWBUtil
15+
import SWBTestSupport
16+
import SWBTaskExecution
17+
18+
@Suite(.requireHostOS(.macOS)) // Core isn't working on Linux yet
19+
struct SwiftHeaderToolTaskActionTests: CoreBasedTests {
20+
21+
/// Utility function to create and run a `SwiftHeaderToolTaskAction` and call a block to check the results.
22+
private func testSwiftHeaderToolTaskAction(archs: [String], validate: (ByteString) -> Void) async throws {
23+
guard !archs.isEmpty else {
24+
Issue.record("Must pass at least one architecture.")
25+
return
26+
}
27+
28+
let fs = PseudoFS()
29+
30+
// Build the command line and write the input files.
31+
try fs.createDirectory(Path("/Volumes/Inputs"), recursive: true)
32+
try fs.createDirectory(Path("/Volumes/Outputs"), recursive: true)
33+
var commandLine = ["builtin-swiftHeaderTool"]
34+
if archs.count == 1 {
35+
commandLine.append("-single")
36+
}
37+
for arch in archs {
38+
let inputPath = Path("/Volumes/Inputs/\(arch)/GeneratedHeader-Swift.h")
39+
try await fs.writeFileContents(inputPath) { stream in
40+
stream <<< "Contents of file for \(arch)\n"
41+
}
42+
commandLine.append(contentsOf: [
43+
"-arch", arch,
44+
inputPath.str,
45+
])
46+
}
47+
let outputPath = Path("/Volumes/Outputs/GeneratedHeader-Swift.h")
48+
commandLine.append(contentsOf: [
49+
"-o", outputPath.str
50+
])
51+
52+
// Construct and run the task action.
53+
let executionDelegate = MockExecutionDelegate(fs: fs)
54+
let outputDelegate = MockTaskOutputDelegate()
55+
let action = SwiftHeaderToolTaskAction()
56+
let task = Task(forTarget: nil, ruleInfo: [], commandLine: commandLine, workingDirectory: .root, outputs: [], action: action, execDescription: "")
57+
guard let result = await task.action?.performTaskAction(task, dynamicExecutionDelegate: MockDynamicTaskExecutionDelegate(), executionDelegate: executionDelegate, clientDelegate: MockTaskExecutionClientDelegate(), outputDelegate: outputDelegate) else {
58+
Issue.record("No result was returned.")
59+
return
60+
}
61+
62+
// Check the command succeeded with no errors.
63+
#expect(result == .succeeded)
64+
#expect(outputDelegate.messages == [])
65+
66+
// Read the output file and pass it to the validation block.
67+
let outputFileContents = try fs.read(outputPath)
68+
validate(outputFileContents)
69+
}
70+
71+
/// Test that running the tool for a single arch just copies the file and doesn't add any `#if` blocks.
72+
@Test
73+
func testSingleArch() async throws {
74+
let archs = ["arm64"]
75+
try await testSwiftHeaderToolTaskAction(archs: archs) { outputFileContents in
76+
let expectedFileContents =
77+
"Contents of file for arm64\n"
78+
#expect(outputFileContents == expectedFileContents)
79+
}
80+
}
81+
82+
/// Basic test for two architectures.
83+
@Test
84+
func testTwoArchs() async throws {
85+
let archs = ["arm64", "x86_64"]
86+
try await testSwiftHeaderToolTaskAction(archs: archs) { outputFileContents in
87+
let expectedFileContents =
88+
"#if 0\n" +
89+
"#elif defined(__arm64__) && __arm64__\n" +
90+
"Contents of file for arm64\n\n" +
91+
"#elif defined(__x86_64__) && __x86_64__\n" +
92+
"Contents of file for x86_64\n\n" +
93+
"#else\n" +
94+
"#error unsupported Swift architecture\n" +
95+
"#endif\n"
96+
#expect(outputFileContents == expectedFileContents)
97+
}
98+
}
99+
100+
/// Test that when building for `arm64e` but not `arm64` that we guard the `arm64e` file contents by the fallback `arm64` macro.
101+
@Test
102+
func testFallbackArch() async throws {
103+
let archs = ["arm64e", "x86_64"]
104+
try await testSwiftHeaderToolTaskAction(archs: archs) { outputFileContents in
105+
let expectedFileContents =
106+
"#if 0\n" +
107+
"#elif defined(__arm64__) && __arm64__\n" +
108+
"Contents of file for arm64e\n\n" +
109+
"#elif defined(__x86_64__) && __x86_64__\n" +
110+
"Contents of file for x86_64\n\n" +
111+
"#else\n" +
112+
"#error unsupported Swift architecture\n" +
113+
"#endif\n"
114+
#expect(outputFileContents == expectedFileContents)
115+
}
116+
}
117+
118+
/// Test that when building for both `arm64e` and `arm64` that we end up with the content for both archs using both macros.
119+
@Test
120+
func testNoFallbackArch() async throws {
121+
let archs = ["arm64", "arm64e"]
122+
try await testSwiftHeaderToolTaskAction(archs: archs) { outputFileContents in
123+
let expectedFileContents =
124+
"#if 0\n" +
125+
"#elif defined(__arm64e__) && __arm64e__\n" +
126+
"Contents of file for arm64e\n\n" +
127+
"#elif defined(__arm64__) && __arm64__\n" +
128+
"Contents of file for arm64\n\n" +
129+
"#else\n" +
130+
"#error unsupported Swift architecture\n" +
131+
"#endif\n"
132+
#expect(outputFileContents == expectedFileContents)
133+
}
134+
}
135+
136+
}

0 commit comments

Comments
 (0)