Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -874,8 +874,6 @@ jobs:
- upload-test-results
test-bun:
executor: linux-python
environment:
OVERRIDE_NODE_JS_TEST_VERSION: "v24.0.0"
steps:
- checkout
- pip-install
Expand All @@ -884,8 +882,8 @@ jobs:
name: install bun
command: |
curl -fsSL https://bun.com/install | bash
echo "NODE_JS_TEST = os.path.expanduser('~/.bun/bin/bun')" >> ~/emsdk/.emscripten
echo "JS_ENGINES = [NODE_JS_TEST]" >> ~/emsdk/.emscripten
echo "BUN = os.path.expanduser('~/.bun/bin/bun')" >> ~/emsdk/.emscripten
echo "JS_ENGINES = [BUN]" >> ~/emsdk/.emscripten
- run-tests:
test_targets: "
core0.test_hello_world
Expand All @@ -907,6 +905,7 @@ jobs:
- run-tests:
test_targets: "
core0.test_hello_world
core2.test_pthread_create
"
test-jsc:
executor: linux-python
Expand Down
67 changes: 45 additions & 22 deletions test/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,27 @@ def get_output_suffix(args):
return '.js'


def match_engine_executable(engine, name):
basename = os.path.basename(engine[0])
return name in basename


def engine_is_node(engine):
return match_engine_executable(engine, 'node')


def engine_is_v8(engine):
return match_engine_executable(engine, 'd8') or match_engine_executable(engine, 'v8')


def engine_is_deno(engine):
return match_engine_executable(engine, 'deno')


def engine_is_bun(engine):
return match_engine_executable(engine, 'bun')


class RunnerMeta(type):
@classmethod
def make_test(mcs, name, func, suffix, args):
Expand Down Expand Up @@ -362,9 +383,23 @@ def check_dylink(self):

def get_v8(self):
"""Return v8 engine, if one is configured, otherwise None"""
if not config.V8_ENGINE or config.V8_ENGINE not in config.JS_ENGINES:
return None
return config.V8_ENGINE
for engine in config.JS_ENGINES:
if engine_is_v8(engine):
return engine
return None

def require_pthreads(self):
self.setup_pthreads()
for engine in self.js_engines:
if engine_is_node(engine):
self.require_node()
nodejs = self.get_nodejs()
self.node_args += shared.node_pthread_flags(nodejs)
return
elif 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:
Expand All @@ -377,9 +412,10 @@ def require_v8(self):

def get_nodejs(self):
"""Return nodejs engine, if one is configured, otherwise None"""
if config.NODE_JS_TEST not in config.JS_ENGINES:
return None
return config.NODE_JS_TEST
for engine in config.JS_ENGINES:
if engine_is_node(engine):
return engine
return None

def require_node(self):
if 'EMTEST_SKIP_NODE' in os.environ:
Expand All @@ -390,15 +426,6 @@ def require_node(self):
self.require_engine(nodejs)
return nodejs

def get_node_test_version(self, nodejs):
override = os.environ.get('OVERRIDE_NODE_JS_TEST_VERSION')
if override:
override = override.removeprefix('v')
override = override.split('-')[0].split('.')
override = tuple(int(v) for v in override)
return override
return shared.get_node_version(nodejs)

def node_is_canary(self, nodejs):
return nodejs and nodejs[0] and ('canary' in nodejs[0] or 'nightly' in nodejs[0])

Expand Down Expand Up @@ -441,7 +468,7 @@ def try_require_node_version(self, major, minor = 0, revision = 0):
nodejs = self.get_nodejs()
if not nodejs:
self.skipTest('Test requires nodejs to run')
version = self.get_node_test_version(nodejs)
version = shared.get_node_version(nodejs)
if version < (major, minor, revision):
return False

Expand Down Expand Up @@ -559,14 +586,10 @@ def setup_wasmfs_test(self):
self.set_setting('WASMFS')
self.cflags += ['-DWASMFS']

def setup_node_pthreads(self):
self.require_node()
def setup_pthreads(self):
self.cflags += ['-Wno-pthreads-mem-growth', '-pthread']
if self.get_setting('MINIMAL_RUNTIME'):
self.skipTest('node pthreads not yet supported with MINIMAL_RUNTIME')
nodejs = self.get_nodejs()
self.js_engines = [nodejs]
self.node_args += shared.node_pthread_flags(nodejs)

def set_temp_dir(self, temp_dir):
self.temp_dir = temp_dir
Expand Down Expand Up @@ -626,7 +649,7 @@ def setUp(self):

nodejs = self.get_nodejs()
if nodejs:
node_version = self.get_node_test_version(nodejs)
node_version = shared.get_node_version(nodejs)
if node_version < (13, 0, 0):
self.node_args.append('--unhandled-rejections=strict')
elif node_version < (15, 0, 0):
Expand Down
2 changes: 1 addition & 1 deletion test/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ def node_pthreads(func):

@wraps(func)
def decorated(self, *args, **kwargs):
self.setup_node_pthreads()
self.require_pthreads()
return func(self, *args, **kwargs)
return decorated

Expand Down
16 changes: 8 additions & 8 deletions test/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1991,7 +1991,7 @@ def test_em_asm_2(self):
@flaky('https://github.com/emscripten-core/emscripten/issues/25175')
def test_main_thread_em_asm(self, args):
if args:
self.setup_node_pthreads()
self.require_pthreads()
src = read_file(test_file('core/test_em_asm_2.cpp'))
create_file('test.cpp', src.replace('EM_ASM', 'MAIN_THREAD_EM_ASM'))

