@@ -56,6 +56,16 @@ public struct Runner: Sendable {
5656// MARK: - Running tests
5757
5858extension Runner {
59+ /// The current configuration _while_ running.
60+ ///
61+ /// This should be used from the functions in this extension which access the
62+ /// current configuration. This is important since individual tests or suites
63+ /// may have traits which customize the execution scope of their children,
64+ /// including potentially modifying the current configuration.
65+ private static var _configuration : Configuration {
66+ . current ?? . init( )
67+ }
68+
5969 /// Apply the custom scope for any test scope providers of the traits
6070 /// associated with a specified test by calling their
6171 /// ``TestScoping/provideScope(for:testCase:performing:)`` function.
@@ -70,7 +80,7 @@ extension Runner {
7080 ///
7181 /// - Throws: Whatever is thrown by `body` or by any of the
7282 /// ``TestScoping/provideScope(for:testCase:performing:)`` function calls.
73- private func _applyScopingTraits(
83+ private static func _applyScopingTraits(
7484 for test: Test ,
7585 testCase: Test . Case ? ,
7686 _ body: @escaping @Sendable ( ) async throws -> Void
@@ -103,21 +113,13 @@ extension Runner {
103113 ///
104114 /// - Parameters:
105115 /// - sequence: The sequence to enumerate.
106- /// - step: The plan step that controls parallelization. If `nil`, or if its
107- /// ``Runner/Plan/Step/action`` property is not of case
108- /// ``Runner/Plan/Action/run(options:)``, the
109- /// ``Configuration/isParallelizationEnabled`` property of this runner's
110- /// ``configuration`` property is used instead to determine if
111- /// parallelization is enabled.
112116 /// - body: The function to invoke.
113117 ///
114118 /// - Throws: Whatever is thrown by `body`.
115- private func _forEach< E> (
119+ private static func _forEach< E> (
116120 in sequence: some Sequence < E > ,
117- for step: Plan . Step ? ,
118121 _ body: @Sendable @escaping ( E) async throws -> Void
119122 ) async throws where E: Sendable {
120- let isParallelizationEnabled = step? . action. isParallelizationEnabled ?? configuration. isParallelizationEnabled
121123 try await withThrowingTaskGroup ( of: Void . self) { taskGroup in
122124 for element in sequence {
123125 // Each element gets its own subtask to run in.
@@ -126,7 +128,7 @@ extension Runner {
126128 }
127129
128130 // If not parallelizing, wait after each task.
129- if !isParallelizationEnabled {
131+ if !_configuration . isParallelizationEnabled {
130132 try await taskGroup. waitForAll ( )
131133 }
132134 }
@@ -137,12 +139,6 @@ extension Runner {
137139 ///
138140 /// - Parameters:
139141 /// - stepGraph: The subgraph whose root value, a step, is to be run.
140- /// - depth: How deep into the step graph this call is. The first call has a
141- /// depth of `0`.
142- /// - lastAncestorStep: The last-known ancestral step, if any, of the step
143- /// at the root of `stepGraph`. The options in this step (if its action is
144- /// of case ``Runner/Plan/Action/run(options:)``) inform the execution of
145- /// `stepGraph`.
146142 ///
147143 /// - Throws: Whatever is thrown from the test body. Thrown errors are
148144 /// normally reported as test failures.
@@ -157,7 +153,7 @@ extension Runner {
157153 /// ## See Also
158154 ///
159155 /// - ``Runner/run()``
160- private func _runStep( atRootOf stepGraph: Graph < String , Plan . Step ? > , depth : Int , lastAncestorStep : Plan . Step ? ) async throws {
156+ private static func _runStep( atRootOf stepGraph: Graph < String , Plan . Step ? > ) async throws {
161157 // Exit early if the task has already been cancelled.
162158 try Task . checkCancellation ( )
163159
@@ -166,6 +162,8 @@ extension Runner {
166162 // example, a skip event only sends `.testSkipped`.
167163 let shouldSendTestEnded : Bool
168164
165+ let configuration = _configuration
166+
169167 // Determine what action to take for this step.
170168 if let step = stepGraph. value {
171169 Event . post ( . planStepStarted( step) , for: ( step. test, nil ) , configuration: configuration)
@@ -204,14 +202,14 @@ extension Runner {
204202 }
205203
206204 // Run the children of this test (i.e. the tests in this suite.)
207- try await _runChildren ( of: stepGraph, depth : depth , lastAncestorStep : lastAncestorStep )
205+ try await _runChildren ( of: stepGraph)
208206 }
209207 }
210208 }
211209 } else {
212210 // There is no test at this node in the graph, so just skip down to the
213211 // child nodes.
214- try await _runChildren ( of: stepGraph, depth : depth , lastAncestorStep : lastAncestorStep )
212+ try await _runChildren ( of: stepGraph)
215213 }
216214 }
217215
@@ -222,7 +220,7 @@ extension Runner {
222220 ///
223221 /// - Returns: The source location of the root node of `stepGraph`, or of the
224222 /// first descendant node thereof (sorted by source location.)
225- private func _sourceLocation( of stepGraph: Graph < String , Plan . Step ? > ) -> SourceLocation ? {
223+ private static func _sourceLocation( of stepGraph: Graph < String , Plan . Step ? > ) -> SourceLocation ? {
226224 if let result = stepGraph. value? . test. sourceLocation {
227225 return result
228226 }
@@ -234,26 +232,13 @@ extension Runner {
234232 /// Recursively run the tests that are children of a given plan step.
235233 ///
236234 /// - Parameters:
237- /// - stepGraph: The subgraph whose root value, a step, is to be run.
238- /// - depth: How deep into the step graph this call is. The first call has a
239- /// depth of `0`.
240- /// - lastAncestorStep: The last-known ancestral step, if any, of the step
241- /// at the root of `stepGraph`. The options in this step (if its action is
242- /// of case ``Runner/Plan/Action/run(options:)``) inform the execution of
243- /// `stepGraph`.
235+ /// - stepGraph: The subgraph whose root value, a step, will be used to
236+ /// find children to run.
244237 ///
245238 /// - Throws: Whatever is thrown from the test body. Thrown errors are
246239 /// normally reported as test failures.
247- private func _runChildren( of stepGraph: Graph < String , Plan . Step ? > , depth: Int , lastAncestorStep: Plan . Step ? ) async throws {
248- // Figure out the last-good step, either the one at the root of `stepGraph`
249- // or, if it is nil, the one passed into this function. We need to track
250- // this value in case we run into sparse sections of the graph so we don't
251- // lose track of the recursive `isParallelizationEnabled` property in the
252- // runnable steps' options.
253- let stepOrAncestor = stepGraph. value ?? lastAncestorStep
254-
255- let isParallelizationEnabled = stepOrAncestor? . action. isParallelizationEnabled ?? configuration. isParallelizationEnabled
256- let childGraphs = if isParallelizationEnabled {
240+ private static func _runChildren( of stepGraph: Graph < String , Plan . Step ? > ) async throws {
241+ let childGraphs = if _configuration. isParallelizationEnabled {
257242 // Explicitly shuffle the steps to help detect accidental dependencies
258243 // between tests due to their ordering.
259244 Array ( stepGraph. children)
@@ -282,8 +267,8 @@ extension Runner {
282267 }
283268
284269 // Run the child nodes.
285- try await _forEach ( in: childGraphs, for : stepOrAncestor ) { _, childGraph in
286- try await _runStep ( atRootOf: childGraph, depth : depth + 1 , lastAncestorStep : stepOrAncestor )
270+ try await _forEach ( in: childGraphs) { _, childGraph in
271+ try await _runStep ( atRootOf: childGraph)
287272 }
288273 }
289274
@@ -298,13 +283,14 @@ extension Runner {
298283 ///
299284 /// If parallelization is supported and enabled, the generated test cases will
300285 /// be run in parallel using a task group.
301- private func _runTestCases( _ testCases: some Sequence < Test . Case > , within step: Plan . Step ) async throws {
286+ private static func _runTestCases( _ testCases: some Sequence < Test . Case > , within step: Plan . Step ) async throws {
302287 // Apply the configuration's test case filter.
288+ let testCaseFilter = _configuration. testCaseFilter
303289 let testCases = testCases. lazy. filter { testCase in
304- configuration . testCaseFilter ( testCase, step. test)
290+ testCaseFilter ( testCase, step. test)
305291 }
306292
307- try await _forEach ( in: testCases, for : step ) { testCase in
293+ try await _forEach ( in: testCases) { testCase in
308294 try await _runTestCase ( testCase, within: step)
309295 }
310296 }
@@ -320,10 +306,12 @@ extension Runner {
320306 ///
321307 /// This function sets ``Test/Case/current``, then invokes the test case's
322308 /// body closure.
323- private func _runTestCase( _ testCase: Test . Case , within step: Plan . Step ) async throws {
309+ private static func _runTestCase( _ testCase: Test . Case , within step: Plan . Step ) async throws {
324310 // Exit early if the task has already been cancelled.
325311 try Task . checkCancellation ( )
326312
313+ let configuration = _configuration
314+
327315 Event . post ( . testCaseStarted, for: ( step. test, testCase) , configuration: configuration)
328316 defer {
329317 Event . post ( . testCaseEnded, for: ( step. test, testCase) , configuration: configuration)
@@ -357,9 +345,6 @@ extension Runner {
357345 ///
358346 /// - Parameters:
359347 /// - runner: The runner to run.
360- /// - configuration: The configuration to use for running. The value of this
361- /// argument temporarily replaces the value of `runner`'s
362- /// ``Runner/configuration`` property.
363348 ///
364349 /// This function is `static` so that it cannot accidentally reference `self`
365350 /// or `self.configuration` when it should use a modified copy of either.
@@ -399,7 +384,7 @@ extension Runner {
399384
400385 await withTaskGroup ( of: Void . self) { [ runner] taskGroup in
401386 _ = taskGroup. addTaskUnlessCancelled {
402- try ? await runner . _runStep ( atRootOf: runner. plan. stepGraph, depth : 0 , lastAncestorStep : nil )
387+ try ? await _runStep ( atRootOf: runner. plan. stepGraph)
403388 }
404389 await taskGroup. waitForAll ( )
405390 }
0 commit comments