diff --git a/test/common.py b/test/common.py index 7e2ae12c1f034..106a9f84e8ea8 100644 --- a/test/common.py +++ b/test/common.py @@ -457,13 +457,14 @@ def check_dylink(self): def require_pthreads(self): self.cflags += ['-Wno-pthreads-mem-growth', '-pthread'] - if self.get_setting('MINIMAL_RUNTIME'): - self.skipTest('non-browser pthreads not yet supported with MINIMAL_RUNTIME') - for engine in self.js_engines: - if engine_is_node(engine) or engine_is_bun(engine) or engine_is_deno(engine): - self.require_engine(engine) - return - self.fail('no JS engine found capable of running pthreads') + if not self.is_browser_test(): + if self.get_setting('MINIMAL_RUNTIME'): + self.skipTest('non-browser pthreads not yet supported with MINIMAL_RUNTIME') + for engine in self.js_engines: + if engine_is_node(engine) or engine_is_bun(engine) or engine_is_deno(engine): + self.require_engine(engine) + return + self.fail('no JS engine found capable of running pthreads') def require_v8(self): if 'EMTEST_SKIP_V8' in os.environ: diff --git a/test/decorators.py b/test/decorators.py index e0984078e3ac7..90cd0b3e976c5 100644 --- a/test/decorators.py +++ b/test/decorators.py @@ -252,6 +252,21 @@ def modified(self, *args, **kwargs): return decorated +def also_with_pthreads(f): + assert callable(f) + + @wraps(f) + def decorated(self, threads, *args, **kwargs): + if threads: + self.require_pthreads() + f(self, *args, **kwargs) + + parameterize(decorated, {'': (False,), + 'pthreads': (True,)}) + + return decorated + + def also_with_wasmfs(func): assert callable(func) @@ -594,7 +609,7 @@ def parameterize(func, parameters): test functions. """ prev = getattr(func, '_parameterize', None) - assert not any(p.startswith('_') for p in parameters) + assert not any(p.startswith('_') for p in parameters), 'test variant names should not start with _' if prev: # If we're parameterizing 2nd time, construct a cartesian product for various combinations. func._parameterize = { diff --git a/test/test_browser.py b/test/test_browser.py index 1c636aaef1f62..93c3cce4c2d21 100644 --- a/test/test_browser.py +++ b/test/test_browser.py @@ -49,6 +49,7 @@ also_with_asan, also_with_fetch_streaming, also_with_minimal_runtime, + also_with_pthreads, also_with_wasm2js, also_with_wasmfs, disabled, @@ -181,21 +182,6 @@ def is_jspi(args): return '-sJSPI' in args -def also_with_threads(f): - assert callable(f) - - @wraps(f) - def decorated(self, threads, *args, **kwargs): - if threads: - self.cflags += ['-pthread'] - f(self, *args, **kwargs) - - parameterize(decorated, {'': (False,), - 'pthreads': (True,)}) - - return decorated - - def also_with_proxy_to_pthread(f): assert callable(f) @@ -3676,7 +3662,7 @@ def test_pthread_64bit_atomics(self): self.btest_exit('pthread/test_pthread_64bit_atomics.c', cflags=['-O3', '-pthread', '-sPTHREAD_POOL_SIZE=8']) # Test 64-bit C++11 atomics. - @also_with_threads + @also_with_pthreads @parameterized({ '': ([],), 'O3': (['-O3'],), @@ -3932,7 +3918,7 @@ def test_pthread_sbrk(self, args): # Test that -sABORTING_MALLOC=0 works in both pthreads and non-pthreads # builds. (sbrk fails gracefully) - @also_with_threads + @also_with_pthreads @parameterized({ '': ([],), 'O2': (['-O2'],), @@ -4157,11 +4143,11 @@ def test_wasm_locate_file(self): shutil.move('test.wasm', Path('cdn/test.wasm')) self.run_browser('test.html', '/report_result?0') - @also_with_threads + @also_with_pthreads def test_utf8_textdecoder(self): self.btest_exit('benchmark/benchmark_utf8.c', 0, cflags=['--embed-file', test_file('utf8_corpus.txt') + '@/utf8_corpus.txt']) - @also_with_threads + @also_with_pthreads def test_utf16_textdecoder(self): self.btest_exit('benchmark/benchmark_utf16.cpp', 0, cflags=['--embed-file', test_file('utf16_corpus.txt') + '@/utf16_corpus.txt', '-sEXPORTED_RUNTIME_METHODS=UTF16ToString,stringToUTF16,lengthBytesUTF16']) @@ -5560,7 +5546,7 @@ def test_error_reporting(self): create_file('post.js', 'throw "foo";') self.btest('hello_world.c', cflags=['--post-js=post.js'], expected='exception:foo') - @also_with_threads + @also_with_pthreads @also_with_wasm2js @parameterized({ '': ([],), @@ -5582,7 +5568,7 @@ def test_webpack(self, args): shutil.copy('src/hello.wasm', 'dist/') self.run_browser('dist/index.html', '/report_result?exit:0') - @also_with_threads + @also_with_pthreads @requires_dev_dependency('vite') @parameterized({ '': ([],), @@ -5594,7 +5580,7 @@ def test_vite(self, args): self.run_process(shared.get_npm_cmd('vite') + ['build']) self.run_browser('dist/index.html', '/report_result?exit:0') - @also_with_threads + @also_with_pthreads @requires_dev_dependency('rollup') def test_rollup(self): copytree(test_file('rollup'), '.') diff --git a/test/test_core.py b/test/test_core.py index 1d7a737b50de0..975c3086bc2ee 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -45,6 +45,7 @@ also_with_nodefs, also_with_nodefs_both, also_with_noderawfs, + also_with_pthreads, also_with_standalone_wasm, also_with_wasmfs, also_without_bigint, @@ -6812,16 +6813,10 @@ def test_freetype(self): @no_ubsan('local count too large for VMs') @is_slow_test @also_with_wasmfs - @parameterized({ - '': (False,), - 'pthreads': (True,), - }) - def test_sqlite(self, use_pthreads): + @also_with_pthreads + def test_sqlite(self): if self.get_setting('STRICT'): self.cflags += ['-lstubs'] - if use_pthreads: - self.cflags.append('-pthread') - self.require_pthreads() self.do_run_in_out_file_test('sqlite/test.c', cflags=['-sUSE_SQLITE3']) @needs_make('mingw32-make') @@ -9758,15 +9753,10 @@ def test_esm_integration(self): def test_modularize_instance_hello(self): self.do_core_test('test_hello_world.c', cflags=['-sMODULARIZE=instance', '-Wno-experimental']) - @parameterized({ - '': ([],), - 'pthreads': (['-pthread'],), - }) @no_omit_asm_module_exports('MODULARIZE is not compatible with DECLARE_ASM_MODULE_EXPORTS=0') @no_strict_js('EXPORT_ES6 is not compatible with STRICT_JS') - def test_modularize_instance(self, args): - if args: - self.require_pthreads() + @also_with_pthreads + def test_modularize_instance(self): create_file('library.js', '''\ addToLibrary({ $baz: () => console.log('baz'), @@ -9778,7 +9768,7 @@ def test_modularize_instance(self, args): '-sEXPORTED_RUNTIME_METHODS=baz,addOnExit,HEAP32,runtimeKeepalivePush,runtimeKeepalivePop', '-sEXPORTED_FUNCTIONS=_bar,_main,qux', '--js-library', 'library.js', - '-o', 'modularize_instance.mjs'] + args + self.get_cflags()) + '-o', 'modularize_instance.mjs'] + self.get_cflags()) create_file('runner.mjs', ''' import { strict as assert } from 'assert'; diff --git a/test/test_emrun.py b/test/test_emrun.py index ca43d4393f292..7d80b675824c3 100644 --- a/test/test_emrun.py +++ b/test/test_emrun.py @@ -10,7 +10,7 @@ from browser_common import BrowserCore, get_browser, has_browser from common import EMRUN, RunnerCore, path_from_root, read_file, test_file -from test_browser import also_with_threads +from decorators import also_with_pthreads from tools.shared import EMCC, PIPE @@ -60,7 +60,7 @@ def test_program_arg_separator(self): self.assertContained('error: unrecognized arguments: --foo', err) self.assertContained('remember to add `--` between arguments', err) - @also_with_threads + @also_with_pthreads def test_emrun(self): self.emcc('test_emrun.c', ['--emrun', '-o', 'test_emrun.html']) if not has_browser(): diff --git a/test/test_other.py b/test/test_other.py index 17b2ed2aca90d..3d2d48502e3dd 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -62,6 +62,7 @@ also_with_modularize, also_with_nodefs_both, also_with_noderawfs, + also_with_pthreads, also_with_standalone_wasm, also_with_wasm2js, also_with_wasm64, @@ -15145,22 +15146,17 @@ def test_install(self): self.assertNotExists('newdir/tools/maint/') @requires_node - @parameterized({ - '': ([],), - 'pthreads': (['-pthread'],), - }) + @also_with_pthreads @parameterized({ '': ([],), 'closure': (['--closure=1'],), }) - def test_TextDecoder(self, args1, args2): - self.cflags += args1 + args2 - - self.do_runf('hello_world.c') + def test_TextDecoder(self, args): + self.do_runf('hello_world.c', cflags=args) td_with_fallback = os.path.getsize('hello_world.js') print('td_with_fallback:\t%s' % td_with_fallback) - self.do_runf('hello_world.c', cflags=['-sTEXTDECODER=2']) + self.do_runf('hello_world.c', cflags=args + ['-sTEXTDECODER=2']) td_without_fallback = os.path.getsize('hello_world.js') print('td_without_fallback:\t%s' % td_without_fallback)