Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Sources/SWBTestSupport/SwiftTestingExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,14 @@ package import Testing
package func expectEqual<T: Equatable>(_ lhs: T, _ rhs: T, sourceLocation: SourceLocation = #_sourceLocation) {
#expect(lhs == rhs, sourceLocation: sourceLocation)
}


package extension Tag {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we leave this tagging scheme for future discussion? Our tests are already largely organized into modules by test type and small/medium/large doesn't really add any useful information on top of that

enum TestSize {}
}

package extension Tag.TestSize {
@Tag static var small: Tag
@Tag static var medium: Tag
@Tag static var large: Tag
}
2 changes: 1 addition & 1 deletion Sources/SWBUniversalPlatform/Specs/Clang.xcspec
Original file line number Diff line number Diff line change
Expand Up @@ -2896,7 +2896,7 @@
};
AdditionalLinkerArgs = {
YES = (
"-fsanitize=address",
"$(LD_ADDRESS_SANITIZER)",
);
NO = ();
};
Expand Down
39 changes: 39 additions & 0 deletions Sources/SWBUniversalPlatform/Specs/Ld.xcspec
Original file line number Diff line number Diff line change
Expand Up @@ -582,17 +582,37 @@
DefaultValue = YES;
},

// Address Sanitizer options
{
Name = LD_ADDRESS_SANITIZER;
DefaultValue = "$(LD_ADDRESS_SANITIZER_$(LINKER_DRIVER))";
},
{
Name = LD_ADDRESS_SANITIZER_clang;
DefaultValue = "-fsanitize=address";
},
{
Name = LD_ADDRESS_SANITIZER_swiftc;
DefaultValue = "-sanitize=address";
},

// Thread Sanitizer options
{
Name = "LD_THREAD_SANITIZER";
Type = Boolean;
DefaultValue = "$(ENABLE_THREAD_SANITIZER)";
},
{
Name = "CLANG_LD_THREAD_SANITIZER";
Type = Boolean;
DefaultValue = "$(LD_THREAD_SANITIZER)";
Architectures = (
x86_64,
x86_64h,
arm64,
arm64e,
);
Condition = "$(LINKER_DRIVER) == clang";
CommandLineArgs = {
YES = (
"-fsanitize=thread",
Expand All @@ -601,6 +621,25 @@
};
// Not visible in the build settings editor
},
{
Name = "SWIFTC_LD_THREAD_SANITIZER";
Type = Boolean;
DefaultValue = "$(LD_THREAD_SANITIZER)";
Architectures = (
x86_64,
x86_64h,
arm64,
arm64e,
);
Condition = "$(LINKER_DRIVER) == swiftc";
CommandLineArgs = {
YES = (
"-sanitize=thread",
);
NO = ();
};
// Not visible in the build settings editor
},

{
Name = "LD_DEBUG_VARIANT";
Expand Down
2 changes: 1 addition & 1 deletion Sources/SWBUniversalPlatform/Specs/Swift.xcspec
Original file line number Diff line number Diff line change
Expand Up @@ -1225,7 +1225,7 @@
};
AdditionalLinkerArgs = {
YES = (
"-fsanitize=address",
"$(LD_ADDRESS_SANITIZER)",
);
NO = ();
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,4 +141,89 @@ fileprivate struct LinkerTaskConstructionTests: CoreBasedTests {
}
}
}

