Skip to content

Commit ae42dd5

Browse files
hi-kumaryonaskolb
andauthored
Address Sanitizer options in run/test schemes (#1550)
* Expose address sanitizer flags in run and test BuildActions in Schemes * Update testJSONEncodable to test the new fields * Also test the asan setting values for run scheme * Update changelog --------- Co-authored-by: Yonas Kolb <[email protected]>
1 parent 38d76e7 commit ae42dd5

File tree

4 files changed

+92
-1
lines changed

4 files changed

+92
-1
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
## Next Version
44

5+
### Added
6+
- Added sanitizer options to run and test actions in Scheme #1550 @hi-kumar
7+
58
### Fixed
69
- Added validation to ensure that all values in `settings.configs` are mappings. Previously, passing non-mapping values did not raise an error, making it difficult to detect misconfigurations. Now, `SpecParsingError.invalidConfigsMappingFormat` is thrown if misused. #1547 @Ryu0118
710

Sources/ProjectSpec/Scheme.swift

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,10 @@ public struct Scheme: Equatable {
127127
}
128128

129129
public struct Run: BuildAction {
130+
public static let enableAddressSanitizerDefault = false
131+
public static let enableASanStackUseAfterReturnDefault = false
132+
public static let enableThreadSanitizerDefault = false
133+
public static let enableUBSanitizerDefault = false
130134
public static let disableMainThreadCheckerDefault = false
131135
public static let stopOnEveryMainThreadCheckerIssueDefault = false
132136
public static let disableThreadPerformanceCheckerDefault = false
@@ -140,6 +144,10 @@ public struct Scheme: Equatable {
140144
public var environmentVariables: [XCScheme.EnvironmentVariable]
141145
public var enableGPUFrameCaptureMode: XCScheme.LaunchAction.GPUFrameCaptureMode
142146
public var enableGPUValidationMode: Bool
147+
public var enableAddressSanitizer: Bool
148+
public var enableASanStackUseAfterReturn: Bool
149+
public var enableThreadSanitizer: Bool
150+
public var enableUBSanitizer: Bool
143151
public var disableMainThreadChecker: Bool
144152
public var stopOnEveryMainThreadCheckerIssue: Bool
145153
public var disableThreadPerformanceChecker: Bool
@@ -163,6 +171,10 @@ public struct Scheme: Equatable {
163171
environmentVariables: [XCScheme.EnvironmentVariable] = [],
164172
enableGPUFrameCaptureMode: XCScheme.LaunchAction.GPUFrameCaptureMode = XCScheme.LaunchAction.defaultGPUFrameCaptureMode,
165173
enableGPUValidationMode: Bool = enableGPUValidationModeDefault,
174+
enableAddressSanitizer: Bool = enableAddressSanitizerDefault,
175+
enableASanStackUseAfterReturn: Bool = enableASanStackUseAfterReturnDefault,
176+
enableThreadSanitizer: Bool = enableThreadSanitizerDefault,
177+
enableUBSanitizer: Bool = enableUBSanitizerDefault,
166178
disableMainThreadChecker: Bool = disableMainThreadCheckerDefault,
167179
stopOnEveryMainThreadCheckerIssue: Bool = stopOnEveryMainThreadCheckerIssueDefault,
168180
disableThreadPerformanceChecker: Bool = disableThreadPerformanceCheckerDefault,
@@ -181,6 +193,10 @@ public struct Scheme: Equatable {
181193
self.preActions = preActions
182194
self.postActions = postActions
183195
self.environmentVariables = environmentVariables
196+
self.enableAddressSanitizer = enableAddressSanitizer
197+
self.enableASanStackUseAfterReturn = enableASanStackUseAfterReturn
198+
self.enableThreadSanitizer = enableThreadSanitizer
199+
self.enableUBSanitizer = enableUBSanitizer
184200
self.disableMainThreadChecker = disableMainThreadChecker
185201
self.enableGPUFrameCaptureMode = enableGPUFrameCaptureMode
186202
self.enableGPUValidationMode = enableGPUValidationMode
@@ -200,6 +216,10 @@ public struct Scheme: Equatable {
200216

201217
public struct Test: BuildAction {
202218
public static let gatherCoverageDataDefault = false
219+
public static let enableAddressSanitizerDefault = false
220+
public static let enableASanStackUseAfterReturnDefault = false
221+
public static let enableThreadSanitizerDefault = false
222+
public static let enableUBSanitizerDefault = false
203223
public static let disableMainThreadCheckerDefault = false
204224
public static let debugEnabledDefault = true
205225
public static let captureScreenshotsAutomaticallyDefault = true
@@ -209,6 +229,10 @@ public struct Scheme: Equatable {
209229
public var config: String?
210230
public var gatherCoverageData: Bool
211231
public var coverageTargets: [TestableTargetReference]
232+
public var enableAddressSanitizer: Bool
233+
public var enableASanStackUseAfterReturn: Bool
234+
public var enableThreadSanitizer: Bool
235+
public var enableUBSanitizer: Bool
212236
public var disableMainThreadChecker: Bool
213237
public var commandLineArguments: [String: Bool]
214238
public var targets: [TestTarget]
@@ -276,6 +300,10 @@ public struct Scheme: Equatable {
276300
config: String? = nil,
277301
gatherCoverageData: Bool = gatherCoverageDataDefault,
278302
coverageTargets: [TestableTargetReference] = [],
303+
enableAddressSanitizer: Bool = enableAddressSanitizerDefault,
304+
enableASanStackUseAfterReturn: Bool = enableASanStackUseAfterReturnDefault,
305+
enableThreadSanitizer: Bool = enableThreadSanitizerDefault,
306+
enableUBSanitizer: Bool = enableUBSanitizerDefault,
279307
disableMainThreadChecker: Bool = disableMainThreadCheckerDefault,
280308
randomExecutionOrder: Bool = false,
281309
parallelizable: Bool = false,
@@ -297,6 +325,10 @@ public struct Scheme: Equatable {
297325
self.config = config
298326
self.gatherCoverageData = gatherCoverageData
299327
self.coverageTargets = coverageTargets
328+
self.enableAddressSanitizer = enableAddressSanitizer
329+
self.enableASanStackUseAfterReturn = enableASanStackUseAfterReturn
330+
self.enableThreadSanitizer = enableThreadSanitizer
331+
self.enableUBSanitizer = enableUBSanitizer
300332
self.disableMainThreadChecker = disableMainThreadChecker
301333
self.commandLineArguments = commandLineArguments
302334
self.targets = targets
@@ -500,6 +532,10 @@ extension Scheme.Run: JSONObjectConvertible {
500532
} else {
501533
enableGPUValidationMode = jsonDictionary.json(atKeyPath: "enableGPUValidationMode") ?? Scheme.Run.enableGPUValidationModeDefault
502534
}
535+
enableAddressSanitizer = jsonDictionary.json(atKeyPath: "enableAddressSanitizer") ?? Scheme.Run.enableAddressSanitizerDefault
536+
enableASanStackUseAfterReturn = jsonDictionary.json(atKeyPath: "enableASanStackUseAfterReturn") ?? Scheme.Run.enableASanStackUseAfterReturnDefault
537+
enableThreadSanitizer = jsonDictionary.json(atKeyPath: "enableThreadSanitizer") ?? Scheme.Run.enableThreadSanitizerDefault
538+
enableUBSanitizer = jsonDictionary.json(atKeyPath: "enableUBSanitizer") ?? Scheme.Run.enableUBSanitizerDefault
503539
disableMainThreadChecker = jsonDictionary.json(atKeyPath: "disableMainThreadChecker") ?? Scheme.Run.disableMainThreadCheckerDefault
504540
stopOnEveryMainThreadCheckerIssue = jsonDictionary.json(atKeyPath: "stopOnEveryMainThreadCheckerIssue") ?? Scheme.Run.stopOnEveryMainThreadCheckerIssueDefault
505541
disableThreadPerformanceChecker = jsonDictionary.json(atKeyPath: "disableThreadPerformanceChecker") ?? Scheme.Run.disableThreadPerformanceCheckerDefault
@@ -550,6 +586,22 @@ extension Scheme.Run: JSONEncodable {
550586
dict["enableGPUValidationMode"] = enableGPUValidationMode
551587
}
552588

589+
if enableAddressSanitizer != Scheme.Run.enableAddressSanitizerDefault {
590+
dict["enableAddressSanitizer"] = enableAddressSanitizer
591+
}
592+
593+
if enableASanStackUseAfterReturn != Scheme.Run.enableASanStackUseAfterReturnDefault {
594+
dict["enableASanStackUseAfterReturn"] = enableASanStackUseAfterReturn
595+
}
596+
597+
if enableThreadSanitizer != Scheme.Run.enableThreadSanitizerDefault {
598+
dict["enableThreadSanitizer"] = enableThreadSanitizer
599+
}
600+
601+
if enableUBSanitizer != Scheme.Run.enableUBSanitizerDefault {
602+
dict["enableUBSanitizer"] = enableUBSanitizer
603+
}
604+
553605
if disableMainThreadChecker != Scheme.Run.disableMainThreadCheckerDefault {
554606
dict["disableMainThreadChecker"] = disableMainThreadChecker
555607
}
@@ -608,7 +660,11 @@ extension Scheme.Test: JSONObjectConvertible {
608660
} else {
609661
coverageTargets = []
610662
}
611-
663+
664+
enableAddressSanitizer = jsonDictionary.json(atKeyPath: "enableAddressSanitizer") ?? Scheme.Test.enableAddressSanitizerDefault
665+
enableASanStackUseAfterReturn = jsonDictionary.json(atKeyPath: "enableASanStackUseAfterReturn") ?? Scheme.Test.enableASanStackUseAfterReturnDefault
666+
enableThreadSanitizer = jsonDictionary.json(atKeyPath: "enableThreadSanitizer") ?? Scheme.Test.enableThreadSanitizerDefault
667+
enableUBSanitizer = jsonDictionary.json(atKeyPath: "enableUBSanitizer") ?? Scheme.Test.enableUBSanitizerDefault
612668
disableMainThreadChecker = jsonDictionary.json(atKeyPath: "disableMainThreadChecker") ?? Scheme.Test.disableMainThreadCheckerDefault
613669
commandLineArguments = jsonDictionary.json(atKeyPath: "commandLineArguments") ?? [:]
614670
if let targets = jsonDictionary["targets"] as? [Any] {
@@ -659,6 +715,22 @@ extension Scheme.Test: JSONEncodable {
659715
dict["gatherCoverageData"] = gatherCoverageData
660716
}
661717

718+
if enableAddressSanitizer != Scheme.Test.enableAddressSanitizerDefault {
719+
dict["enableAddressSanitizer"] = enableAddressSanitizer
720+
}
721+
722+
if enableASanStackUseAfterReturn != Scheme.Test.enableASanStackUseAfterReturnDefault {
723+
dict["enableASanStackUseAfterReturn"] = enableASanStackUseAfterReturn
724+
}
725+
726+
if enableThreadSanitizer != Scheme.Test.enableThreadSanitizerDefault {
727+
dict["enableThreadSanitizer"] = enableThreadSanitizer
728+
}
729+
730+
if enableUBSanitizer != Scheme.Test.enableUBSanitizerDefault {
731+
dict["enableUBSanitizer"] = enableUBSanitizer
732+
}
733+
662734
if disableMainThreadChecker != Scheme.Test.disableMainThreadCheckerDefault {
663735
dict["disableMainThreadChecker"] = disableMainThreadChecker
664736
}

Sources/XcodeGenKit/SchemeGenerator.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,10 @@ public class SchemeGenerator {
311311
codeCoverageEnabled: scheme.test?.gatherCoverageData ?? Scheme.Test.gatherCoverageDataDefault,
312312
codeCoverageTargets: coverageBuildableTargets,
313313
onlyGenerateCoverageForSpecifiedTargets: !coverageBuildableTargets.isEmpty,
314+
enableAddressSanitizer: scheme.test?.enableAddressSanitizer ?? Scheme.Test.enableAddressSanitizerDefault,
315+
enableASanStackUseAfterReturn: scheme.test?.enableASanStackUseAfterReturn ?? Scheme.Test.enableASanStackUseAfterReturnDefault,
316+
enableThreadSanitizer: scheme.test?.enableThreadSanitizer ?? Scheme.Test.enableThreadSanitizerDefault,
317+
enableUBSanitizer: scheme.test?.enableUBSanitizer ?? Scheme.Test.enableUBSanitizerDefault,
314318
disableMainThreadChecker: scheme.test?.disableMainThreadChecker ?? Scheme.Test.disableMainThreadCheckerDefault,
315319
commandlineArguments: testCommandLineArgs,
316320
environmentVariables: testVariables,
@@ -359,6 +363,10 @@ public class SchemeGenerator {
359363
locationScenarioReference: locationScenarioReference,
360364
enableGPUFrameCaptureMode: scheme.run?.enableGPUFrameCaptureMode ?? XCScheme.LaunchAction.defaultGPUFrameCaptureMode,
361365
disableGPUValidationMode: !(scheme.run?.enableGPUValidationMode ?? Scheme.Run.enableGPUValidationModeDefault),
366+
enableAddressSanitizer: scheme.run?.enableAddressSanitizer ?? Scheme.Run.enableAddressSanitizerDefault,
367+
enableASanStackUseAfterReturn: scheme.run?.enableASanStackUseAfterReturn ?? Scheme.Run.enableASanStackUseAfterReturnDefault,
368+
enableThreadSanitizer: scheme.run?.enableThreadSanitizer ?? Scheme.Run.enableThreadSanitizerDefault,
369+
enableUBSanitizer: scheme.run?.enableUBSanitizer ?? Scheme.Run.enableUBSanitizerDefault,
362370
disableMainThreadChecker: scheme.run?.disableMainThreadChecker ?? Scheme.Run.disableMainThreadCheckerDefault,
363371
disablePerformanceAntipatternChecker: scheme.run?.disableThreadPerformanceChecker ?? Scheme.Run.disableThreadPerformanceCheckerDefault,
364372
stopOnEveryMainThreadCheckerIssue: scheme.run?.stopOnEveryMainThreadCheckerIssue ?? Scheme.Run.stopOnEveryMainThreadCheckerIssueDefault,

Tests/ProjectSpecTests/ProjectSpecTests.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,10 +768,18 @@ class ProjectSpecTests: XCTestCase {
768768
value: "bar",
769769
enabled: false)],
770770
enableGPUFrameCaptureMode: .openGL,
771+
enableAddressSanitizer: true,
772+
enableASanStackUseAfterReturn: true,
773+
enableThreadSanitizer: true,
774+
enableUBSanitizer: true,
771775
launchAutomaticallySubstyle: "2",
772776
storeKitConfiguration: "Configuration.storekit"),
773777
test: Scheme.Test(config: "Config",
774778
gatherCoverageData: true,
779+
enableAddressSanitizer: true,
780+
enableASanStackUseAfterReturn: true,
781+
enableThreadSanitizer: true,
782+
enableUBSanitizer: true,
775783
disableMainThreadChecker: true,
776784
randomExecutionOrder: false,
777785
parallelizable: false,

0 commit comments

Comments
 (0)