diff --git a/test/test_browser.py b/test/test_browser.py index 20fa6eadc142c..cde3d36303232 100644 --- a/test/test_browser.py +++ b/test/test_browser.py @@ -5459,7 +5459,6 @@ def test_full_js_library_strict(self): # Tests the AudioWorklet demo @parameterized({ '': ([],), - 'memory64': (['-sMEMORY64'],), 'with_fs': (['--preload-file', test_file('hello_world.c') + '@/'],), 'closure': (['--closure', '1', '-Oz'],), 'asyncify': (['-sASYNCIFY'],), @@ -5471,29 +5470,35 @@ def test_full_js_library_strict(self): 'es6': (['-sEXPORT_ES6'],), 'strict': (['-sSTRICT'],), }) + @no_wasm64('https://github.com/emscripten-core/emscripten/pull/23508') + @no_2gb('https://github.com/emscripten-core/emscripten/pull/23508') @requires_sound_hardware def test_audio_worklet(self, args): - self.btest_exit('webaudio/audioworklet.c', args=['-sAUDIO_WORKLET', '-sWASM_WORKERS'] + args) + self.btest_exit('webaudio/audioworklet.c', args=['-sAUDIO_WORKLET', '-sWASM_WORKERS', '-DTEST_AND_EXIT'] + args) # Tests that audioworklets and workers can be used at the same time + # Note: doesn't need audio hardware (and has no AW code that tests 2GB or wasm64) def test_audio_worklet_worker(self): - self.btest('webaudio/audioworklet_worker.c', args=['-sAUDIO_WORKLET', '-sWASM_WORKERS'], expected='1') + self.btest_exit('webaudio/audioworklet_worker.c', args=['-sAUDIO_WORKLET', '-sWASM_WORKERS']) # Tests that posting functions between the main thread and the audioworklet thread works @parameterized({ '': ([],), 'closure': (['--closure', '1', '-Oz'],), }) + # Note: doesn't need audio hardware (and has no AW code that tests 2GB or wasm64) def test_audio_worklet_post_function(self, args): - self.btest('webaudio/audioworklet_post_function.c', args=['-sAUDIO_WORKLET', '-sWASM_WORKERS'] + args, expected='1') + self.btest_exit('webaudio/audioworklet_post_function.c', args=['-sAUDIO_WORKLET', '-sWASM_WORKERS'] + args) @parameterized({ '': ([],), 'closure': (['--closure', '1', '-Oz'],), }) + @no_wasm64('https://github.com/emscripten-core/emscripten/pull/23508') + @no_2gb('https://github.com/emscripten-core/emscripten/pull/23508') @requires_sound_hardware def test_audio_worklet_modularize(self, args): - self.btest_exit('webaudio/audioworklet.c', args=['-sAUDIO_WORKLET', '-sWASM_WORKERS', '-sMODULARIZE=1', '-sEXPORT_NAME=MyModule', '--shell-file', test_file('shell_that_launches_modularize.html')] + args) + self.btest_exit('webaudio/audioworklet.c', args=['-sAUDIO_WORKLET', '-sWASM_WORKERS', '-sMODULARIZE=1', '-sEXPORT_NAME=MyModule', '--shell-file', test_file('shell_that_launches_modularize.html'), '-DTEST_AND_EXIT'] + args) # Tests multiple inputs, forcing a larger stack (note: passing BROWSER_TEST is # specific to this test to allow it to exit rather than play forever). diff --git a/test/webaudio/audioworklet.c b/test/webaudio/audioworklet.c index 9b4bdd8a3dd60..964b30ddad5da 100644 --- a/test/webaudio/audioworklet.c +++ b/test/webaudio/audioworklet.c @@ -1,6 +1,4 @@ #include -#include -#include #include /* Steps to use Wasm-based AudioWorklets: @@ -22,16 +20,17 @@ begin to fire. */ -// REPORT_RESULT is defined when running in Emscripten test harness. You can -// strip these out in your own project. -#ifdef REPORT_RESULT +// TEST_AND_EXIT is defined when running in the Emscripten test harness. You can +// strip these out in your own project (otherwise playback will end quickly). +#ifdef TEST_AND_EXIT _Thread_local int testTlsVariable = 1; int lastTlsVariableValueInAudioThread = 1; #endif // This function will be called for every fixed-size buffer of audio samples to be processed. bool ProcessAudio(int numInputs, const AudioSampleFrame *inputs, int numOutputs, AudioSampleFrame *outputs, int numParams, const AudioParamFrame *params, void *userData) { -#ifdef REPORT_RESULT +#ifdef TEST_AND_EXIT + // Only running in the test harness, see main_thread_tls_access() assert(testTlsVariable == lastTlsVariableValueInAudioThread); ++testTlsVariable; lastTlsVariableValueInAudioThread = testTlsVariable; @@ -63,14 +62,15 @@ EM_JS(void, InitHtmlUi, (EMSCRIPTEN_WEBAUDIO_T audioContext), { }; }); -#ifdef REPORT_RESULT +#ifdef TEST_AND_EXIT bool main_thread_tls_access(double time, void *userData) { // Try to mess the TLS variable on the main thread, with the expectation that - // it should not change the TLS value on the AudioWorklet thread. + // it should not change the TLS value on the AudioWorklet thread, asserted in + // ProcessAudio(). testTlsVariable = (int)time; + // Exit to the test harness after enough calls to ProcessAudio() if (lastTlsVariableValueInAudioThread >= 100) { - REPORT_RESULT(0); - return false; + emscripten_force_exit(0); } return true; } @@ -79,7 +79,7 @@ bool main_thread_tls_access(double time, void *userData) { // This callback will fire after the Audio Worklet Processor has finished being // added to the Worklet global scope. void AudioWorkletProcessorCreated(EMSCRIPTEN_WEBAUDIO_T audioContext, bool success, void *userData) { - if (!success) return; + assert(success && "Stopped in AudioWorkletProcessorCreated"); // Specify the input and output node configurations for the Wasm Audio // Worklet. A simple setup with single mono output channel here, and no @@ -97,7 +97,8 @@ void AudioWorkletProcessorCreated(EMSCRIPTEN_WEBAUDIO_T audioContext, bool succe // Connect the audio worklet node to the graph. emscripten_audio_node_connect(wasmAudioWorklet, audioContext, 0, 0); -#ifdef REPORT_RESULT +#ifdef TEST_AND_EXIT + // Schedule this to exit after ProcessAudio() has been called 100 times emscripten_set_timeout_loop(main_thread_tls_access, 10, 0); #endif @@ -108,7 +109,7 @@ void AudioWorkletProcessorCreated(EMSCRIPTEN_WEBAUDIO_T audioContext, bool succe // AudioWorklet global scope, and is now ready to begin adding Audio Worklet // Processors. void WebAudioWorkletThreadInitialized(EMSCRIPTEN_WEBAUDIO_T audioContext, bool success, void *userData) { - if (!success) return; + assert(success && "Stopped in WebAudioWorkletThreadInitialized"); WebAudioWorkletProcessorCreateOptions opts = { .name = "noise-generator", @@ -132,4 +133,9 @@ int main() { // and kick off Audio Worklet scope initialization, which shares the Wasm // Module and Memory to the AudioWorklet scope and initializes its stack. emscripten_start_wasm_audio_worklet_thread_async(context, wasmAudioWorkletStack, sizeof(wasmAudioWorkletStack), WebAudioWorkletThreadInitialized, 0); + +#ifdef TEST_AND_EXIT + // We're in the test harness and exiting is via main_thread_tls_access() + emscripten_exit_with_live_runtime(); +#endif } diff --git a/test/webaudio/audioworklet_post_function.c b/test/webaudio/audioworklet_post_function.c index caabd1f45c599..1b7ed61aec013 100644 --- a/test/webaudio/audioworklet_post_function.c +++ b/test/webaudio/audioworklet_post_function.c @@ -1,5 +1,4 @@ #include -#include #include // This test showcases posting messages (function calls) between the main thread @@ -8,17 +7,17 @@ // This event will fire on the main thread. void MessageReceivedOnMainThread(int d, int e, int f) { - printf("MessageReceivedOnMainThread: d=%d, e=%d, f=%d\n", d, e, f); + emscripten_outf("MessageReceivedOnMainThread: d=%d, e=%d, f=%d", d, e, f); assert(!emscripten_current_thread_is_audio_worklet()); assert(d == 1 && e == 2 && f == 3); -#ifdef REPORT_RESULT - REPORT_RESULT(1); // test succeeded, were able to post a message from main thread to audio thread and back! -#endif + + // test succeeded, were able to post a message from main thread to audio thread and back! + emscripten_force_exit(0); } // This event will fire on the audio worklet thread. void MessageReceivedInAudioWorkletThread(int a, int b) { - printf("MessageReceivedInAudioWorkletThread: a=%d, b=%d\n", a, b); + emscripten_outf("MessageReceivedInAudioWorkletThread: a=%d, b=%d", a, b); assert(emscripten_current_thread_is_audio_worklet()); assert(a == 42 && b == 9000); emscripten_audio_worklet_post_function_viii(EMSCRIPTEN_AUDIO_MAIN_THREAD, MessageReceivedOnMainThread, /*d=*/1, /*e=*/2, /*f=*/3); @@ -26,7 +25,7 @@ void MessageReceivedInAudioWorkletThread(int a, int b) { // This callback will fire when the audio worklet thread has been initialized. void WebAudioWorkletThreadInitialized(EMSCRIPTEN_WEBAUDIO_T audioContext, bool success, void *userData) { - printf("WebAudioWorkletThreadInitialized\n"); + emscripten_out("WebAudioWorkletThreadInitialized"); emscripten_audio_worklet_post_function_vii(audioContext, MessageReceivedInAudioWorkletThread, /*a=*/42, /*b=*/9000); } @@ -39,4 +38,6 @@ int main() { // and kick off Audio Worklet scope initialization, which shares the Wasm // Module and Memory to the AudioWorklet scope and initializes its stack. emscripten_start_wasm_audio_worklet_thread_async(context, wasmAudioWorkletStack, sizeof(wasmAudioWorkletStack), WebAudioWorkletThreadInitialized, 0); + + emscripten_exit_with_live_runtime(); } diff --git a/test/webaudio/audioworklet_worker.c b/test/webaudio/audioworklet_worker.c index b7394f86035b7..4511ebf6ece16 100644 --- a/test/webaudio/audioworklet_worker.c +++ b/test/webaudio/audioworklet_worker.c @@ -1,8 +1,6 @@ #include #include #include -#include -#include #include // Tests that @@ -13,17 +11,19 @@ int workletToWorkerFutexLocation = 0; int workletToWorkerFlag = 0; +void do_exit() { + emscripten_terminate_all_wasm_workers(); + emscripten_force_exit(0); +} + void run_in_worker() { while (0 == emscripten_futex_wait(&workletToWorkerFutexLocation, 0, 30000)) { if (workletToWorkerFlag == 1) { - printf("Test success\n"); + emscripten_out("Test success"); + emscripten_wasm_worker_post_function_v(EMSCRIPTEN_WASM_WORKER_ID_PARENT, &do_exit); break; } } - -#ifdef REPORT_RESULT - REPORT_RESULT(workletToWorkerFlag == 1); -#endif } // This event will fire on the audio worklet thread. @@ -45,4 +45,6 @@ int main() { EMSCRIPTEN_WEBAUDIO_T context = emscripten_create_audio_context(0); emscripten_start_wasm_audio_worklet_thread_async(context, wasmAudioWorkletStack, sizeof(wasmAudioWorkletStack), WebAudioWorkletThreadInitialized, 0); + + emscripten_exit_with_live_runtime(); }