Expand Down Expand Up @@ -2061,7 +2061,7 @@ def test_em_js(self, args, force_c):
self.check_dylink()
self.cflags += ['-sEXPORTED_FUNCTIONS=_main,_malloc'] + args
if '-pthread' in args:
self.setup_node_pthreads()
self.require_pthreads()

self.do_core_test('test_em_js.cpp', force_c=force_c)
if self.get_setting('WASM_ESM_INTEGRATION'):
Expand Down Expand Up @@ -2742,7 +2742,7 @@ def test_pthread_run_script(self):
self.do_runf('pthread/test_pthread_run_script.c')

# Run the test again with PROXY_TO_PTHREAD
self.setup_node_pthreads()
self.require_pthreads()
self.set_setting('PROXY_TO_PTHREAD')
self.set_setting('EXIT_RUNTIME')
self.do_runf('pthread/test_pthread_run_script.c')
Expand Down Expand Up @@ -2918,7 +2918,7 @@ def test_dlfcn_missing(self):
})
def test_dlfcn_basic(self, args):
if args:
self.setup_node_pthreads()
self.require_pthreads()
self.cflags += args
create_file('libside.cpp', '''
#include <cstdio>
Expand Down Expand Up @@ -6811,7 +6811,7 @@ def test_sqlite(self, use_pthreads):
self.cflags += ['-lstubs']
if use_pthreads:
self.cflags.append('-pthread')
self.setup_node_pthreads()
self.require_pthreads()
self.cflags += ['-sUSE_SQLITE3']
self.do_run_in_out_file_test('sqlite/test.c')

Expand Down Expand Up @@ -9433,7 +9433,7 @@ def test_Module_dynamicLibraries(self, args):
''')

if args:
self.setup_node_pthreads()
self.require_pthreads()

self.dylink_test(
r'''
Expand Down Expand Up @@ -9661,7 +9661,7 @@ def test_poll_blocking(self):
})
def test_pipe_select(self, args):
if args:
self.setup_node_pthreads()
self.require_pthreads()
self.do_runf('core/test_pipe_select.c', cflags=args)

@also_without_bigint
Expand Down Expand Up @@ -9759,7 +9759,7 @@ def test_modularize_instance_hello(self):
@no_strict_js('MODULARIZE is not compatible with STRICT_JS')
def test_modularize_instance(self, args):
if args:
self.setup_node_pthreads()
self.require_pthreads()
create_file('library.js', '''\
addToLibrary({
$baz: () => console.log('baz'),
Expand Down
12 changes: 6 additions & 6 deletions test/test_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -6643,7 +6643,7 @@ def test_ld_library_path(self, args):
if '-pthread' in args:
self.skipTest('Problems with readFile from pthread')
if '-pthread' in args:
self.setup_node_pthreads()
self.require_pthreads()
create_file('hello1_dep.c', r'''
#include <stdio.h>

Expand Down Expand Up @@ -12357,7 +12357,7 @@ def test_gen_struct_info(self):
self.assertFileContents(path_from_root('src/struct_info_generated.json'), read_file('out.json'))

# Same again for wasm64
node_version = self.get_node_test_version(self.get_nodejs())
node_version = shared.get_node_version(self.get_nodejs())
if node_version and node_version >= (14, 0, 0):
self.run_process([PYTHON, path_from_root('tools/gen_struct_info.py'), '--wasm64', '-o', 'out.json'])
self.assertFileContents(path_from_root('src/struct_info_generated_wasm64.json'), read_file('out.json'))
Expand Down Expand Up @@ -12870,7 +12870,7 @@ def test_node_unhandled_rejection(self):
self.build('main.c', cflags=['--pre-js=pre.js', '-sNODEJS_CATCH_REJECTION=0'])
self.assertNotContained('unhandledRejection', read_file('main.js'))

if self.get_node_test_version(self.get_nodejs())[0] >= 15:
if shared.get_node_version(self.get_nodejs())[0] >= 15:
self.skipTest('old behaviour of node JS cannot be tested on node v15 or above')

output = self.run_js('main.js')
Expand All @@ -12881,7 +12881,7 @@ def test_default_pthread_stack_size(self):
self.do_runf('other/test_default_pthread_stack_size.c')

# Same again with pthreads enabled
self.setup_node_pthreads()
self.require_pthreads()
self.do_other_test('test_default_pthread_stack_size.c')

# Same again but with a custom stack size
Expand Down Expand Up @@ -13949,7 +13949,7 @@ def test_parseTools_legacy(self):

@requires_node
def test_min_node_version(self):
node_version = self.get_node_test_version(self.get_nodejs())
node_version = shared.get_node_version(self.get_nodejs())
node_version = '.'.join(str(x) for x in node_version)
self.set_setting('MIN_NODE_VERSION', 300000)
expected = 'This emscripten-generated code requires node v30.0.0 (detected v%s' % node_version
Expand Down Expand Up @@ -14230,7 +14230,7 @@ def test_add_js_function_bigint(self, memory64, wasm_function):
})
def test_preload_module(self, args):
if '-pthread' in args:
self.setup_node_pthreads()
self.require_pthreads()
# TODO(sbc): This test is copyied from test_browser.py. Perhaps find a better way to
# share code between them.
create_file('library.c', r'''
Expand Down