Skip to content

Commit b9ebd4d

Browse files
authored
Extend EMTEST_AUTOSKIP=0/1 to cover Wasm EH and Wasm Legacy EH tests (#25723)
Extend EMTEST_AUTOSKIP=0/1 to cover Wasm EH and Wasm Legacy EH tests, e.g. in browser.test_sdl2_image_formats* tests. This allows old Firefox and Safari test runs to skip over these tests automatically.
1 parent ad83c1b commit b9ebd4d

File tree

2 files changed

+86
-69
lines changed

2 files changed

+86
-69
lines changed

test/common.py

Lines changed: 82 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import json
1111
import logging
1212
import os
13+
import plistlib
1314
import queue
1415
import re
1516
import shlex
@@ -38,11 +39,13 @@
3839
from retryable_unittest import RetryableTestCase
3940

4041
from tools import building, config, feature_matrix, shared, utils
42+
from tools.feature_matrix import UNSUPPORTED, Feature, min_browser_versions
4143
from tools.settings import COMPILE_TIME_SETTINGS
4244
from tools.shared import DEBUG, EMCC, EMXX, get_canonical_temp_dir, path_from_root
4345
from tools.utils import (
4446
WINDOWS,
4547
exit_with_error,
48+
memoize,
4649
read_binary,
4750
read_file,
4851
write_binary,
@@ -108,6 +111,67 @@
108111
browser_spawn_lock_filename = os.path.join(path_from_root('out/browser_spawn_lock'))
109112

110113

114+
@memoize
115+
def get_safari_version():
116+
if not is_safari():
117+
return UNSUPPORTED
118+
plist_path = os.path.join(EMTEST_BROWSER.strip(), 'Contents', 'version.plist')
119+
version_str = plistlib.load(open(plist_path, 'rb')).get('CFBundleShortVersionString')
120+
# Split into parts (major.minor.patch)
121+
parts = (version_str.split('.') + ['0', '0', '0'])[:3]
122+
# Convert each part into integers, discarding any trailing string, e.g. '13a' -> 13.
123+
parts = [int(re.match(r"\d+", s).group()) if re.match(r"\d+", s) else 0 for s in parts]
124+
# Return version as XXYYZZ
125+
return parts[0] * 10000 + parts[1] * 100 + parts[2]
126+
127+
128+
@memoize
129+
def get_firefox_version():
130+
if not is_firefox():
131+
return UNSUPPORTED
132+
exe_path = shlex.split(EMTEST_BROWSER)[0]
133+
ini_path = os.path.join(os.path.dirname(exe_path), "platform.ini")
134+
# Extract the first numeric part before any dot (e.g. "Milestone=102.15.1" → 102)
135+
m = re.search(r"^Milestone=(.*)$", open(ini_path).read(), re.MULTILINE)
136+
milestone = m.group(1).strip()
137+
version = int(re.match(r"(\d+)", milestone).group(1))
138+
# On Nightly and Beta, e.g. 145.0a1, pretend it to still mean version 144,
139+
# since it is a pre-release version
140+
if any(c in milestone for c in ('a', 'b')):
141+
version -= 1
142+
return version
143+
144+
145+
def browser_should_skip_feature(skip_env_var, feature):
146+
# If an env. var. EMTEST_LACKS_x to skip the given test is set (to either
147+
# value 0 or 1), don't bother checking if current browser supports the feature
148+
# - just unconditionally run the test, or skip the test.
149+
if os.getenv(skip_env_var) is not None:
150+
return int(os.getenv(skip_env_var)) != 0
151+
152+
# If there is no Feature object associated with this capability, then we
153+
# should run the test.
154+
if feature is None:
155+
return False
156+
157+
# If EMTEST_AUTOSKIP=0, also never skip.
158+
if os.getenv('EMTEST_AUTOSKIP') == '0':
159+
return False
160+
161+
# Otherwise EMTEST_AUTOSKIP=1 or EMTEST_AUTOSKIP is not set: check whether
162+
# the current browser supports the test or not.
163+
min_required = min_browser_versions[feature]
164+
not_supported = get_firefox_version() < min_required['firefox'] or get_safari_version() < min_required['safari']
165+
166+
# Current browser does not support the test, and EMTEST_AUTOSKIP is not set?
167+
# Then error out to have end user decide what to do in this situation.
168+
if not_supported and os.getenv('EMTEST_AUTOSKIP') is None:
169+
return 'error'
170+
171+
# Report whether to skip the test based on browser support.
172+
return not_supported
173+
174+
111175
# Default flags used to run browsers in CI testing:
112176
class ChromeConfig:
113177
data_dir_flag = '--user-data-dir='
@@ -613,8 +677,16 @@ def require_simd(self):
613677
def require_wasm_legacy_eh(self):
614678
if 'EMTEST_SKIP_WASM_LEGACY_EH' in os.environ:
615679
self.skipTest('test requires node >= 17 or d8 (and EMTEST_SKIP_WASM_LEGACY_EH is set)')
616-
617680
self.set_setting('WASM_LEGACY_EXCEPTIONS')
681+
682+
if self.is_browser_test():
683+
skip = browser_should_skip_feature('EMTEST_SKIP_WASM_LEGACY_EH', Feature.WASM_LEGACY_EXCEPTIONS)
684+
if skip == 'error':
685+
self.fail('test requires Wasm Legacy EH')
686+
elif skip:
687+
self.skipTest('test requires Wasm Legacy EH')
688+
return
689+
618690
if self.try_require_node_version(17):
619691
return
620692

@@ -630,11 +702,17 @@ def require_wasm_eh(self):
630702
if 'EMTEST_SKIP_WASM_EH' in os.environ:
631703
self.skipTest('test requires node v24 or d8 (and EMTEST_SKIP_WASM_EH is set)')
632704
self.set_setting('WASM_LEGACY_EXCEPTIONS', 0)
633-
if self.try_require_node_version(22):
634-
self.node_args.append('--experimental-wasm-exnref')
635-
return
636705

637706
if self.is_browser_test():
707+
skip = browser_should_skip_feature('EMTEST_SKIP_WASM_EH', Feature.WASM_EXCEPTIONS)
708+
if skip == 'error':
709+
self.fail('test requires Wasm EH')
710+
elif skip:
711+
self.skipTest('test requires Wasm EH')
712+
return
713+
714+
if self.try_require_node_version(22):
715+
self.node_args.append('--experimental-wasm-exnref')
638716
return
639717

640718
v8 = self.get_v8()

test/test_browser.py

Lines changed: 4 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55

66
import argparse
77
import os
8-
import plistlib
98
import random
10-
import re
119
import shlex
1210
import shutil
1311
import subprocess
@@ -32,10 +30,12 @@
3230
HttpServerThread,
3331
Reporting,
3432
RunnerCore,
33+
browser_should_skip_feature,
3534
copytree,
3635
create_file,
3736
ensure_dir,
3837
find_browser_test_file,
38+
get_safari_version,
3939
has_browser,
4040
is_chrome,
4141
is_firefox,
@@ -64,9 +64,9 @@
6464
)
6565

6666
from tools import ports, shared
67-
from tools.feature_matrix import UNSUPPORTED, Feature, min_browser_versions
67+
from tools.feature_matrix import Feature
6868
from tools.shared import DEBUG, EMCC, FILE_PACKAGER, PIPE, WINDOWS
69-
from tools.utils import delete_dir, memoize
69+
from tools.utils import delete_dir
7070

7171

7272
def make_test_chunked_synchronous_xhr_server(support_byte_ranges, data, port):
@@ -180,37 +180,6 @@ def is_swiftshader(_):
180180
return is_chrome() and '--use-gl=swiftshader' in common.EMTEST_BROWSER
181181

182182

183-
@memoize
184-
def get_safari_version():
185-
if not is_safari():
186-
return UNSUPPORTED
187-
plist_path = os.path.join(common.EMTEST_BROWSER.strip(), 'Contents', 'version.plist')
188-
version_str = plistlib.load(open(plist_path, 'rb')).get('CFBundleShortVersionString')
189-
# Split into parts (major.minor.patch)
190-
parts = (version_str.split('.') + ['0', '0', '0'])[:3]
191-
# Convert each part into integers, discarding any trailing string, e.g. '13a' -> 13.
192-
parts = [int(re.match(r"\d+", s).group()) if re.match(r"\d+", s) else 0 for s in parts]
193-
# Return version as XXYYZZ
194-
return parts[0] * 10000 + parts[1] * 100 + parts[2]
195-
196-
197-
@memoize
198-
def get_firefox_version():
199-
if not is_firefox():
200-
return UNSUPPORTED
201-
exe_path = shlex.split(common.EMTEST_BROWSER)[0]
202-
ini_path = os.path.join(os.path.dirname(exe_path), "platform.ini")
203-
# Extract the first numeric part before any dot (e.g. "Milestone=102.15.1" → 102)
204-
m = re.search(r"^Milestone=(.*)$", open(ini_path).read(), re.MULTILINE)
205-
milestone = m.group(1).strip()
206-
version = int(re.match(r"(\d+)", milestone).group(1))
207-
# On Nightly and Beta, e.g. 145.0a1, pretend it to still mean version 144,
208-
# since it is a pre-release version
209-
if any(c in milestone for c in ('a', 'b')):
210-
version -= 1
211-
return version
212-
213-
214183
no_swiftshader = skip_if_simple('not compatible with swiftshader', is_swiftshader)
215184

216185
no_chrome = skip_if('no_chrome', lambda _: is_chrome(), 'chrome is not supported')
@@ -251,36 +220,6 @@ def decorated(self, threads, *args, **kwargs):
251220
return decorated
252221

253222

254-
def browser_should_skip_feature(skip_env_var, feature):
255-
# If an env. var. EMTEST_LACKS_x to skip the given test is set (to either
256-
# value 0 or 1), don't bother checking if current browser supports the feature
257-
# - just unconditionally run the test, or skip the test.
258-
if os.getenv(skip_env_var) is not None:
259-
return int(os.getenv(skip_env_var)) != 0
260-
261-
# If there is no Feature object associated with this capability, then we
262-
# should run the test.
263-
if feature is None:
264-
return False
265-
266-
# If EMTEST_AUTOSKIP=0, also never skip.
267-
if os.getenv('EMTEST_AUTOSKIP') == '0':
268-
return False
269-
270-
# Otherwise EMTEST_AUTOSKIP=1 or EMTEST_AUTOSKIP is not set: check whether
271-
# the current browser supports the test or not.
272-
min_required = min_browser_versions[feature]
273-
not_supported = get_firefox_version() < min_required['firefox'] or get_safari_version() < min_required['safari']
274-
275-
# Current browser does not support the test, and EMTEST_AUTOSKIP is not set?
276-
# Then error out to have end user decide what to do in this situation.
277-
if not_supported and os.getenv('EMTEST_AUTOSKIP') is None:
278-
return 'error'
279-
280-
# Report whether to skip the test based on browser support.
281-
return not_supported
282-
283-
284223
def skipIfFeatureNotAvailable(skip_env_var, feature, message):
285224
for env_var in skip_env_var if type(skip_env_var) == list else [skip_env_var]:
286225
should_skip = browser_should_skip_feature(env_var, feature)

0 commit comments

Comments
 (0)