@Test(
.tags(
.TestSize.medium,
),
.requireSDKs(.host),
arguments: [
(
buildSettingNameUT: "ENABLE_ADDRESS_SANITIZER",
linkerDriverUT: "clang",
expectedArgument: "-fsanitize=address",
),
(
buildSettingNameUT: "ENABLE_ADDRESS_SANITIZER",
linkerDriverUT: "swiftc",
expectedArgument: "-sanitize=address",
),
(
buildSettingNameUT: "ENABLE_THREAD_SANITIZER",
linkerDriverUT: "clang",
expectedArgument: "-fsanitize=thread",
),
(
buildSettingNameUT: "ENABLE_THREAD_SANITIZER",
linkerDriverUT: "swiftc",
expectedArgument: "-sanitize=thread",
),
]
)
func ldSanitizerArgumentsAppearsOnCommandLine(
buildSettingNameUT: String,
linkerDriverUT: String,
expectedArgument: String,
) async throws {
let testProject = TestProject(
"aProject",
groupTree: TestGroup(
"SomeFiles",
children: [
TestFile("c.c"),
TestFile("cxx.cpp"),
TestFile("s.swift"),
]),
buildConfigurations: [
TestBuildConfiguration("Debug", buildSettings: [
"PRODUCT_NAME": "$(TARGET_NAME)",
"SWIFT_EXEC": try await swiftCompilerPath.str,
"SWIFT_VERSION": try await swiftVersion
]),
],
targets: [
TestStandardTarget(
"Library",
type: .dynamicLibrary,
buildConfigurations: [
TestBuildConfiguration("Debug", buildSettings: [:]),
],
buildPhases: [
TestSourcesBuildPhase(["c.c", "cxx.cpp", "s.swift"]),
]
),
],
)
let core = try await getCore()
let tester = try TaskConstructionTester(core, testProject)
let buildOverrides = [
"LINKER_DRIVER": linkerDriverUT,
buildSettingNameUT: "YES",
]

await tester.checkBuild(
BuildParameters(
configuration: "Debug",
overrides: buildOverrides,
),
runDestination: .host,
) { results in
results.checkNoDiagnostics()
results.checkTask(.matchRuleType("Ld")) { task in
task.checkCommandLineContains([expectedArgument])
}
}

}

}
23 changes: 18 additions & 5 deletions Tests/SWBTaskConstructionTests/TaskConstructionTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4061,8 +4061,17 @@ fileprivate struct TaskConstructionTests: CoreBasedTests {
}

/// Test that we properly generate commands for the compiler sanitizer features.
@Test(.requireSDKs(.macOS))
func sanitizers() async throws {
@Test(
.requireSDKs(.macOS),
arguments:[
(linkerDriver: "clang", expectedArgument: "-fsanitize=address"),
(linkerDriver: "swiftc", expectedArgument: "-sanitize=address"),
],
)
func sanitizers(
linkerDriver: String,
expectedArgument: String,
) async throws {
try await withTemporaryDirectory { tmpDir in
let targetName = "AppTarget"
let testProject = try await TestProject(
Expand Down Expand Up @@ -4115,7 +4124,7 @@ fileprivate struct TaskConstructionTests: CoreBasedTests {
}

// Check the LibSystem address sanitizer.
await tester.checkBuild(BuildParameters(configuration: "Debug", overrides: ["ENABLE_ADDRESS_SANITIZER": "YES","ENABLE_SYSTEM_SANITIZERS": "YES" ]), runDestination: .macOS, fs: fs) { results in
await tester.checkBuild(BuildParameters(configuration: "Debug", overrides: ["LINKER_DRIVER": linkerDriver,"ENABLE_ADDRESS_SANITIZER": "YES","ENABLE_SYSTEM_SANITIZERS": "YES" ]), runDestination: .macOS, fs: fs) { results in
results.checkTarget(targetName) { target in
// There should be one CompileC task, which includes the ASan option, and which puts its output in a -asan directory.
results.checkTask(.matchTarget(target), .matchRuleType("CompileC")) { task in
Expand All @@ -4129,8 +4138,12 @@ fileprivate struct TaskConstructionTests: CoreBasedTests {
}
results.checkTask(.matchTarget(target), .matchRuleType("Ld")) { task in
task.checkCommandLineContains(
["-fsanitize=address", "-fsanitize-stable-abi", "\(SRCROOT)/build/Debug/\(targetName).app/Contents/MacOS/\(targetName)"
])
[
expectedArgument,
"-fsanitize-stable-abi",
"\(SRCROOT)/build/Debug/\(targetName).app/Contents/MacOS/\(targetName)",
]
)
}
}
}
Expand Down