Skip to content

Commit 8921b9a

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

File tree

1 file changed

+138
-0
lines changed

1 file changed

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

0 commit comments

Comments
 (0)