Skip to content

Commit b408bbb

Browse files
committed
[libc++] Avoid conflating stderr and stdout in the DSL
This is a workaround until https://reviews.llvm.org/D81892 is merged and the internal Lit shell stops conflating error output with normal output. Without this, any program that writes to stderr will trip up the programOutput function, because it will pick up the '# command stderr:' string and think it's part of the command's stdout. rdar://81056048 Differential Revision: https://reviews.llvm.org/D107912
1 parent 7c81024 commit b408bbb

File tree

2 files changed

+29
-4
lines changed

2 files changed

+29
-4
lines changed

libcxx/test/libcxx/selftest/dsl/dsl.sh.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ def test_caching_is_not_too_aggressive(self):
196196
#include <cstdio>
197197
int main(int, char**) {
198198
std::printf("MACRO=%u\\n", MACRO);
199+
return 0;
199200
}
200201
"""
201202
compileFlagsIndex = findIndex(self.config.substitutions, lambda x: x[0] == '%{compile_flags}')
@@ -209,6 +210,19 @@ def test_caching_is_not_too_aggressive(self):
209210
output2 = dsl.programOutput(self.config, source)
210211
self.assertEqual(output2, "MACRO=2\n")
211212

213+
def test_program_stderr_is_not_conflated_with_stdout(self):
214+
# Run a program that produces stdout output and stderr output too, making
215+
# sure the stderr output does not pollute the stdout output.
216+
source = """
217+
#include <cstdio>
218+
int main(int, char**) {
219+
std::fprintf(stdout, "STDOUT-OUTPUT");
220+
std::fprintf(stderr, "STDERR-OUTPUT");
221+
return 0;
222+
}
223+
"""
224+
self.assertEqual(dsl.programOutput(self.config, source), "STDOUT-OUTPUT")
225+
212226

213227
class TestHasLocale(SetupConfigs):
214228
"""

libcxx/utils/libcxx/test/dsl.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,20 @@ def _executeScriptInternal(test, commands):
6464
if not os.path.exists(d):
6565
os.makedirs(d)
6666
res = lit.TestRunner.executeScriptInternal(test, litConfig, tmpBase, parsedCommands, execDir)
67-
if isinstance(res, lit.Test.Result):
68-
res = ('', '', 127, None)
69-
return res
67+
if isinstance(res, lit.Test.Result): # Handle failure to parse the Lit test
68+
res = ('', res.output, 127, None)
69+
(out, err, exitCode, timeoutInfo) = res
70+
71+
# TODO: As a temporary workaround until https://reviews.llvm.org/D81892 lands, manually
72+
# split any stderr output that is included in stdout. It shouldn't be there, but
73+
# the Lit internal shell conflates stderr and stdout.
74+
conflatedErrorOutput = re.search("(# command stderr:.+$)", out, flags=re.DOTALL)
75+
if conflatedErrorOutput:
76+
conflatedErrorOutput = conflatedErrorOutput.group(0)
77+
out = out[:-len(conflatedErrorOutput)]
78+
err += conflatedErrorOutput
79+
80+
return (out, err, exitCode, timeoutInfo)
7081

7182
def _makeConfigTest(config, testPrefix=''):
7283
sourceRoot = os.path.join(config.test_exec_root, '__config_src__')
@@ -122,7 +133,7 @@ def programOutput(config, program, args=None, testPrefix=''):
122133
if exitCode != 0:
123134
return None
124135

125-
actualOut = re.search("command output:\n(.+)\n$", out, flags=re.DOTALL)
136+
actualOut = re.search("# command output:\n(.+)\n$", out, flags=re.DOTALL)
126137
actualOut = actualOut.group(1) if actualOut else ""
127138
return actualOut
128139

0 commit comments

Comments
 (0)