Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert all remaining wasm worker tests to btest_exit. NFC #22776

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
15 changes: 10 additions & 5 deletions test/atomic/test_wait32_notify.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,16 @@ void run_test() {
// This test run in both wasm workers and pthreads mode
#ifdef __EMSCRIPTEN_WASM_WORKERS__

void do_exit() {
emscripten_out("do_exit");
emscripten_terminate_all_wasm_workers();
emscripten_force_exit(0);
}

void worker_main() {
run_test();

#ifdef REPORT_RESULT
REPORT_RESULT(addr);
#endif
assert(addr == 3);
emscripten_wasm_worker_post_function_v(EMSCRIPTEN_WASM_WORKER_ID_PARENT, do_exit);
}

#else
Expand All @@ -69,7 +73,7 @@ bool main_loop(double time, void *userData) {
// Burn one second to make sure worker finishes its test.
emscripten_out("main: seen worker running");
double t0 = emscripten_performance_now();
while(emscripten_performance_now() < t0 + 1000);
while (emscripten_performance_now() < t0 + 1000);

// Wake the waiter
emscripten_out("main: waking worker");
Expand All @@ -91,6 +95,7 @@ int main() {
static char stack[1024];
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker(stack, sizeof(stack));
emscripten_wasm_worker_post_function_v(worker, worker_main);
emscripten_runtime_keepalive_push();
#else
pthread_create(&t, NULL, thread_main, NULL);
#endif
Expand Down
12 changes: 9 additions & 3 deletions test/atomic/test_wait64_notify.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,16 @@ void run_test() {

char stack[1024];

void do_exit() {
emscripten_out("do_exit");
emscripten_terminate_all_wasm_workers();
emscripten_force_exit(0);
}

void worker_main() {
run_test();
#ifdef REPORT_RESULT
REPORT_RESULT(addr >> 32);
#endif
assert(addr == 0x300000000ull);
emscripten_wasm_worker_post_function_v(EMSCRIPTEN_WASM_WORKER_ID_PARENT, do_exit);
}

#else
Expand Down Expand Up @@ -91,6 +96,7 @@ int main() {
#ifdef __EMSCRIPTEN_WASM_WORKERS__
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker(stack, sizeof(stack));
emscripten_wasm_worker_post_function_v(worker, worker_main);
emscripten_runtime_keepalive_push();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I slightly worry about converting all the tests to this form, as our users may be writing in the simpler way?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I can make this part implicit by having post_function itself keep the runtime alive.

The other part of replacing REPORT_RESULT with normal exit I hope/think is fine.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually post_function doesn't track when job is done so that don't work.

I think the benefit here of making these test runnable under node, along with using a more normal exit-status-based test setup outweighs the downside here of having code that a user might not write. Note that emscripten_runtime_keepalive_push simply does nothing in default build without -sEXIT_RUNTIME since the runtime always stays alive regardless in the default mode.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, maybe we can land just a small subset for now? #22777

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be ok landing the whole thing, so long as we keep one test in the old form (something like a "wasm workers without exit runtime" test).

#else
pthread_create(&t, NULL, thread_main, NULL);
#endif
Expand Down
8 changes: 4 additions & 4 deletions test/atomic/test_wait_async.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,12 @@ void asyncWaitFinishedShouldBeOk(int32_t* ptr,
assert(numCalled == 2);
assert(waitResult == ATOMICS_WAIT_OK);
emscripten_out("test finished");
#ifdef REPORT_RESULT
REPORT_RESULT(0);
#endif
#if !defined(__EMSCRIPTEN_WASM_WORKERS__)
#ifdef __EMSCRIPTEN_WASM_WORKERS__
emscripten_terminate_all_wasm_workers();
#else
pthread_join(t, NULL);
#endif
emscripten_force_exit(0);
}

int main() {
Expand Down
61 changes: 30 additions & 31 deletions test/test_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -5003,7 +5003,7 @@ def test_wasm_worker_hello_embedded(self):
'pthread': (['-pthread'],),
})
def test_wasm_worker_futex_wait(self, args):
self.btest('wasm_worker/wasm_worker_futex_wait.c', expected='0', args=['-sWASM_WORKERS=1', '-sASSERTIONS'] + args)
self.btest_exit('wasm_worker/wasm_worker_futex_wait.c', args=['-sWASM_WORKERS=1', '-sASSERTIONS'] + args)

# Tests Wasm Worker thread stack setup
@also_with_minimal_runtime
Expand All @@ -5013,48 +5013,48 @@ def test_wasm_worker_futex_wait(self, args):
'2': (2,),
})
def test_wasm_worker_thread_stack(self, mode):
self.btest('wasm_worker/thread_stack.c', expected='0', args=['-sWASM_WORKERS', f'-sSTACK_OVERFLOW_CHECK={mode}'])
self.btest_exit('wasm_worker/thread_stack.c', args=['-sWASM_WORKERS', f'-sSTACK_OVERFLOW_CHECK={mode}'])

# Tests emscripten_malloc_wasm_worker() and emscripten_current_thread_is_wasm_worker() functions
@also_with_minimal_runtime
def test_wasm_worker_malloc(self):
self.btest('wasm_worker/malloc_wasm_worker.c', expected='0', args=['-sWASM_WORKERS'])
self.btest_exit('wasm_worker/malloc_wasm_worker.c', args=['-sWASM_WORKERS'])

# Tests Wasm Worker+pthreads simultaneously
@also_with_minimal_runtime
def test_wasm_worker_and_pthreads(self):
self.btest('wasm_worker/wasm_worker_and_pthread.c', expected='0', args=['-sWASM_WORKERS', '-pthread'])
self.btest_exit('wasm_worker/wasm_worker_and_pthread.c', args=['-sWASM_WORKERS', '-pthread'])

# Tests emscripten_wasm_worker_self_id() function
@also_with_minimal_runtime
def test_wasm_worker_self_id(self):
self.btest('wasm_worker/wasm_worker_self_id.c', expected='0', args=['-sWASM_WORKERS'])
self.btest_exit('wasm_worker/wasm_worker_self_id.c', args=['-sWASM_WORKERS'])

# Tests direct Wasm Assembly .S file based TLS variables in Wasm Workers
@also_with_minimal_runtime
def test_wasm_worker_tls_wasm_assembly(self):
self.btest('wasm_worker/wasm_worker_tls_wasm_assembly.c',
expected='42', args=['-sWASM_WORKERS', test_file('wasm_worker/wasm_worker_tls_wasm_assembly.S')])
self.btest_exit('wasm_worker/wasm_worker_tls_wasm_assembly.c',
args=['-sWASM_WORKERS', test_file('wasm_worker/wasm_worker_tls_wasm_assembly.S')])

# Tests C++11 keyword thread_local for TLS in Wasm Workers
@also_with_minimal_runtime
def test_wasm_worker_cpp11_thread_local(self):
self.btest('wasm_worker/cpp11_thread_local.cpp', expected='42', args=['-sWASM_WORKERS'])
self.btest_exit('wasm_worker/cpp11_thread_local.cpp', args=['-sWASM_WORKERS'])

# Tests C11 keyword _Thread_local for TLS in Wasm Workers
@also_with_minimal_runtime
def test_wasm_worker_c11__Thread_local(self):
self.btest('wasm_worker/c11__Thread_local.c', expected='42', args=['-sWASM_WORKERS', '-std=gnu11']) # Cannot test C11 - because of EM_ASM must test Gnu11.
self.btest_exit('wasm_worker/c11__Thread_local.c', args=['-sWASM_WORKERS', '-std=gnu11']) # Cannot test C11 - because of EM_ASM must test Gnu11.

# Tests GCC specific extension keyword __thread for TLS in Wasm Workers
@also_with_minimal_runtime
def test_wasm_worker_gcc___thread(self):
self.btest('wasm_worker/gcc___Thread.c', expected='42', args=['-sWASM_WORKERS', '-std=gnu11'])
self.btest_exit('wasm_worker/gcc___Thread.c', args=['-sWASM_WORKERS', '-std=gnu11'])

# Tests emscripten_wasm_worker_sleep()
@also_with_minimal_runtime
def test_wasm_worker_sleep(self):
self.btest('wasm_worker/wasm_worker_sleep.c', expected='1', args=['-sWASM_WORKERS'])
self.btest_exit('wasm_worker/wasm_worker_sleep.c', args=['-sWASM_WORKERS'])

# Tests emscripten_terminate_wasm_worker()
@also_with_minimal_runtime
Expand All @@ -5064,71 +5064,70 @@ def test_wasm_worker_terminate(self):
# Tests emscripten_terminate_all_wasm_workers()
@also_with_minimal_runtime
def test_wasm_worker_terminate_all(self):
self.set_setting('WASM_WORKERS')
# Test uses the dynCall library function in its EM_ASM code
self.set_setting('DEFAULT_LIBRARY_FUNCS_TO_INCLUDE', ['$dynCall'])
self.btest('wasm_worker/terminate_all_wasm_workers.c', expected='0')
self.btest_exit('wasm_worker/terminate_all_wasm_workers.c', args=['-sWASM_WORKERS'])

# Tests emscripten_wasm_worker_post_function_*() API
@also_with_minimal_runtime
def test_wasm_worker_post_function(self):
self.btest('wasm_worker/post_function.c', expected='8', args=['-sWASM_WORKERS'])
self.btest_exit('wasm_worker/post_function.c', args=['-sWASM_WORKERS'])

# Tests emscripten_wasm_worker_post_function_*() API and EMSCRIPTEN_WASM_WORKER_ID_PARENT
# to send a message back from Worker to its parent thread.
@also_with_minimal_runtime
def test_wasm_worker_post_function_to_main_thread(self):
self.btest('wasm_worker/post_function_to_main_thread.c', expected='10', args=['-sWASM_WORKERS'])
self.btest_exit('wasm_worker/post_function_to_main_thread.c', args=['-sWASM_WORKERS'])

# Tests emscripten_navigator_hardware_concurrency() and emscripten_atomics_is_lock_free()
@also_with_minimal_runtime
def test_wasm_worker_hardware_concurrency_is_lock_free(self):
self.btest('wasm_worker/hardware_concurrency_is_lock_free.c', expected='0', args=['-sWASM_WORKERS'])
self.btest_exit('wasm_worker/hardware_concurrency_is_lock_free.c', args=['-sWASM_WORKERS'])

# Tests emscripten_atomic_wait_u32() and emscripten_atomic_notify() functions.
@also_with_minimal_runtime
def test_wasm_worker_wait32_notify(self):
self.btest('atomic/test_wait32_notify.c', expected='3', args=['-sWASM_WORKERS'])
self.btest_exit('atomic/test_wait32_notify.c', args=['-sWASM_WORKERS'])

# Tests emscripten_atomic_wait_u64() and emscripten_atomic_notify() functions.
@also_with_minimal_runtime
def test_wasm_worker_wait64_notify(self):
self.btest('atomic/test_wait64_notify.c', expected='3', args=['-sWASM_WORKERS'])
self.btest_exit('atomic/test_wait64_notify.c', args=['-sWASM_WORKERS'])

# Tests emscripten_atomic_wait_async() function.
@also_with_minimal_runtime
def test_wasm_worker_wait_async(self):
self.btest('atomic/test_wait_async.c', expected='0', args=['-sWASM_WORKERS'])
self.btest_exit('atomic/test_wait_async.c', args=['-sWASM_WORKERS'])

# Tests emscripten_atomic_cancel_wait_async() function.
@also_with_minimal_runtime
def test_wasm_worker_cancel_wait_async(self):
self.btest('wasm_worker/cancel_wait_async.c', expected='1', args=['-sWASM_WORKERS'])
self.btest_exit('wasm_worker/cancel_wait_async.c', args=['-sWASM_WORKERS'])

# Tests emscripten_atomic_cancel_all_wait_asyncs() function.
@also_with_minimal_runtime
def test_wasm_worker_cancel_all_wait_asyncs(self):
self.btest('wasm_worker/cancel_all_wait_asyncs.c', expected='1', args=['-sWASM_WORKERS'])
self.btest_exit('wasm_worker/cancel_all_wait_asyncs.c', args=['-sWASM_WORKERS'])

# Tests emscripten_atomic_cancel_all_wait_asyncs_at_address() function.
@also_with_minimal_runtime
def test_wasm_worker_cancel_all_wait_asyncs_at_address(self):
self.btest('wasm_worker/cancel_all_wait_asyncs_at_address.c', expected='1', args=['-sWASM_WORKERS'])
self.btest_exit('wasm_worker/cancel_all_wait_asyncs_at_address.c', args=['-sWASM_WORKERS'])

# Tests emscripten_lock_init(), emscripten_lock_waitinf_acquire() and emscripten_lock_release()
@also_with_minimal_runtime
def test_wasm_worker_lock_waitinf(self):
self.btest('wasm_worker/lock_waitinf_acquire.c', expected='4000', args=['-sWASM_WORKERS'])
self.btest_exit('wasm_worker/lock_waitinf_acquire.c', args=['-sWASM_WORKERS'])

# Tests emscripten_lock_wait_acquire() and emscripten_lock_try_acquire() in Worker.
@also_with_minimal_runtime
def test_wasm_worker_lock_wait(self):
self.btest('wasm_worker/lock_wait_acquire.c', expected='0', args=['-sWASM_WORKERS'])
self.btest_exit('wasm_worker/lock_wait_acquire.c', args=['-sWASM_WORKERS'])

# Tests emscripten_lock_wait_acquire() between two Wasm Workers.
@also_with_minimal_runtime
def test_wasm_worker_lock_wait2(self):
self.btest('wasm_worker/lock_wait_acquire2.c', expected='0', args=['-sWASM_WORKERS'])
self.btest_exit('wasm_worker/lock_wait_acquire2.c', args=['-sWASM_WORKERS'])

# Tests emscripten_lock_async_acquire() function.
@also_with_minimal_runtime
Expand All @@ -5138,12 +5137,12 @@ def test_wasm_worker_lock_async_acquire(self):
# Tests emscripten_lock_busyspin_wait_acquire() in Worker and main thread.
@also_with_minimal_runtime
def test_wasm_worker_lock_busyspin_wait(self):
self.btest('wasm_worker/lock_busyspin_wait_acquire.c', expected='0', args=['-sWASM_WORKERS'])
self.btest_exit('wasm_worker/lock_busyspin_wait_acquire.c', args=['-sWASM_WORKERS'])

# Tests emscripten_lock_busyspin_waitinf_acquire() in Worker and main thread.
@also_with_minimal_runtime
def test_wasm_worker_lock_busyspin_waitinf(self):
self.btest('wasm_worker/lock_busyspin_waitinf_acquire.c', expected='1', args=['-sWASM_WORKERS'])
self.btest_exit('wasm_worker/lock_busyspin_waitinf_acquire.c', args=['-sWASM_WORKERS'])

# Tests that proxied JS functions cannot be called from Wasm Workers
@also_with_minimal_runtime
Expand All @@ -5152,18 +5151,18 @@ def test_wasm_worker_no_proxied_js_functions(self):
self.set_setting('ASSERTIONS')
# Test uses the dynCall library function in its EM_ASM code
self.set_setting('DEFAULT_LIBRARY_FUNCS_TO_INCLUDE', ['$dynCall'])
self.btest('wasm_worker/no_proxied_js_functions.c', expected='0',
args=['--js-library', test_file('wasm_worker/no_proxied_js_functions.js')])
self.btest_exit('wasm_worker/no_proxied_js_functions.c',
args=['--js-library', test_file('wasm_worker/no_proxied_js_functions.js')])

# Tests emscripten_semaphore_init(), emscripten_semaphore_waitinf_acquire() and emscripten_semaphore_release()
@also_with_minimal_runtime
def test_wasm_worker_semaphore_waitinf_acquire(self):
self.btest('wasm_worker/semaphore_waitinf_acquire.c', expected='0', args=['-sWASM_WORKERS'])
self.btest_exit('wasm_worker/semaphore_waitinf_acquire.c', args=['-sWASM_WORKERS'])

# Tests emscripten_semaphore_try_acquire() on the main thread
@also_with_minimal_runtime
def test_wasm_worker_semaphore_try_acquire(self):
self.btest('wasm_worker/semaphore_try_acquire.c', expected='0', args=['-sWASM_WORKERS'])
self.btest_exit('wasm_worker/semaphore_try_acquire.c', args=['-sWASM_WORKERS'])

# Tests that calling any proxied function in a Wasm Worker will abort at runtime when ASSERTIONS are enabled.
def test_wasm_worker_proxied_function(self):
Expand Down
7 changes: 0 additions & 7 deletions test/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -9647,23 +9647,16 @@ def test_emscripten_async_load_script(self):
self.run_process([FILE_PACKAGER, 'test.data', '--preload', 'file1.txt', 'file2.txt', '--from-emcc', '--js-output=script2.js'])
self.do_runf('test_emscripten_async_load_script.c', emcc_args=['-sFORCE_FILESYSTEM'])

def prep_wasm_worker_in_node(self):
# Auto exit after 3 seconds in Nodejs environment to get WASM Worker stdout
self.add_pre_run("setTimeout(()=>process.exit(), 3000);")

@node_pthreads
def test_wasm_worker_hello(self):
self.prep_wasm_worker_in_node()
self.do_run_in_out_file_test('wasm_worker/hello_wasm_worker.c', emcc_args=['-sWASM_WORKERS'])

@node_pthreads
def test_wasm_worker_malloc(self):
self.prep_wasm_worker_in_node()
self.do_run_in_out_file_test('wasm_worker/malloc_wasm_worker.c', emcc_args=['-sWASM_WORKERS'])

@node_pthreads
def test_wasm_worker_wait_async(self):
self.prep_wasm_worker_in_node()
self.do_runf('atomic/test_wait_async.c', emcc_args=['-sWASM_WORKERS'])


Expand Down
8 changes: 5 additions & 3 deletions test/wasm_worker/c11__Thread_local.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <emscripten/console.h>
#include <emscripten/emscripten.h>
#include <emscripten/wasm_worker.h>
#include <assert.h>
#include <threads.h>
Expand All @@ -8,9 +9,9 @@ _Thread_local int __attribute__((aligned(64))) tls = 1;
void main_thread_func() {
assert(!emscripten_current_thread_is_wasm_worker());
emscripten_outf("%d", tls);
#ifdef REPORT_RESULT
REPORT_RESULT(tls);
#endif
assert(tls == 42);
emscripten_terminate_all_wasm_workers();
emscripten_force_exit(0);
}

void worker_main() {
Expand All @@ -32,4 +33,5 @@ int main() {
tls = 42;
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker(stack, sizeof(stack));
emscripten_wasm_worker_post_function_v(worker, worker_main);
emscripten_exit_with_live_runtime();
}
6 changes: 3 additions & 3 deletions test/wasm_worker/cancel_all_wait_asyncs.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ void asyncWaitFinishedShouldNotBeCalled(int32_t *ptr, uint32_t val, ATOMICS_WAIT

void asyncWaitFinishedShouldBeCalled(int32_t *ptr, uint32_t val, ATOMICS_WAIT_RESULT_T waitResult, void *userData) {
emscripten_out("asyncWaitFinishedShouldBeCalled");
#ifdef REPORT_RESULT
REPORT_RESULT(testSucceeded);
#endif
assert(testSucceeded);
emscripten_force_exit(0);
}

int main() {
Expand Down Expand Up @@ -70,4 +69,5 @@ int main() {
emscripten_out("Notifying an async wait after value changing should trigger the callback");
numWoken = emscripten_atomic_notify((int32_t*)&addr, EMSCRIPTEN_NOTIFY_ALL_WAITERS);
#endif
emscripten_exit_with_live_runtime();
}
7 changes: 4 additions & 3 deletions test/wasm_worker/cancel_all_wait_asyncs_at_address.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ void asyncWaitFinishedShouldNotBeCalled(int32_t *ptr, uint32_t val, ATOMICS_WAIT

void asyncWaitFinishedShouldBeCalled(int32_t *ptr, uint32_t val, ATOMICS_WAIT_RESULT_T waitResult, void *userData) {
emscripten_out("asyncWaitFinishedShouldBeCalled");
#ifdef REPORT_RESULT
REPORT_RESULT(testSucceeded);
#endif
assert(testSucceeded);
emscripten_force_exit(0);
}

int main() {
Expand Down Expand Up @@ -74,4 +73,6 @@ int main() {
emscripten_out("Notifying an async wait after value changing should trigger the callback");
numWoken = emscripten_atomic_notify((int32_t*)&addr, EMSCRIPTEN_NOTIFY_ALL_WAITERS);
#endif

emscripten_exit_with_live_runtime();
}
6 changes: 3 additions & 3 deletions test/wasm_worker/cancel_wait_async.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ void asyncWaitFinishedShouldNotBeCalled(int32_t *ptr, uint32_t val, ATOMICS_WAIT

void asyncWaitFinishedShouldBeCalled(int32_t *ptr, uint32_t val, ATOMICS_WAIT_RESULT_T waitResult, void *userData) {
emscripten_out("asyncWaitFinishedShouldBeCalled");
#ifdef REPORT_RESULT
REPORT_RESULT(testSucceeded);
#endif
assert(testSucceeded);
emscripten_force_exit(0);
}

int main() {
Expand Down Expand Up @@ -62,4 +61,5 @@ int main() {
emscripten_out("Notifying an async wait after value changing should trigger the callback");
numWoken = emscripten_atomic_notify((int32_t*)&addr, EMSCRIPTEN_NOTIFY_ALL_WAITERS);
#endif
emscripten_exit_with_live_runtime();
}
Loading
Loading