@@ -839,7 +839,7 @@ func _childProcess() {
839839 var stderr = _Stderr ( )
840840 print ( " \( _stdlibUnittestStreamPrefix) ;end " , to: & stderr)
841841
842- if ! testSuite. _testByName ( testName) . canReuseChildProcessAfterTest {
842+ if testSuite. _shouldShutDownChildProcess ( forTestNamed : testName) {
843843 return
844844 }
845845 }
@@ -1107,7 +1107,7 @@ class _ParentProcess {
11071107 // Check if the child has sent us "end" markers for the current test.
11081108 if stdoutEnd && stderrEnd {
11091109 var status : ProcessTerminationStatus ?
1110- if ! testSuite. _testByName ( testName) . canReuseChildProcessAfterTest {
1110+ if testSuite. _shouldShutDownChildProcess ( forTestNamed : testName) {
11111111 status = _waitForChild ( )
11121112 switch status! {
11131113 case . exit( 0 ) :
@@ -1147,7 +1147,11 @@ class _ParentProcess {
11471147 return ( failed: false , ( ) )
11481148 }
11491149#endif
1150- print ( " \( _stdlibUnittestStreamPrefix) ;shutdown " , to: & _childStdin)
1150+ // If the child process expects an EOF, its stdin fd has already been closed and
1151+ // it will shut itself down automatically.
1152+ if !_childStdin. isClosed {
1153+ print ( " \( _stdlibUnittestStreamPrefix) ;shutdown " , to: & _childStdin)
1154+ }
11511155
11521156 var childCrashed = false
11531157
@@ -1209,6 +1213,9 @@ class _ParentProcess {
12091213 if t. stdinText != nil {
12101214 print ( " The test \( fullTestName) requires stdin input and can't be run in-process, marking as failed " )
12111215 _anyExpectFailed = true
1216+ } else if t. requiresOwnProcess {
1217+ print ( " The test \( fullTestName) requires running in a child process and can't be run in-process, marking as failed. " )
1218+ _anyExpectFailed = true
12121219 } else {
12131220 _anyExpectFailed = false
12141221 testSuite. _runTest ( name: t. name, parameter: testParameter)
@@ -1550,6 +1557,17 @@ public final class TestSuite {
15501557 return _tests [ _testNameToIndex [ testName] !]
15511558 }
15521559
1560+ /// Determines if we should shut down the current test process, i.e. if this
1561+ /// test or the next test requires executing in its own process.
1562+ func _shouldShutDownChildProcess( forTestNamed testName: String ) -> Bool {
1563+ let index = _testNameToIndex [ testName] !
1564+ if index == _tests. count - 1 { return false }
1565+ let currentTest = _tests [ index]
1566+ let nextTest = _tests [ index + 1 ]
1567+ if !currentTest. canReuseChildProcessAfterTest { return true }
1568+ return currentTest. requiresOwnProcess || nextTest. requiresOwnProcess
1569+ }
1570+
15531571 internal enum _TestCode {
15541572 case single( code: ( ) -> Void )
15551573 case parameterized( code: ( Int ) -> Void , count: Int )
@@ -1564,6 +1582,7 @@ public final class TestSuite {
15641582 let stdinEndsWithEOF : Bool
15651583 let crashOutputMatches : [ String ]
15661584 let code : _TestCode
1585+ let requiresOwnProcess : Bool
15671586
15681587 /// Whether the test harness should stop reusing the child process after
15691588 /// running this test.
@@ -1601,6 +1620,7 @@ public final class TestSuite {
16011620 var _stdinEndsWithEOF : Bool = false
16021621 var _crashOutputMatches : [ String ] = [ ]
16031622 var _testLoc : SourceLoc ?
1623+ var _requiresOwnProcess : Bool = false
16041624 }
16051625
16061626 init ( testSuite: TestSuite , name: String , loc: SourceLoc ) {
@@ -1630,6 +1650,11 @@ public final class TestSuite {
16301650 return self
16311651 }
16321652
1653+ public func requireOwnProcess( ) -> _TestBuilder {
1654+ _data. _requiresOwnProcess = true
1655+ return self
1656+ }
1657+
16331658 internal func _build( _ testCode: _TestCode ) {
16341659 _testSuite. _tests. append (
16351660 _Test (
@@ -1638,7 +1663,8 @@ public final class TestSuite {
16381663 stdinText: _data. _stdinText,
16391664 stdinEndsWithEOF: _data. _stdinEndsWithEOF,
16401665 crashOutputMatches: _data. _crashOutputMatches,
1641- code: testCode) )
1666+ code: testCode,
1667+ requiresOwnProcess: _data. _requiresOwnProcess) )
16421668 _testSuite. _testNameToIndex [ _name] = _testSuite. _tests. count - 1
16431669 }
16441670
0 commit comments