Skip to content

Commit f163dc2

Browse files
authored
[test] Improve stdout/stderr capturing for browser tests. NFC (emscripten-core#24174)
Now you just need to edit one line in browser_reporting.js to have stdout/stderr sent back to the server. This makes debugging issues, especially in headless mode, much simpler. Ideally I'd like to make this even easier (e.g. enabled via a command line flag), but this is a good step in the right direction. I made this change while trying to invesitgate flakiness in `test_sdl_mouse`. The ouput from that test with this logging enabled now looks like this: ``` test_sdl_mouse (test_browser.browser.test_sdl_mouse) ... 127.0.0.1 - - [23/Apr/2025 10:42:49] code 404, message File not found [client stderr: 'motion: abs:10,20 rel:10,20'] [client stderr: 'button down: 1,1 10,20'] [client stderr: 'button up: 1,0 10,20'] [client stderr: 'motion: abs:30,77 rel:20,57'] ok [Browser harness server terminated] ```
1 parent 3b72132 commit f163dc2

File tree

2 files changed

+39
-12
lines changed

2 files changed

+39
-12
lines changed

test/browser_reporting.js

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1+
// Set this to true to have stdout and stderr sent back to the server
2+
var captureStdoutStderr = false;
3+
14
var hasModule = typeof Module === 'object' && Module;
25

36
var reportingURL = 'http://localhost:8888/';
47

58
async function reportResultToServer(result) {
69
if (reportResultToServer.reported) {
710
// Only report one result per test, even if the test misbehaves and tries to report more.
8-
reportErrorToServer(`excessive reported results, sending ${result}, test will fail`);
11+
reportStderrToServer(`excessive reported results, sending ${result}, test will fail`);
912
}
1013
reportResultToServer.reported = true;
1114
if ((typeof ENVIRONMENT_IS_NODE !== 'undefined' && ENVIRONMENT_IS_NODE) || (typeof ENVIRONMENT_IS_AUDIO_WORKLET !== 'undefined' && ENVIRONMENT_IS_AUDIO_WORKLET)) {
@@ -29,14 +32,22 @@ function maybeReportResultToServer(result) {
2932
}
3033
}
3134

32-
function reportErrorToServer(message) {
35+
function reportStderrToServer(message) {
3336
if (typeof ENVIRONMENT_IS_NODE !== 'undefined' && ENVIRONMENT_IS_NODE) {
3437
err(message);
3538
} else {
3639
fetch(`${reportingURL}?stderr=${encodeURIComponent(message)}`);
3740
}
3841
}
3942

43+
function reportStdoutToServer(message) {
44+
if (typeof ENVIRONMENT_IS_NODE !== 'undefined' && ENVIRONMENT_IS_NODE) {
45+
out(message);
46+
} else {
47+
fetch(`${reportingURL}?stdout=${encodeURIComponent(message)}`);
48+
}
49+
}
50+
4051
function reportTopLevelError(e) {
4152
// MINIMAL_RUNTIME doesn't handle exit or call the below onExit handler
4253
// so we detect the exit by parsing the uncaught exception message.
@@ -89,4 +100,19 @@ if (hasModule) {
89100
}
90101
Module['onAbort'].proxy = true;
91102
}
103+
104+
if (captureStdoutStderr) {
105+
const origPrint = Module['print'];
106+
const origPrintErr = Module['printErr'];
107+
108+
Module['print'] = (...args) => {
109+
origPrint?.(...args);
110+
reportStdoutToServer(args.join(' '));
111+
};
112+
113+
Module['printErr'] = (...args) => {
114+
origPrintErr?.(...args);
115+
reportStderrToServer(args.join(' '));
116+
};
117+
}
92118
}

test/common.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2120,7 +2120,9 @@ def do_POST(self):
21202120
print(f'do_POST: unexpected POST: {urlinfo.query}')
21212121

21222122
def do_GET(self):
2123-
if self.path == '/run_harness':
2123+
info = urlparse(self.path)
2124+
query = parse_qs(info.query)
2125+
if info.path == '/run_harness':
21242126
if DEBUG:
21252127
print('[server startup]')
21262128
self.send_response(200)
@@ -2160,18 +2162,17 @@ def do_GET(self):
21602162
self.end_headers()
21612163
self.wfile.write(b'OK')
21622164

2163-
elif 'stdout=' in self.path or 'stderr=' in self.path:
2164-
'''
2165-
To get logging to the console from browser tests, add this to
2166-
print/printErr/the exception handler in src/shell.html:
2167-
2168-
fetch(encodeURI('http://localhost:8888?stdout=' + text));
2169-
'''
2170-
print('[client logging:', unquote_plus(self.path), ']')
2165+
elif info.path == '/' and 'stdout' in query or 'stderr' in query:
2166+
# Logging reported by reportStdoutToServer / reportStderrToServer.
2167+
#
2168+
# To automatically capture stderr/stdout message from browser tests, modify
2169+
# `captureStdoutStderr` in `test/browser_reporting.js`.
2170+
for key, value in query.items():
2171+
print(f"[client {key}: '{value[0]}']")
21712172
self.send_response(200)
21722173
self.send_header('Content-type', 'text/html')
21732174
self.end_headers()
2174-
elif self.path == '/check':
2175+
elif info.path == '/check':
21752176
self.send_response(200)
21762177
self.send_header('Content-type', 'text/html')
21772178
self.end_headers()

0 commit comments

Comments
 (0)