97 lines
5.2 KiB
JavaScript
97 lines
5.2 KiB
JavaScript
// Exercise the production touch debounce and serialized conversation manager.
|
|||
|
|
const fs = require('node:fs'), path = require('node:path');
|
||
|
|
const root = path.resolve(__dirname, '..');
|
||
|
|
const touch = fs.readFileSync(path.join(root, 'main/conv_ai_embedded_kit.c'), 'utf8');
|
||
|
|
const manager = fs.readFileSync(path.join(root, 'components/application/service/conv_service/src/volc_conv_service.c'), 'utf8');
|
||
|
|
function extract(text, first, next) {
|
||
|
|
const a = text.indexOf(first), b = text.indexOf(next, a);
|
||
|
|
if (a < 0 || b < 0) throw new Error('Missing production section: ' + first);
|
||
|
|
return text.slice(a, b);
|
||
|
|
}
|
||
|
|
process.stdout.write(String.raw`
|
||
|
|
#include <assert.h>
|
||
|
|
#include <stdbool.h>
|
||
|
|
#include <stdint.h>
|
||
|
|
#include <stdio.h>
|
||
|
|
typedef uint32_t TickType_t;
|
||
|
|
typedef int aios_ret_t;
|
||
|
|
#define ESP_PLATFORM 1
|
||
|
|
typedef void *TaskHandle_t;
|
||
|
|
typedef struct {int id;} aios_event_t;
|
||
|
|
typedef struct {void *conv_thread_id;} volc_conv_service_manager_t;
|
||
|
|
typedef struct {void *display_handle;} volc_hal_context_t;
|
||
|
|
typedef void *volc_hal_display_t;
|
||
|
|
typedef struct {char name[32];int stack_size,priority,stack_in_ext;} volc_osal_thread_param_t;
|
||
|
|
enum {VOLC_SERVICE_AI_CONVERSATION_START=100,VOLC_SERVICE_AI_CONVERSATION_INTERRUPT,
|
||
|
|
VOLC_SERVICE_AI_CONVERSATION_QUIT,VOLC_SERVICE_AI_CONVERSATION_OVER,VOLC_SERVICE_AI_CONVERSATION_TOGGLE};
|
||
|
|
enum {AIOS_Ret_NotHandled,AIOS_Ret_Handled};
|
||
|
|
#define VOLC_DISPLAY_OBJ_STATUS 0
|
||
|
|
#define VOLC_DISPLAY_TEXT 0
|
||
|
|
#define pdMS_TO_TICKS(x) (x)
|
||
|
|
#define ESP_LOGI(...) ((void)0)
|
||
|
|
static volc_hal_context_t hal;
|
||
|
|
static bool create_fail,publish_fail,hal_missing;
|
||
|
|
static bool standby,wake_accept=true;
|
||
|
|
static unsigned wakes;
|
||
|
|
static bool call_client_standby(void){return standby;}
|
||
|
|
static bool device_control_request_screen_wake(void){if(!wake_accept)return false;wakes++;return true;}
|
||
|
|
static unsigned starts,stops,prepares,resets,events,reaps;
|
||
|
|
static int task_data;
|
||
|
|
static void *handle=&task_data;
|
||
|
|
static volc_conv_service_manager_t state;
|
||
|
|
static volc_hal_context_t *volc_get_global_hal_context(void){return hal_missing?NULL:&hal;}
|
||
|
|
static void volc_hal_display_set_content(void *h,int o,int t,const char *c){(void)h;(void)o;(void)t;(void)c;}
|
||
|
|
static void conv_ai_service_prepare_task(void){prepares++;}
|
||
|
|
static void conv_ai_service_task(void *p){(void)p;}
|
||
|
|
static void conv_ai_service_task_stop(void){stops++;}
|
||
|
|
static void conv_ai_service_diagnostic_reset(void){resets++;}
|
||
|
|
static void volc_osal_thread_destroy(void *h){assert(h==&handle);}
|
||
|
|
static void vTaskDeleteWithCaps(TaskHandle_t h){assert(h==&task_data);reaps++;}
|
||
|
|
static int volc_osal_thread_create(void **h,volc_osal_thread_param_t *p,void (*f)(void*),void *arg){
|
||
|
|
(void)p;(void)f;(void)arg;starts++;if(create_fail)return -1;*h=&handle;return 0;
|
||
|
|
}
|
||
|
|
` + extract(manager, 'static aios_ret_t __state_conversation(', '\nstatic aios_ret_t __state_init(') + String.raw`
|
||
|
|
static int aios_event_pub(int id,void *a,void *b){
|
||
|
|
assert(id==VOLC_SERVICE_AI_CONVERSATION_TOGGLE&&!a&&!b);events++;
|
||
|
|
if(publish_fail)return -1;
|
||
|
|
aios_event_t e={id};assert(__state_conversation(&state,&e)==AIOS_Ret_Handled);return 0;
|
||
|
|
}
|
||
|
|
` + extract(touch, '/* SCREEN_CALL_TAP_BEGIN:', '/* SCREEN_CALL_TAP_END */') + String.raw`
|
||
|
|
int main(void){
|
||
|
|
screen_call_tap(0);assert(starts==1&&prepares==1&&state.conv_thread_id);
|
||
|
|
screen_call_tap(100);screen_call_tap(299);assert(events==1&&!stops);
|
||
|
|
// A second deliberate tap stops even within the former five-second guard.
|
||
|
|
screen_call_tap(300);assert(stops==1&&starts==1&&state.conv_thread_id);
|
||
|
|
// Connecting/stopping retain admission; rapid repeated taps cannot restart.
|
||
|
|
screen_call_tap(600);screen_call_tap(900);assert(stops==3&&starts==1);
|
||
|
|
aios_event_t over={VOLC_SERVICE_AI_CONVERSATION_OVER};
|
||
|
|
__state_conversation(&state,&over);assert(!state.conv_thread_id);
|
||
|
|
screen_call_tap(1200);assert(starts==2&&state.conv_thread_id);
|
||
|
|
aios_event_t quit={VOLC_SERVICE_AI_CONVERSATION_QUIT};
|
||
|
|
__state_conversation(&state,&quit);assert(stops==4&&state.conv_thread_id);
|
||
|
|
__state_conversation(&state,&over);
|
||
|
|
create_fail=true;screen_call_tap(1500);assert(starts==3&&resets==1&&!state.conv_thread_id);
|
||
|
|
create_fail=false;screen_call_tap(1800);assert(starts==4&&state.conv_thread_id);
|
||
|
|
__state_conversation(&state,&over);
|
||
|
|
// Failed event delivery does not consume the debounce window.
|
||
|
|
publish_fail=true;screen_call_tap(2100);assert(starts==4);
|
||
|
|
publish_fail=false;screen_call_tap(2101);assert(starts==5&&state.conv_thread_id);
|
||
|
|
// Unsigned tick rollover preserves the short debounce.
|
||
|
|
screen_call_tap(UINT32_MAX-100);assert(stops==5);
|
||
|
|
screen_call_tap(100);assert(stops==5);
|
||
|
|
screen_call_tap(199);assert(stops==6&&starts==5);
|
||
|
|
assert(reaps==3);
|
||
|
|
// A sleeping screen consumes the tap as wake, never as call toggle.
|
||
|
|
__state_conversation(&state,&over);
|
||
|
|
unsigned old_events=events,old_starts=starts;
|
||
|
|
standby=true;screen_call_tap(500);assert(wakes==1&&events==old_events&&starts==old_starts);
|
||
|
|
standby=false;screen_call_tap(501);assert(events==old_events);
|
||
|
|
screen_call_tap(800);assert(events==old_events+1&&starts==old_starts+1);
|
||
|
|
__state_conversation(&state,&over);
|
||
|
|
standby=true;wake_accept=false;screen_call_tap(1100);assert(wakes==1);
|
||
|
|
wake_accept=true;screen_call_tap(1101);assert(wakes==2&&starts==old_starts+1);
|
||
|
|
puts("PASS screen tap: idle start, second tap hangup at 300ms, connecting/closing admission, repeated stop, OVER reopen, create failure, delivery retry, tick rollover");
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
`);
|