Skip to content

Commit 184834f

Browse files
authored
[test] AudioWorklet tests now correctly run and exit (#23695)
All the audio tests in `test_browser.py` (except the mixer) were updated now the CI has audio, specifically: - Tests that require audio were flagged as so (tests that don't are documented) - Tests that currently fail for 2GB and wasm64 were flagged (only tests that play audio fail) - All tests were migrated to `btest_exit()` as previously discussed - (Tests moved `printf` calls to Emscripten's API and not stdio) - All tests were run manually and the audio output verified - All tests were run with `emscripten_force_exit` returning non-zero to verify they failed - All of this was also verified that they're running on a Debian VM without audio to manually check the console for `"Test success"` and other outputs for tests without `requires_sound_hardware` The mixer/AW struct test is a standalone PR in #23659. Fixes: #23131
1 parent 89aca9c commit 184834f

File tree

4 files changed

+46
-32
lines changed

4 files changed

+46
-32
lines changed

test/test_browser.py

+10-5
Original file line numberDiff line numberDiff line change
@@ -5459,7 +5459,6 @@ def test_full_js_library_strict(self):
54595459
# Tests the AudioWorklet demo
54605460
@parameterized({
54615461
'': ([],),
5462-
'memory64': (['-sMEMORY64'],),
54635462
'with_fs': (['--preload-file', test_file('hello_world.c') + '@/'],),
54645463
'closure': (['--closure', '1', '-Oz'],),
54655464
'asyncify': (['-sASYNCIFY'],),
@@ -5471,29 +5470,35 @@ def test_full_js_library_strict(self):
54715470
'es6': (['-sEXPORT_ES6'],),
54725471
'strict': (['-sSTRICT'],),
54735472
})
5473+
@no_wasm64('https://github.com/emscripten-core/emscripten/pull/23508')
5474+
@no_2gb('https://github.com/emscripten-core/emscripten/pull/23508')
54745475
@requires_sound_hardware
54755476
def test_audio_worklet(self, args):
5476-
self.btest_exit('webaudio/audioworklet.c', args=['-sAUDIO_WORKLET', '-sWASM_WORKERS'] + args)
5477+
self.btest_exit('webaudio/audioworklet.c', args=['-sAUDIO_WORKLET', '-sWASM_WORKERS', '-DTEST_AND_EXIT'] + args)
54775478

54785479
# Tests that audioworklets and workers can be used at the same time
5480+
# Note: doesn't need audio hardware (and has no AW code that tests 2GB or wasm64)
54795481
def test_audio_worklet_worker(self):
5480-
self.btest('webaudio/audioworklet_worker.c', args=['-sAUDIO_WORKLET', '-sWASM_WORKERS'], expected='1')
5482+
self.btest_exit('webaudio/audioworklet_worker.c', args=['-sAUDIO_WORKLET', '-sWASM_WORKERS'])
54815483

54825484
# Tests that posting functions between the main thread and the audioworklet thread works
54835485
@parameterized({
54845486
'': ([],),
54855487
'closure': (['--closure', '1', '-Oz'],),
54865488
})
5489+
# Note: doesn't need audio hardware (and has no AW code that tests 2GB or wasm64)
54875490
def test_audio_worklet_post_function(self, args):
5488-
self.btest('webaudio/audioworklet_post_function.c', args=['-sAUDIO_WORKLET', '-sWASM_WORKERS'] + args, expected='1')
5491+
self.btest_exit('webaudio/audioworklet_post_function.c', args=['-sAUDIO_WORKLET', '-sWASM_WORKERS'] + args)
54895492

54905493
@parameterized({
54915494
'': ([],),
54925495
'closure': (['--closure', '1', '-Oz'],),
54935496
})
5497+
@no_wasm64('https://github.com/emscripten-core/emscripten/pull/23508')
5498+
@no_2gb('https://github.com/emscripten-core/emscripten/pull/23508')
54945499
@requires_sound_hardware
54955500
def test_audio_worklet_modularize(self, args):
5496-
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)
5501+
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)
54975502

54985503
# Tests multiple inputs, forcing a larger stack (note: passing BROWSER_TEST is
54995504
# specific to this test to allow it to exit rather than play forever).

test/webaudio/audioworklet.c

+19-13
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
#include <emscripten/webaudio.h>
2-
#include <stdio.h>
3-
#include <stdlib.h>
42
#include <assert.h>
53

64
/* Steps to use Wasm-based AudioWorklets:
@@ -22,16 +20,17 @@
2220
begin to fire.
2321
*/
2422

