Fix tee functionality in Rust unit test wrapper

The output was captured, but not printed to stdout. Additionally, the
check_output method causes an exception when the child fails so the
output was completely lost on test failure.

The revised function forwards the process's stdout to both the
parent's and a buffer.

Color output is also restored.

Bug: 1271215
Change-Id: I11e9873eb44688fc47acc057af391f7cca605505
Cq-Include-Trybots: luci.chromium.try:android-rust-arm32-rel,android-rust-arm64-dbg,android-rust-arm64-rel,linux-rust-x64-dbg,linux-rust-x64-rel,win-rust-x64-rel
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4501262
Reviewed-by: Ɓukasz Anforowicz <[email protected]>
Auto-Submit: Collin Baker <[email protected]>
Commit-Queue: Collin Baker <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1138921}
NOKEYCHECK=True
GitOrigin-RevId: 9de05d828b865f7b41de3bd166d06a9d5b24d82b
diff --git a/exe_util.py b/exe_util.py
index 32e284d..0b61ad3 100644
--- a/exe_util.py
+++ b/exe_util.py
@@ -7,11 +7,12 @@
 import os
 import subprocess
 import re
+import sys
 
 # Regex for matching 7-bit and 8-bit C1 ANSI sequences.
 # Credit: https://stackoverflow.com/a/14693789/4692014
 _ANSI_ESCAPE_8BIT_REGEX = re.compile(
-    br"""
+    r"""
     (?: # either 7-bit C1, two bytes, ESC Fe (omitting CSI)
         \x1B
         [@-Z\\-_]
@@ -37,8 +38,17 @@
     Returns:
         The full executable output as an UTF-8 string.
     """
-    output_bytes = subprocess.check_output(args)
-    # Strip ANSI / terminal escapes.
-    output_bytes = _ANSI_ESCAPE_8BIT_REGEX.sub(b'', output_bytes)
+    # Capture stdout (where test results are written), but inherit stderr. This
+    # way errors related to invalid arguments are printed normally.
+    proc = subprocess.Popen(args, stdout=subprocess.PIPE)
+    captured_output = b''
+    while proc.poll() is None:
+        buf = proc.stdout.read()
+        # Write captured output directly, so escape sequences are preserved.
+        sys.stdout.buffer.write(buf)
+        captured_output += buf
 
-    return output_bytes.decode('utf-8')
+    captured_output = _ANSI_ESCAPE_8BIT_REGEX.sub(
+        '', captured_output.decode('utf-8'))
+
+    return captured_output
diff --git a/rust_main_program.py b/rust_main_program.py
index c09193f..db156d8 100644
--- a/rust_main_program.py
+++ b/rust_main_program.py
@@ -150,7 +150,7 @@
         # output to the terminal).
         args = [
             self._path_to_test_executable, '--test', '--format=pretty',
-            '--exact'
+            '--color=always', '--exact'
         ]
         args.extend(list_of_tests_to_run)