Skip to content

Commit 8744410

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

File tree

1 file changed

+135
-0
lines changed

1 file changed

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

0 commit comments

Comments
 (0)