25-
// REPORT_RESULT is defined when running in Emscripten test harness. You can
26-
// strip these out in your own project.
27-
#ifdef REPORT_RESULT
23+
// TEST_AND_EXIT is defined when running in the Emscripten test harness. You can
24+
// strip these out in your own project (otherwise playback will end quickly).
25+
#ifdef TEST_AND_EXIT
2826
_Thread_local int testTlsVariable = 1;
2927
int lastTlsVariableValueInAudioThread = 1;
3028
#endif
3129

3230
// This function will be called for every fixed-size buffer of audio samples to be processed.
3331
bool ProcessAudio(int numInputs, const AudioSampleFrame *inputs, int numOutputs, AudioSampleFrame *outputs, int numParams, const AudioParamFrame *params, void *userData) {
34-
#ifdef REPORT_RESULT
32+
#ifdef TEST_AND_EXIT
33+
// Only running in the test harness, see main_thread_tls_access()
3534
assert(testTlsVariable == lastTlsVariableValueInAudioThread);
3635
++testTlsVariable;
3736
lastTlsVariableValueInAudioThread = testTlsVariable;
@@ -63,14 +62,15 @@ EM_JS(void, InitHtmlUi, (EMSCRIPTEN_WEBAUDIO_T audioContext), {
6362
};
6463
});
6564

