diff --git a/tests/unit/Testables/Shell/RealShellTest.swift b/tests/unit/Testables/Shell/RealShellTest.swift index bedd306b..88450bd3 100644 --- a/tests/unit/Testables/Shell/RealShellTest.swift +++ b/tests/unit/Testables/Shell/RealShellTest.swift @@ -78,14 +78,28 @@ struct RealShellTest { #expect(duration < .milliseconds(2000)) // Should complete in ~700ms if parallel } - @Test func attach_handles_concurrent_stdout_stderr_writes_safely() async throws { - // This test verifies that concurrent writes to output.out and output.err - // from multiple readability handlers don't cause data races or crashes. - // Without the serial queue, rapid interleaved output causes undefined behavior. + /** + This test verifies that concurrent writes to `output.out` and `output.err` + from multiple readability handlers don't cause data races or crashes, + and that the output is correct (for both stdout and stderr output). + When Thread Sanitizer is enabled, this will also check if any potential + data races occur. None should, at this point. You can enable the + Thread Sanitizer by editing the Test Plan's Configurations. + + This test was added specifically to diagnose and fix one such reported + data race, which was fixed by adding a serial queue to the shell's + `attach()` method, since the readability handlers actually run + on separate threads. + */ + @Test func attach_handles_concurrent_stdout_stderr_writes_safely() async throws { + // Create a PHP script that will output lots of text to STDOUT and STDERR. let phpScript = "php -r 'for ($i = 1; $i <= 500; $i++) { fwrite(STDOUT, \"stdout-$i\" . PHP_EOL); fwrite(STDERR, \"stderr-$i\" . PHP_EOL); flush(); }'" + // Keep track of the total chunk count var receivedChunks = 0 + + // We will now test the attach method let (_, shellOutput) = try await container.shell.attach( phpScript, didReceiveOutput: { _, _ in @@ -105,7 +119,7 @@ struct RealShellTest { #expect(stdoutLines.count == 500) #expect(stderrLines.count == 500) - // Verify content integrity - each line should match the pattern + // Verify content integrity for i in 1...200 { #expect(stdoutLines.contains("stdout-\(i)")) #expect(stderrLines.contains("stderr-\(i)"))