from pathlib import Path import re, subprocess, tempfile src=(Path(__file__).resolve().parents[1]/'components/platform/src/lcd_direct.c').read_text() def extract(name): m=re.search(r'static [^;{}]+\b'+name+r'\([^;{}]*\)\s*\{',src) a=m.start();b=src.index('{',a)+1;depth=1 while depth: if src[b]=='{':depth+=1 if src[b]=='}':depth-=1 b+=1 return src[a:b] prefix='''#include #include #include #include #include #define ESP_OK 0 #define ESP_ERR_INVALID_STATE 1 #define LCD_DIRECT_EMOTE_STEP_MS 34U #define LCD_DIRECT_PRESENTATION_WAIT_POLL_MS 20U #define pdMS_TO_TICKS(x) ((x)/10) #define ESP_RETURN_ON_ERROR(expr,...) do {int e=(expr);if(e)return e;}while(0) typedef int esp_err_t; typedef uint32_t TickType_t; static int s_emote_handle, delays, stop_after, locks, unlocks; static bool stop; static int64_t now; static int64_t esp_timer_get_time(void){return now;} static bool lcd_direct_should_stop_idle(void){return stop;} static int gfx_emote_lock(int h){++locks;return 0;} static int gfx_emote_unlock(int h){++unlocks;return 0;} static int lcd_direct_emote_update_hud(bool force,bool *changed){*changed=false;return 0;} static int lcd_direct_emote_refresh(void){return 0;} static void vTaskDelay(TickType_t ticks){assert(ticks>0);now+=ticks*10000;++delays;if(stop_after && delays>=stop_after)stop=true;} ''' test='''int main(void){ for(size_t i=0;i<12;++i){ assert(lcd_direct_emote_step_deadline(123000,i)==123000+(int64_t)(i+1)*34000); now+=13000; assert(lcd_direct_emote_wait_until(lcd_direct_emote_step_deadline(0,i))==0); assert(now>=(int64_t)(i+1)*34000 && now<(int64_t)(i+1)*34000+10000); } int64_t anchored=now; now=0; for(size_t i=0;i<12;++i){now+=13000;assert(lcd_direct_emote_wait(21)==0);} assert(anchored<418000 && now>=480000); now=200000;int before=delays; assert(lcd_direct_emote_wait_until(100000)==0 && now==200000 && delays==before); stop=true;assert(lcd_direct_emote_wait_until(100000)==1); stop=false;stop_after=delays+1;assert(lcd_direct_emote_wait_until(now+100000)==1); assert(locks==unlocks); printf("PASS: fixed deadlines, 10ms tick drift reduction (anchored=%lldus), late/stop handling and paired HUD locks\\n",(long long)anchored); }''' with tempfile.TemporaryDirectory(prefix='emote-timeline-') as tmp: c=Path(tmp)/'test.c';exe=Path(tmp)/'test' c.write_text(prefix+'\n'.join(extract(n) for n in ['lcd_direct_emote_wait_until','lcd_direct_emote_wait','lcd_direct_emote_step_deadline'])+'\n'+test) subprocess.run(['clang','-std=c11','-fsanitize=address,undefined',str(c),'-o',str(exe)],check=True) subprocess.run([str(exe)],check=True)