Skip to content

Commit

Permalink
Support separate version of Node.js for running tests. NFC (emscripte…
Browse files Browse the repository at this point in the history
…n-core#20573)

This is needed for emscripten-core#20551 so that we can continue to run tests
under versions of node that are too old to run the compiler.
  • Loading branch information
sbc100 authored Oct 30, 2023
1 parent c551d53 commit bcbfdd4
Show file tree
Hide file tree
Showing 10 changed files with 102 additions and 68 deletions.
4 changes: 2 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ commands:
wget https://nodejs.org/dist/v${version}/node-v${version}-linux-x64.tar.xz
fi
tar xf node-v${version}-linux-x64.tar.xz
echo "NODE_JS = [os.path.expanduser('~/node-v${version}-linux-x64/bin/node')]" >> ~/emsdk/.emscripten
echo "JS_ENGINES = [NODE_JS]" >> ~/emsdk/.emscripten
echo "NODE_JS_TEST = [os.path.expanduser('~/node-v${version}-linux-x64/bin/node')]" >> ~/emsdk/.emscripten
echo "JS_ENGINES = [NODE_JS_TEST]" >> ~/emsdk/.emscripten
echo "if os.path.exists(V8_ENGINE[0]): JS_ENGINES.append(V8_ENGINE)" >> ~/emsdk/.emscripten
cat ~/emsdk/.emscripten
echo "export PATH=\"$HOME/node-v${version}-linux-x64/bin:\$PATH\"" >> $BASH_ENV
Expand Down
2 changes: 1 addition & 1 deletion emcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -748,7 +748,7 @@ def make_js_executable(script):
if settings.MEMORY64 == 1:
cmd += shared.node_memory64_flags()
elif settings.WASM_BIGINT:
cmd += shared.node_bigint_flags()
cmd += shared.node_bigint_flags(config.NODE_JS)
if len(cmd) > 1 or not os.path.isabs(cmd[0]):
# Using -S (--split-string) here means that arguments to the executable are
# correctly parsed. We don't do this by default because old versions of env
Expand Down
2 changes: 1 addition & 1 deletion emcmake.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def has_substr(args, substr):
node_js = [config.NODE_JS[0]]
# In order to allow cmake to run code built with pthreads we need to pass
# some extra flags to node.
node_js += shared.node_pthread_flags()
node_js += shared.node_pthread_flags(config.NODE_JS)
node_js = ';'.join(node_js)
# See https://github.com/emscripten-core/emscripten/issues/15522
args.append(f'-DCMAKE_CROSSCOMPILING_EMULATOR={node_js}')
Expand Down
76 changes: 47 additions & 29 deletions test/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@
WASM_DIS = Path(building.get_binaryen_bin(), 'wasm-dis')
LLVM_OBJDUMP = os.path.expanduser(shared.build_llvm_tool_path(shared.exe_suffix('llvm-objdump')))
PYTHON = sys.executable
if not config.NODE_JS_TEST:
config.NODE_JS_TEST = config.NODE_JS


def test_file(*path_components):
Expand Down Expand Up @@ -318,7 +320,8 @@ def metafunc(self, with_bigint):
if self.get_setting('WASM_BIGINT') is not None:
self.skipTest('redundant in bigint test config')
self.set_setting('WASM_BIGINT')
self.node_args += shared.node_bigint_flags()
nodejs = self.require_node()
self.node_args += shared.node_bigint_flags(nodejs)
f(self)
else:
f(self)
Expand Down Expand Up @@ -382,7 +385,8 @@ def metafunc(self, standalone):
# if we are impure, disallow all wasm engines
if impure:
self.wasm_engines = []
self.node_args += shared.node_bigint_flags()
nodejs = self.require_node()
self.node_args += shared.node_bigint_flags(nodejs)
func(self)

metafunc._parameterize = {'': (False,),
Expand Down Expand Up @@ -614,19 +618,27 @@ def require_v8(self):
self.require_engine(config.V8_ENGINE)
self.emcc_args.append('-sENVIRONMENT=shell')

def get_nodejs(self):
if config.NODE_JS_TEST not in self.js_engines:
return None
return config.NODE_JS_TEST

def require_node(self):
if not config.NODE_JS or config.NODE_JS not in config.JS_ENGINES:
nodejs = self.get_nodejs()
if not nodejs:
if 'EMTEST_SKIP_NODE' in os.environ:
self.skipTest('test requires node and EMTEST_SKIP_NODE is set')
else:
self.fail('node required to run this test. Use EMTEST_SKIP_NODE to skip')
self.require_engine(config.NODE_JS)
self.require_engine(nodejs)
return nodejs

def require_node_canary(self):
if config.NODE_JS or config.NODE_JS in config.JS_ENGINES:
version = shared.check_node_version()
nodejs = self.get_nodejs()
if nodejs:
version = shared.get_node_version(nodejs)
if version >= (20, 0, 0):
self.require_engine(config.NODE_JS)
self.require_engine(nodejs)
return

if 'EMTEST_SKIP_NODE_CANARY' in os.environ:
Expand All @@ -643,10 +655,11 @@ def require_engine(self, engine):
self.wasm_engines = []

def require_wasm64(self):
if config.NODE_JS and config.NODE_JS in self.js_engines:
version = shared.check_node_version()
nodejs = self.get_nodejs()
if nodejs:
version = shared.get_node_version(nodejs)
if version >= (16, 0, 0):
self.js_engines = [config.NODE_JS]
self.js_engines = [nodejs]
self.node_args += shared.node_memory64_flags()
return

Expand All @@ -662,10 +675,11 @@ def require_wasm64(self):
self.fail('either d8 or node >= 16 required to run wasm64 tests. Use EMTEST_SKIP_WASM64 to skip')

def require_simd(self):
if config.NODE_JS and config.NODE_JS in self.js_engines:
version = shared.check_node_version()
nodejs = self.get_nodejs()
if nodejs:
version = shared.get_node_version(nodejs)
if version >= (16, 0, 0):
self.js_engines = [config.NODE_JS]
self.js_engines = [nodejs]
return

if config.V8_ENGINE and config.V8_ENGINE in self.js_engines:
Expand All @@ -679,10 +693,11 @@ def require_simd(self):
self.fail('either d8 or node >= 16 required to run wasm64 tests. Use EMTEST_SKIP_SIMD to skip')

def require_wasm_eh(self):
if config.NODE_JS and config.NODE_JS in self.js_engines:
version = shared.check_node_version()
nodejs = self.get_nodejs()
if nodejs:
version = shared.get_node_version(nodejs)
if version >= (17, 0, 0):
self.js_engines = [config.NODE_JS]
self.js_engines = [nodejs]
return

if config.V8_ENGINE and config.V8_ENGINE in self.js_engines:
Expand All @@ -709,12 +724,13 @@ def require_jspi(self):
return

exp_args = ['--experimental-wasm-stack-switching', '--experimental-wasm-type-reflection']
if config.NODE_JS and config.NODE_JS in self.js_engines:
version = shared.check_node_version()
nodejs = self.get_nodejs()
if nodejs:
version = shared.get_node_version(nodejs)
# Support for JSPI came earlier than 19, but 19 is what currently works
# with emscripten's implementation.
if version >= (19, 0, 0):
self.js_engines = [config.NODE_JS]
self.js_engines = [nodejs]
self.node_args += exp_args
return

Expand All @@ -734,8 +750,9 @@ def setup_node_pthreads(self):
self.emcc_args += ['-Wno-pthreads-mem-growth', '-pthread']
if self.get_setting('MINIMAL_RUNTIME'):
self.skipTest('node pthreads not yet supported with MINIMAL_RUNTIME')
self.js_engines = [config.NODE_JS]
self.node_args += shared.node_pthread_flags()
nodejs = self.get_nodejs()
self.js_engines = [nodejs]
self.node_args += shared.node_pthread_flags(nodejs)

def uses_memory_init_file(self):
if self.get_setting('SIDE_MODULE') or (self.is_wasm() and not self.get_setting('WASM2JS')):
Expand All @@ -761,14 +778,16 @@ def setUpClass(cls):

def setUp(self):
super().setUp()
self.js_engines = config.JS_ENGINES.copy()
self.settings_mods = {}
self.emcc_args = ['-Wclosure', '-Werror', '-Wno-limited-postlink-optimizations']
self.ldflags = []
# Increate stack trace limit to maximise usefulness of test failure reports
self.node_args = ['--stack-trace-limit=50']

node_version = shared.check_node_version()
if node_version:
nodejs = self.get_nodejs()
if nodejs:
node_version = shared.get_node_version(nodejs)
if node_version < (11, 0, 0):
self.node_args.append('--unhandled-rejections=strict')
self.node_args.append('--experimental-wasm-se')
Expand All @@ -795,11 +814,10 @@ def setUp(self):
self.env = {}
self.temp_files_before_run = []
self.uses_es6 = False
self.js_engines = config.JS_ENGINES.copy()
self.required_engine = None
self.wasm_engines = config.WASM_ENGINES.copy()
self.use_all_engines = EMTEST_ALL_ENGINES
if self.js_engines[0] != config.NODE_JS:
if self.js_engines[0] != config.NODE_JS_TEST:
# If our primary JS engine is something other than node then enable
# shell support.
default_envs = 'web,webview,worker,node'
Expand Down Expand Up @@ -943,7 +961,7 @@ def verify_es5(self, filename):
# use --quiet once its available
# See: https://github.com/dollarshaveclub/es-check/pull/126/
es_check_env = os.environ.copy()
es_check_env['PATH'] = os.path.dirname(config.NODE_JS[0]) + os.pathsep + es_check_env['PATH']
es_check_env['PATH'] = os.path.dirname(config.NODE_JS_TEST[0]) + os.pathsep + es_check_env['PATH']
inputfile = os.path.abspath(filename)
# For some reason es-check requires unix paths, even on windows
if WINDOWS:
Expand Down Expand Up @@ -1099,7 +1117,7 @@ def run_js(self, filename, engine=None, args=None,
timeout_error = None
if not engine:
engine = self.js_engines[0]
if engine == config.NODE_JS:
if engine == config.NODE_JS_TEST:
engine = engine + self.node_args
if engine == config.V8_ENGINE:
engine = engine + self.v8_args
Expand Down Expand Up @@ -2111,8 +2129,8 @@ def btest(self, filename, expected=None, reference=None,
if not isinstance(expected, list):
expected = [expected]
if EMTEST_BROWSER == 'node':
self.require_node()
self.node_args += shared.node_pthread_flags()
nodejs = self.require_node()
self.node_args += shared.node_pthread_flags(nodejs)
output = self.run_js('test.js')
self.assertContained('RESULT: ' + expected[0], output)
else:
Expand Down
25 changes: 13 additions & 12 deletions test/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ def test_i64_varargs(self):
def test_i64_invoke_bigint(self):
self.set_setting('WASM_BIGINT')
self.emcc_args += ['-fexceptions']
self.node_args += shared.node_bigint_flags()
self.node_args += shared.node_bigint_flags(self.get_nodejs())
self.do_core_test('test_i64_invoke_bigint.cpp')

def test_vararg_copy(self):
Expand Down Expand Up @@ -2287,7 +2287,7 @@ def test_em_js_i64(self):
self.assertContained('emcc: error: using 64-bit arguments in EM_JS function without WASM_BIGINT is not yet fully supported: `foo`', err)

self.set_setting('WASM_BIGINT')
self.node_args += shared.node_bigint_flags()
self.node_args += shared.node_bigint_flags(self.get_nodejs())
self.do_core_test('test_em_js_i64.c')

def test_em_js_address_taken(self):
Expand Down Expand Up @@ -6392,9 +6392,6 @@ def test_unistd_io(self):
self.emcc_args = orig_compiler_opts + ['-D' + fs]
if fs == 'NODEFS':
self.emcc_args += ['-lnodefs.js']
if config.NODE_JS not in config.JS_ENGINES:
# NODEFS requires node
continue
self.require_node()
if self.get_setting('WASMFS'):
if fs == 'NODEFS':
Expand Down Expand Up @@ -7867,14 +7864,14 @@ def test_embind_dynamic_initialization(self):
def test_embind_i64_val(self):
self.set_setting('WASM_BIGINT')
self.emcc_args += ['-lembind']
self.node_args += shared.node_bigint_flags()
self.node_args += shared.node_bigint_flags(self.get_nodejs())
self.do_run_in_out_file_test('embind/test_i64_val.cpp', assert_identical=True)

@no_wasm2js('wasm_bigint')
def test_embind_i64_binding(self):
self.set_setting('WASM_BIGINT')
self.emcc_args += ['-lembind']
self.node_args += shared.node_bigint_flags()
self.node_args += shared.node_bigint_flags(self.get_nodejs())
self.do_run_in_out_file_test('embind/test_i64_binding.cpp', assert_identical=True)

def test_embind_no_rtti(self):
Expand Down Expand Up @@ -8915,7 +8912,7 @@ def test(assert_returncode=0):
# set us to test in just this engine
self.require_engine(engine)
# tell the compiler to build with just that engine
if engine == config.NODE_JS:
if engine == config.NODE_JS_TEST:
right = 'node'
wrong = 'shell'
else:
Expand Down Expand Up @@ -9888,7 +9885,7 @@ def test_externref(self):
@no_wasm2js('wasm2js does not support reference types')
def test_externref_emjs(self, dynlink):
self.emcc_args += ['-mreference-types']
self.node_args += shared.node_reference_types_flags()
self.node_args += shared.node_reference_types_flags(self.get_nodejs())
if dynlink:
self.set_setting('MAIN_MODULE', 2)
self.do_core_test('test_externref_emjs.c')
Expand Down Expand Up @@ -9961,7 +9958,8 @@ def test_wasm_worker_wait_async(self):
def make_run(name, emcc_args, settings=None, env=None,
require_v8=False, v8_args=None,
require_node=False, node_args=None,
require_wasm64=False):
require_wasm64=False,
init=None):
if env is None:
env = {}
if settings is None:
Expand Down Expand Up @@ -10009,6 +10007,9 @@ def setUp(self):
if require_wasm64:
self.require_wasm64()

if init:
init(self)

TT.setUp = setUp

return TT
Expand Down Expand Up @@ -10047,7 +10048,7 @@ def setUp(self):
# MEMORY64=2, or "lowered"
wasm64l = make_run('wasm64l', emcc_args=['-O1', '-Wno-experimental', '--profiling-funcs'],
settings={'MEMORY64': 2},
node_args=shared.node_bigint_flags())
init=lambda self: shared.node_bigint_flags(self.get_nodejs()))

lto0 = make_run('lto0', emcc_args=['-flto', '-O0'])
lto1 = make_run('lto1', emcc_args=['-flto', '-O1'])
Expand Down Expand Up @@ -10084,7 +10085,7 @@ def setUp(self):
core2ss = make_run('core2ss', emcc_args=['-O2'], settings={'STACK_OVERFLOW_CHECK': 2})

bigint = make_run('bigint', emcc_args=['--profiling-funcs'], settings={'WASM_BIGINT': 1},
node_args=shared.node_bigint_flags())
init=lambda self: shared.node_bigint_flags(self.get_nodejs()))

# Add DEFAULT_TO_CXX=0
strict = make_run('strict', emcc_args=[], settings={'STRICT': 1})
Expand Down
Loading

0 comments on commit bcbfdd4

Please sign in to comment.