fix(audio): reject stale replies during voice startup
This commit is contained in:
@@ -24,10 +24,11 @@ harness = r'''
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
typedef void *ql_mutex_t;
|
||||
static int g_mic_working, recording, shine_init, fota_start;
|
||||
static int tts_playing, tts_play_status, audio_packet_type, no_speech_timeout;
|
||||
static int queued, disconnected, flags_reset, mutex_locked;
|
||||
static int queued, disconnected, flags_reset, mutex_locked, player_mq_couter, vad_starts;
|
||||
static uint64_t now;
|
||||
static unsigned int gSequenceNumber;
|
||||
static int end_result;
|
||||
@@ -42,6 +43,7 @@ static void vad_set_speech_timeout_flag(int value) { no_speech_timeout = value;
|
||||
static void vad_reset_conversation_flags(void) { no_speech_timeout = 0; flags_reset++; }
|
||||
static int build_random_tts_error_url(char *p, size_t n) { (void)p; (void)n; return 1; }
|
||||
static void add_file_to_play_player_queue(char *p, int type) { (void)p; assert(type == 3); queued++; }
|
||||
static void vad_start_func(void) { vad_starts++; recording = 1; g_mic_working = 0; }
|
||||
static void app_play_tips_file(int n) { (void)n; assert(0); }
|
||||
static int conversation_try_begin(void);
|
||||
static void talkingq_ws_disconnect(void) {
|
||||
@@ -52,7 +54,7 @@ static void talkingq_ws_disconnect(void) {
|
||||
static int sendRecordingAudioPacket(AudioPacket *p) { assert(p->packetType == 2); return end_result; }
|
||||
'''
|
||||
harness += source[state_start:state_end]
|
||||
for name in ['conversation_try_begin', 'sendEndPacket', 'conversation_check_timeout']:
|
||||
for name in ['conversation_try_begin', 'sendEndPacket', 'conversation_check_timeout', 'conversation_accept_voice_message', 'conversation_finish_startup_prompt', 'conversation_find_session_id']:
|
||||
harness += function(name)
|
||||
harness += r'''
|
||||
static void reset(void) {
|
||||
@@ -60,9 +62,16 @@ static void reset(void) {
|
||||
conversation_round = wait_round = sender_round = 0;
|
||||
conversation_wait = WAIT_NONE; timeout_action_busy = round_response_received = 0;
|
||||
queued = disconnected = flags_reset = no_speech_timeout = mutex_locked = 0;
|
||||
now = 1000; end_result = 0;
|
||||
now = 1000; end_result = 0; player_mq_couter = vad_starts = 0; active_session_valid = 0; startup_start_ms = 0; tts_playing = 0;
|
||||
}
|
||||
int main(void) {
|
||||
char id[33];
|
||||
const char *tagged = "PROMPT_SOUND_URL:http://host/26101309423304_EFGHIJKLMNOPQRSTUV.mp3";
|
||||
const char *plain = "PROMPT_SOUND_URL:http://host/tts_error.mp3";
|
||||
assert(conversation_find_session_id(tagged, (unsigned int)strlen(tagged), id));
|
||||
assert(strcmp(id, "26101309423304EFGHIJKLMNOPQRSTUV") == 0);
|
||||
assert(!conversation_find_session_id(plain, (unsigned int)strlen(plain), id));
|
||||
assert(!conversation_find_session_id(tagged, 20, id));
|
||||
/* No confirmed speech: prompt remains, without disconnect or reply wait. */
|
||||
reset(); assert(conversation_try_begin() == 0); g_mic_working = 0;
|
||||
conversation_no_speech(); conversation_check_timeout();
|
||||
@@ -94,7 +103,30 @@ int main(void) {
|
||||
reset(); conversation_no_speech(); conversation_cancel_wait(); conversation_check_timeout(); assert(!queued);
|
||||
reset(); conversation_wait = WAIT_REPLY; wait_round = 9; now += 20000;
|
||||
conversation_check_timeout(); assert(!queued && !disconnected);
|
||||
puts("PASS: no-speech prompt, new-round cancellation, ignored recording keys, END deadline, stale rounds, early reply, send failure, timeout/key race, auto-listening");
|
||||
/* Reproduce ai_active followed by a late untagged backend error. */
|
||||
reset(); active_session_valid = 1; active_session_round = 0;
|
||||
assert(conversation_try_begin() == 0);
|
||||
assert(!conversation_accept_voice_message("PROMPT_SOUND_URL:http://host/tts_error.mp3"));
|
||||
assert(!conversation_accept_voice_message("TTS_START"));
|
||||
assert(conversation_accept_voice_message("NFC_SOUND_URL:http://host/card.mp3"));
|
||||
/* A following queue entry cannot consume the startup action. */
|
||||
player_mq_couter = 1;
|
||||
conversation_finish_startup_prompt(conversation_round, 0);
|
||||
assert(vad_starts == 1 && recording && !g_mic_working);
|
||||
assert(!conversation_accept_voice_message("PROMPT_SOUND_URL:http://host/tts_error.mp3"));
|
||||
active_session_valid = 1; active_session_round = conversation_round;
|
||||
assert(conversation_accept_voice_message("PROMPT_SOUND_URL:http://host/tts_error.mp3"));
|
||||
/* Stale prompt completion must not start another round. */
|
||||
reset(); assert(conversation_try_begin() == 0);
|
||||
conversation_finish_startup_prompt(conversation_round - 1, 0); assert(!vad_starts);
|
||||
conversation_finish_startup_prompt(conversation_round, -1); assert(vad_starts == 1);
|
||||
/* Lost startup releases reservation; active work is never recovered. */
|
||||
reset(); assert(conversation_try_begin() == 0); now += 30001;
|
||||
conversation_check_timeout(); assert(!g_mic_working);
|
||||
assert(conversation_try_begin() == 0);
|
||||
now += 30001; player_mq_couter = 1; conversation_check_timeout(); assert(g_mic_working);
|
||||
player_mq_couter = 0; recording = 1; conversation_check_timeout(); assert(g_mic_working);
|
||||
puts("PASS: late backend error admission, prompt completion with queued audio, stale prompt, failed playback, stalled-startup recovery; no-speech prompt, new-round cancellation, ignored recording keys, END deadline, stale rounds, early reply, send failure, timeout/key race, auto-listening");
|
||||
}
|
||||
'''
|
||||
with tempfile.TemporaryDirectory(prefix='banban-timeout-') as directory:
|
||||
|
||||
Reference in New Issue
Block a user