From cce3a701889bbc5b107056b0de3fab8d5ce6f885 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Fri, 21 Nov 2025 00:26:51 +0200 Subject: [PATCH 1/4] Add test runner option --log-test-environment, which will introspect and print detailed information about Emscripten tool setup: Emcc, Clang, Binaryen, Node, Python and LLVM. This helps CI maintainers emit info to test run logs of the active setup for reference. --- test/runner.py | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/test/runner.py b/test/runner.py index 127c25a7e4d02..d25708e2847c9 100755 --- a/test/runner.py +++ b/test/runner.py @@ -506,6 +506,7 @@ def parse_args(): 'Useful when combined with --failfast') parser.add_argument('--force64', action='store_true') parser.add_argument('--crossplatform-only', action='store_true') + parser.add_argument('--log-test-environment', action='store_true', help='Prints out detailed information about the current environment. Useful for adding more info to CI test runs.') parser.add_argument('--force-browser-process-termination', action='store_true', help='If true, a fail-safe method is used to ensure that all browser processes are terminated before and after the test suite run. Note that this option will terminate all browser processes, not just those launched by the harness, so will result in loss of all open browsing sessions.') parser.add_argument('--repeat', type=int, default=1, help='Repeat each test N times (default: 1).') @@ -563,6 +564,94 @@ def cleanup_emscripten_temp(): pass +def print_repository_info(directory, repository_name): + import subprocess + current_commit = subprocess.run(['git', 'log', '-n1'], cwd=directory, stdout=subprocess.PIPE, text=True).stdout.strip() + print(f'\n{repository_name} {current_commit}\n') + local_changes = subprocess.run(['git', 'diff'], cwd=directory, stdout=subprocess.PIPE, text=True).stdout.strip() + if local_changes: + print(f'\n{local_changes}\n') + +def log_test_environment(): + """Print detailed information about the current test environment. Useful for + logging test run configuration in a CI.""" + import datetime, re, subprocess + print('======================== Test Setup ========================') + print(f'Test time: {datetime.datetime.now(datetime.timezone.utc).strftime("%A, %B %d, %Y %H:%M:%S %Z")}') + print(f'Python: "{sys.executable}". Version: {sys.version}') + print(f'Emscripten test runner path: "{os.path.realpath(__file__)}"') + + if os.path.isdir(os.path.join(config.EMSCRIPTEN_ROOT, '.git')): + print(f'\nEmscripten repository: "{config.EMSCRIPTEN_ROOT}"') + + emscripten_version = os.path.realpath(os.path.join(config.EMSCRIPTEN_ROOT, 'emscripten-version.txt')) + if os.path.isfile(emscripten_version): + print(f'emscripten-version.txt: {utils.read_file(emscripten_version).strip()}') + + if os.path.isdir(os.path.join(config.EMSCRIPTEN_ROOT, '.git')): + print_repository_info(config.EMSCRIPTEN_ROOT, 'Emscripten') + + print(f'EM_CONFIG: "{config.EM_CONFIG}"') + if os.path.isfile(config.EM_CONFIG): + print(f'\n{utils.read_file(config.EM_CONFIG).strip()}\n') + + node_js_version = subprocess.run(config.NODE_JS + ['--version'], stdout=subprocess.PIPE, text=True).stdout.strip() + print(f'NODE_JS: {config.NODE_JS}. Version: {node_js_version}') + + print(f'BINARYEN_ROOT: {config.BINARYEN_ROOT}') + wasm_opt_version = subprocess.run([os.path.join(config.BINARYEN_ROOT, 'bin', 'wasm-opt.exe'), '--version'], stdout=subprocess.PIPE, text=True).stdout.strip() + print(f'wasm-opt version: {wasm_opt_version}') + + binaryen_git_dir = config.BINARYEN_ROOT + # Detect emsdk directory structure (build root vs source root) + if re.match(r'main_.*_64bit_binaryen', os.path.basename(binaryen_git_dir)): + binaryen_git_dir = os.path.realpath(os.path.join(binaryen_git_dir, '..', 'main')) + if os.path.isdir(os.path.join(binaryen_git_dir, '.git')): + print(f'Binaryen git directory: "{binaryen_git_dir}"') + print_repository_info(binaryen_git_dir, 'Binaryen') + + print(f'LLVM_ROOT: {config.LLVM_ROOT}') + + # Find LLVM git directory in emsdk aware fashion + def find_llvm_git_root(dir): + while True: + if os.path.isdir(os.path.join(dir, ".git")): + return dir + if os.path.isdir(os.path.join(dir, "src", ".git")): + return os.path.join(dir, "src") + if os.path.dirname(dir) == dir: + return None + dir = os.path.dirname(dir) + + llvm_git_root = find_llvm_git_root(config.LLVM_ROOT) + if llvm_git_root: + print(f'LLVM git directory: "{llvm_git_root}"') + print_repository_info(llvm_git_root, 'LLVM') + + clang_version = subprocess.run([shared.CLANG_CC, '--version'], stdout=subprocess.PIPE, text=True).stdout.strip() + print(f'Clang: "{shared.CLANG_CC}"\n{clang_version}\n') + + print(f'EMTEST_BROWSER: {browser_common.EMTEST_BROWSER}') + firefox_version = browser_common.get_firefox_version() + if firefox_version != 2**31 - 1: + print(f'Firefox version: {firefox_version}') + else: + print(f'Not detected as a Firefox browser') + safari_version = browser_common.get_safari_version() + if safari_version != 2**31 - 1: + print(f'Safari version: {safari_version}') + else: + print(f'Not detected as a Safari browser') + + emsdk_dir = os.getenv('EMSDK') + print(f'\nEMSDK: "{emsdk_dir}"') + if emsdk_dir: + if os.path.isdir(os.path.join(emsdk_dir, '.git')): + print_repository_info(emsdk_dir, 'Emsdk') + + print('==================== End of Test Setup =====================') + + def main(): options = parse_args() @@ -606,6 +695,9 @@ def set_env(name, option_value): browser_common.init(options.force_browser_process_termination) + if options.log_test_environment: + log_test_environment() + def prepend_default(arg): if arg.startswith('test_'): return default_core_test_mode + '.' + arg From c6fdc54033e1b08f68884c656009714b4b966698 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Fri, 21 Nov 2025 00:31:43 +0200 Subject: [PATCH 2/4] ruff --- test/runner.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/runner.py b/test/runner.py index d25708e2847c9..f354980102893 100755 --- a/test/runner.py +++ b/test/runner.py @@ -19,6 +19,7 @@ import argparse import atexit +import datetime import fnmatch import glob import logging @@ -26,6 +27,8 @@ import operator import os import random +import re +import subprocess import sys import time import unittest @@ -575,7 +578,6 @@ def print_repository_info(directory, repository_name): def log_test_environment(): """Print detailed information about the current test environment. Useful for logging test run configuration in a CI.""" - import datetime, re, subprocess print('======================== Test Setup ========================') print(f'Test time: {datetime.datetime.now(datetime.timezone.utc).strftime("%A, %B %d, %Y %H:%M:%S %Z")}') print(f'Python: "{sys.executable}". Version: {sys.version}') @@ -636,12 +638,12 @@ def find_llvm_git_root(dir): if firefox_version != 2**31 - 1: print(f'Firefox version: {firefox_version}') else: - print(f'Not detected as a Firefox browser') + print('Not detected as a Firefox browser') safari_version = browser_common.get_safari_version() if safari_version != 2**31 - 1: print(f'Safari version: {safari_version}') else: - print(f'Not detected as a Safari browser') + print('Not detected as a Safari browser') emsdk_dir = os.getenv('EMSDK') print(f'\nEMSDK: "{emsdk_dir}"') From ec96eadb4aca10b2d5190a167774baadd022504a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Fri, 21 Nov 2025 00:34:09 +0200 Subject: [PATCH 3/4] ruffer --- test/runner.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/runner.py b/test/runner.py index f354980102893..e32a225c91790 100755 --- a/test/runner.py +++ b/test/runner.py @@ -575,6 +575,7 @@ def print_repository_info(directory, repository_name): if local_changes: print(f'\n{local_changes}\n') + def log_test_environment(): """Print detailed information about the current test environment. Useful for logging test run configuration in a CI.""" From fc9533f01e6ba96073fb008ccf5c0a44b0ff7faa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Fri, 21 Nov 2025 12:55:02 +0200 Subject: [PATCH 4/4] review --- test/runner.py | 39 ++++++++++++++++++++------------------- tools/building.py | 8 ++++++-- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/test/runner.py b/test/runner.py index e32a225c91790..7a9fe8ee6cb7e 100755 --- a/test/runner.py +++ b/test/runner.py @@ -47,7 +47,7 @@ from common import errlog from single_line_runner import SingleLineTestRunner -from tools import colored_logger, config, shared, utils +from tools import building, colored_logger, config, shared, utils logger = logging.getLogger("runner") @@ -568,10 +568,9 @@ def cleanup_emscripten_temp(): def print_repository_info(directory, repository_name): - import subprocess - current_commit = subprocess.run(['git', 'log', '-n1'], cwd=directory, stdout=subprocess.PIPE, text=True).stdout.strip() + current_commit = utils.run_process(['git', 'show', '--no-patch'], cwd=directory, stdout=subprocess.PIPE, text=True).stdout.strip() print(f'\n{repository_name} {current_commit}\n') - local_changes = subprocess.run(['git', 'diff'], cwd=directory, stdout=subprocess.PIPE, text=True).stdout.strip() + local_changes = utils.run_process(['git', 'diff'], cwd=directory, stdout=subprocess.PIPE, text=True).stdout.strip() if local_changes: print(f'\n{local_changes}\n') @@ -584,25 +583,25 @@ def log_test_environment(): print(f'Python: "{sys.executable}". Version: {sys.version}') print(f'Emscripten test runner path: "{os.path.realpath(__file__)}"') - if os.path.isdir(os.path.join(config.EMSCRIPTEN_ROOT, '.git')): - print(f'\nEmscripten repository: "{config.EMSCRIPTEN_ROOT}"') + if os.path.isdir(os.path.join(__rootpath__, '.git')): + print(f'\nEmscripten repository: "{__rootpath__}"') - emscripten_version = os.path.realpath(os.path.join(config.EMSCRIPTEN_ROOT, 'emscripten-version.txt')) + emscripten_version = utils.path_from_root('emscripten-version.txt') if os.path.isfile(emscripten_version): - print(f'emscripten-version.txt: {utils.read_file(emscripten_version).strip()}') + print(f'emscripten-version.txt: {utils.EMSCRIPTEN_VERSION}') - if os.path.isdir(os.path.join(config.EMSCRIPTEN_ROOT, '.git')): - print_repository_info(config.EMSCRIPTEN_ROOT, 'Emscripten') + if os.path.isdir(os.path.join(__rootpath__, '.git')): + print_repository_info(__rootpath__, 'Emscripten') print(f'EM_CONFIG: "{config.EM_CONFIG}"') if os.path.isfile(config.EM_CONFIG): print(f'\n{utils.read_file(config.EM_CONFIG).strip()}\n') - node_js_version = subprocess.run(config.NODE_JS + ['--version'], stdout=subprocess.PIPE, text=True).stdout.strip() + node_js_version = utils.run_process(config.NODE_JS + ['--version'], stdout=subprocess.PIPE, text=True).stdout.strip() print(f'NODE_JS: {config.NODE_JS}. Version: {node_js_version}') print(f'BINARYEN_ROOT: {config.BINARYEN_ROOT}') - wasm_opt_version = subprocess.run([os.path.join(config.BINARYEN_ROOT, 'bin', 'wasm-opt.exe'), '--version'], stdout=subprocess.PIPE, text=True).stdout.strip() + wasm_opt_version = building.get_binaryen_version(building.get_binaryen_bin()).strip() print(f'wasm-opt version: {wasm_opt_version}') binaryen_git_dir = config.BINARYEN_ROOT @@ -631,20 +630,22 @@ def find_llvm_git_root(dir): print(f'LLVM git directory: "{llvm_git_root}"') print_repository_info(llvm_git_root, 'LLVM') - clang_version = subprocess.run([shared.CLANG_CC, '--version'], stdout=subprocess.PIPE, text=True).stdout.strip() + clang_version = utils.run_process([shared.CLANG_CC, '--version'], stdout=subprocess.PIPE, text=True).stdout.strip() print(f'Clang: "{shared.CLANG_CC}"\n{clang_version}\n') print(f'EMTEST_BROWSER: {browser_common.EMTEST_BROWSER}') - firefox_version = browser_common.get_firefox_version() - if firefox_version != 2**31 - 1: - print(f'Firefox version: {firefox_version}') + if browser_common.is_firefox(): + print(f'Firefox version: {browser_common.get_firefox_version()}') else: print('Not detected as a Firefox browser') - safari_version = browser_common.get_safari_version() - if safari_version != 2**31 - 1: - print(f'Safari version: {safari_version}') + if browser_common.is_safari(): + print(f'Safari version: {browser_common.get_safari_version()}') else: print('Not detected as a Safari browser') + if browser_common.is_chrome(): + print(f'Browser is Chrome.') + else: + print('Not detected as a Chrome browser') emsdk_dir = os.getenv('EMSDK') print(f'\nEMSDK: "{emsdk_dir}"') diff --git a/tools/building.py b/tools/building.py index c1de2a9062ce9..f96eacf5a7711 100644 --- a/tools/building.py +++ b/tools/building.py @@ -1189,14 +1189,18 @@ def get_binaryen_feature_flags(): return ['--detect-features'] -def check_binaryen(bindir): +def get_binaryen_version(bindir): opt = os.path.join(bindir, utils.exe_suffix('wasm-opt')) if not os.path.exists(opt): exit_with_error('binaryen executable not found (%s). Please check your binaryen installation' % opt) try: - output = run_process([opt, '--version'], stdout=PIPE).stdout + return run_process([opt, '--version'], stdout=PIPE).stdout except subprocess.CalledProcessError: exit_with_error('error running binaryen executable (%s). Please check your binaryen installation' % opt) + + +def check_binaryen(bindir): + output = get_binaryen_version(bindir) if output: output = output.splitlines()[0] try: