Skip to content

Commit 829625f

Browse files
committed
Improve sanitizer usage
This makes a few small improvements to using sanitizers: 1. Include the valid values in `--help`. Before: ``` --sanitize <sanitize> Turn on runtime checks for erroneous behavior ``` After: ``` --sanitize <sanitize> Turn on runtime checks for erroneous behavior, possible values: address, thread, undefined, scudo ``` 2. Improve error for invalid values. Before: ``` error: unknown value 'invalid' for argument --sanitize; use --help to print usage ``` After: ``` error: The value 'invalid' is invalid for '--sanitize <sanitize>': valid sanitizers: address, thread, undefined, scudo ``` 3. Allow underlying values as arguments. Before: ``` error: unknown value 'tsan' for argument --sanitize; use --help to print usage ``` After: Works! Fixes: - https://bugs.swift.org/browse/SR-12545 - https://bugs.swift.org/browse/SR-12546
1 parent 8047543 commit 829625f

File tree

3 files changed

+37
-2
lines changed

3 files changed

+37
-2
lines changed

Sources/Commands/Options.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ public struct SwiftToolOptions: ParsableArguments {
180180

181181
/// Which compile-time sanitizers should be enabled.
182182
@Option(name: .customLong("sanitize"),
183-
help: "Turn on runtime checks for erroneous behavior",
183+
help: "Turn on runtime checks for erroneous behavior, possible values: \(Sanitizer.formattedValues)",
184184
transform: { try Sanitizer(argument: $0) })
185185
var sanitizers: [Sanitizer] = []
186186

Sources/SPMBuildCore/Sanitizers.swift

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,31 @@ import TSCBasic
1212
import TSCUtility
1313

1414
/// Available runtime sanitizers.
15-
public enum Sanitizer: String, Encodable {
15+
public enum Sanitizer: String, Encodable, CaseIterable {
1616
case address
1717
case thread
1818
case undefined
1919
case scudo
2020

21+
public init(argument: String) throws {
22+
if let sanitizer = Sanitizer(rawValue: argument) {
23+
self = sanitizer
24+
return
25+
}
26+
27+
for sanitizer in Sanitizer.allCases where sanitizer.shortName == argument {
28+
self = sanitizer
29+
return
30+
}
31+
32+
throw ArgumentConversionError.custom("valid sanitizers: \(Sanitizer.formattedValues)")
33+
}
34+
35+
/// All sanitizer options in a comma separated string
36+
public static var formattedValues: String {
37+
return Sanitizer.allCases.map(\.rawValue).joined(separator: ", ")
38+
}
39+
2140
/// Return an established short name for a sanitizer, e.g. "asan".
2241
public var shortName: String {
2342
switch self {

Tests/BuildTests/BuildPlanTests.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2464,6 +2464,22 @@ final class BuildPlanTests: XCTestCase {
24642464
try testBinaryTargets(platform: "macos", arch: "arm64e", destinationTriple: arm64eTriple)
24652465
}
24662466

2467+
func testCreatingSanitizers() throws {
2468+
for sanitizer in Sanitizer.allCases {
2469+
XCTAssertEqual(sanitizer, try Sanitizer(argument: sanitizer.shortName))
2470+
}
2471+
}
2472+
2473+
func testInvalidSanitizer() throws {
2474+
do {
2475+
_ = try Sanitizer(argument: "invalid")
2476+
XCTFail("Should have failed to create Sanitizer")
2477+
} catch let error as ArgumentConversionError {
2478+
XCTAssertEqual(
2479+
error.description, "valid sanitizers: address, thread, undefined, scudo")
2480+
}
2481+
}
2482+
24672483
func testAddressSanitizer() throws {
24682484
try sanitizerTest(.address, expectedName: "address")
24692485
}

0 commit comments

Comments
 (0)