Files

97 lines
5.2 KiB
JavaScript
Raw Permalink Normal View History

// 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;
}
`);