66-
#ifdef REPORT_RESULT
65+
#ifdef TEST_AND_EXIT
6766
bool main_thread_tls_access(double time, void *userData) {
6867
// Try to mess the TLS variable on the main thread, with the expectation that
69-
// it should not change the TLS value on the AudioWorklet thread.
68+
// it should not change the TLS value on the AudioWorklet thread, asserted in
69+
// ProcessAudio().
7070
testTlsVariable = (int)time;
71+
// Exit to the test harness after enough calls to ProcessAudio()
7172
if (lastTlsVariableValueInAudioThread >= 100) {
72-
REPORT_RESULT(0);
73-
return false;
73+
emscripten_force_exit(0);
7474
}
7575
return true;
7676
}
@@ -79,7 +79,7 @@ bool main_thread_tls_access(double time, void *userData) {
7979
// This callback will fire after the Audio Worklet Processor has finished being
8080
// added to the Worklet global scope.
8181
void AudioWorkletProcessorCreated(EMSCRIPTEN_WEBAUDIO_T audioContext, bool success, void *userData) {
82-
if (!success) return;
82+
assert(success && "Stopped in AudioWorkletProcessorCreated");
8383

8484
// Specify the input and output node configurations for the Wasm Audio
8585
// Worklet. A simple setup with single mono output channel here, and no
@@ -97,7 +97,8 @@ void AudioWorkletProcessorCreated(EMSCRIPTEN_WEBAUDIO_T audioContext, bool succe
9797
// Connect the audio worklet node to the graph.
9898
emscripten_audio_node_connect(wasmAudioWorklet, audioContext, 0, 0);
9999

100-
#ifdef REPORT_RESULT
100+
#ifdef TEST_AND_EXIT
101+
// Schedule this to exit after ProcessAudio() has been called 100 times
101102
emscripten_set_timeout_loop(main_thread_tls_access, 10, 0);
102103
#endif
103104

@@ -108,7 +109,7 @@ void AudioWorkletProcessorCreated(EMSCRIPTEN_WEBAUDIO_T audioContext, bool succe
108109
// AudioWorklet global scope, and is now ready to begin adding Audio Worklet
109110
// Processors.
110111
void WebAudioWorkletThreadInitialized(EMSCRIPTEN_WEBAUDIO_T audioContext, bool success, void *userData) {
111-
if (!success) return;
112+
assert(success && "Stopped in WebAudioWorkletThreadInitialized");
112113

113114
WebAudioWorkletProcessorCreateOptions opts = {
114115
.name = "noise-generator",
@@ -132,4 +133,9 @@ int main() {
132133
// and kick off Audio Worklet scope initialization, which shares the Wasm
133134
// Module and Memory to the AudioWorklet scope and initializes its stack.
134135
emscripten_start_wasm_audio_worklet_thread_async(context, wasmAudioWorkletStack, sizeof(wasmAudioWorkletStack), WebAudioWorkletThreadInitialized, 0);
136+
137+
#ifdef TEST_AND_EXIT
138+
// We're in the test harness and exiting is via main_thread_tls_access()
139+
emscripten_exit_with_live_runtime();
140+
#endif
135141
}
+8-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#include <emscripten/webaudio.h>
2-
#include <stdio.h>
32
#include <assert.h>
43

54
// This test showcases posting messages (function calls) between the main thread
@@ -8,25 +7,25 @@
87

98
// This event will fire on the main thread.
109
void MessageReceivedOnMainThread(int d, int e, int f) {
11-
printf("MessageReceivedOnMainThread: d=%d, e=%d, f=%d\n", d, e, f);
10+
emscripten_outf("MessageReceivedOnMainThread: d=%d, e=%d, f=%d", d, e, f);
1211
assert(!emscripten_current_thread_is_audio_worklet());
1312
assert(d == 1 && e == 2 && f == 3);
14-
#ifdef REPORT_RESULT
15-
REPORT_RESULT(1); // test succeeded, were able to post a message from main thread to audio thread and back!
16-
#endif
13+
14+
// test succeeded, were able to post a message from main thread to audio thread and back!
15+
emscripten_force_exit(0);
1716
}
1817

1918
// This event will fire on the audio worklet thread.
2019
void MessageReceivedInAudioWorkletThread(int a, int b) {
21-
printf("MessageReceivedInAudioWorkletThread: a=%d, b=%d\n", a, b);
20+
emscripten_outf("MessageReceivedInAudioWorkletThread: a=%d, b=%d", a, b);
2221
assert(emscripten_current_thread_is_audio_worklet());
2322
assert(a == 42 && b == 9000);
2423
emscripten_audio_worklet_post_function_viii(EMSCRIPTEN_AUDIO_MAIN_THREAD, MessageReceivedOnMainThread, /*d=*/1, /*e=*/2, /*f=*/3);
2524
}
2625

2726
// This callback will fire when the audio worklet thread has been initialized.
2827
void WebAudioWorkletThreadInitialized(EMSCRIPTEN_WEBAUDIO_T audioContext, bool success, void *userData) {
29-
printf("WebAudioWorkletThreadInitialized\n");
28+
emscripten_out("WebAudioWorkletThreadInitialized");
3029
emscripten_audio_worklet_post_function_vii(audioContext, MessageReceivedInAudioWorkletThread, /*a=*/42, /*b=*/9000);
3130
}
3231

@@ -39,4 +38,6 @@ int main() {
3938
// and kick off Audio Worklet scope initialization, which shares the Wasm
4039
// Module and Memory to the AudioWorklet scope and initializes its stack.
4140
emscripten_start_wasm_audio_worklet_thread_async(context, wasmAudioWorkletStack, sizeof(wasmAudioWorkletStack), WebAudioWorkletThreadInitialized, 0);
41+
42+
emscripten_exit_with_live_runtime();
4243
}

test/webaudio/audioworklet_worker.c

+9-7
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
#include <emscripten/webaudio.h>
22
#include <emscripten/wasm_worker.h>
33
#include <emscripten/threading.h>
4-
#include <stdio.h>
5-
#include <stdlib.h>
64
#include <assert.h>
75

86
// Tests that
@@ -13,17 +11,19 @@
1311
int workletToWorkerFutexLocation = 0;
1412
int workletToWorkerFlag = 0;
1513

14+
void do_exit() {
15+
emscripten_terminate_all_wasm_workers();
16+
emscripten_force_exit(0);
17+
}
18+
1619
void run_in_worker() {
1720
while (0 == emscripten_futex_wait(&workletToWorkerFutexLocation, 0, 30000)) {
1821
if (workletToWorkerFlag == 1) {
19-
printf("Test success\n");
22+
emscripten_out("Test success");
23+
emscripten_wasm_worker_post_function_v(EMSCRIPTEN_WASM_WORKER_ID_PARENT, &do_exit);
2024
break;
2125
}
2226
}
23-
24-
#ifdef REPORT_RESULT
25-
REPORT_RESULT(workletToWorkerFlag == 1);
26-
#endif
2727
}
2828

2929
// This event will fire on the audio worklet thread.
@@ -45,4 +45,6 @@ int main() {
4545

4646
EMSCRIPTEN_WEBAUDIO_T context = emscripten_create_audio_context(0);
4747
emscripten_start_wasm_audio_worklet_thread_async(context, wasmAudioWorkletStack, sizeof(wasmAudioWorkletStack), WebAudioWorkletThreadInitialized, 0);
48+
49+
emscripten_exit_with_live_runtime();
4850
}

0 commit comments

Comments
 (0)