diff --git a/test/runner.py b/test/runner.py index 127c25a7e4d02..7a9fe8ee6cb7e 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 @@ -44,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") @@ -506,6 +509,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 +567,95 @@ def cleanup_emscripten_temp(): pass +def print_repository_info(directory, repository_name): + 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 = utils.run_process(['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.""" + 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(__rootpath__, '.git')): + print(f'\nEmscripten repository: "{__rootpath__}"') + + emscripten_version = utils.path_from_root('emscripten-version.txt') + if os.path.isfile(emscripten_version): + print(f'emscripten-version.txt: {utils.EMSCRIPTEN_VERSION}') + + 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 = 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 = building.get_binaryen_version(building.get_binaryen_bin()).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 = 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}') + if browser_common.is_firefox(): + print(f'Firefox version: {browser_common.get_firefox_version()}') + else: + print('Not detected as a Firefox browser') + 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}"') + 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 +699,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 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: