#!/usr/bin/env python3 """Host regression tests against the real v40 CAN dispatch function; no hardware motion.""" from pathlib import Path import subprocess, tempfile root=Path(__file__).resolve().parents[2] source=(root/'firmware/application/seat_demo_compat.inc').read_text() start=source.index('void SeatDemoCompat_Service(void)') end=source.index('\nvoid SeatDemoCompat_ReleaseAxisForNative',start) service=source[start:end] preamble=r''' #include #include #include #include "ota_can.h" #include "seat_legacy_version_query.h" #define SEAT_DEMO_CAN_COMMAND_ID 0x300 #define SEAT_DEMO_OPCODE_STOP_ALL 9 #define MOTOR_DIRECTION_STOPPED 0 #define SEAT_DEMO_ACK_STOP_ALL_ACCEPTED 1 #define SEAT_DEMO_REJECT_NONE 0 typedef struct { unsigned opcode,motor,direction,sequence; } seat_demo_command_t; static bool seatDemoInitialized=true,seatDemoCalibrationWorker,seatDemoStopAllFromIsr; static unsigned seatDemoServiceDepth,seatDemoStopAllSequenceFromIsr; static bool seatDemoLastSequenceValid,seatDemoLastCommandValid; static unsigned seatDemoSequenceReference=123; static seat_demo_command_t seatDemoLastCommand; static ota_can_frame_t frames[512]; static unsigned frameCount,frameNext,commandCount,thermalFrames,txCount,ackCount; static unsigned dynamicCalls,taskCalls,dispatchCalls,thermalCalls,feedbackCalls; static unsigned commands[512]; static uint32_t Cy_SysLib_EnterCriticalSection(void){return 0;} static void Cy_SysLib_ExitCriticalSection(uint32_t s){(void)s;} void OtaCan_Service(void){} bool OtaCan_PopFrame(ota_can_frame_t *frame){if(frameNext==frameCount)return false;*frame=frames[frameNext++];return true;} bool OtaCan_QueueFrame(uint32_t id,const uint8_t data[8]){(void)id;(void)data;txCount++;return true;} static void SeatDemoCompat_StopNativeOwnersForAll(void){} static void SeatDemoCompat_StopAllInternal(uint16_t s){(void)s;} static void SeatDemoCompat_SetResponse(unsigned a,unsigned b,seat_demo_command_t *c){(void)a;(void)b;(void)c;ackCount++;} static void SeatDemoCompat_HandleCommand(const ota_can_frame_t *f){commands[commandCount++]=f->data[0];seatDemoSequenceReference=f->data[2]|((unsigned)f->data[3]<<8);} static void SeatDemoThermal_HandleFrame(const ota_can_frame_t *f){(void)f;thermalFrames++;} static void SeatDemoDynamic_Service(void){dynamicCalls++;} static void SeatDemoCompat_ServiceTasks(void){taskCalls++;} static void SeatDemoCompat_ServiceDispatcher(void){dispatchCalls++;} static void SeatDemoThermal_Service(void){thermalCalls++;} static void SeatDemoCompat_ServiceFeedback(void){feedbackCalls++;} ''' tests=r''' int main(void){ ota_can_frame_t q={.identifier=0x300,.dlc=8,.data={0x10,0x10,0,0,0,0,0,0}}; assert(!SeatDemo_IsLegacyVersionQuery(NULL)); for(unsigned i=0;i<65536;i++){q.data[2]=i;q.data[3]=i>>8;assert(SeatDemo_IsLegacyVersionQuery(&q));} for(unsigned opcode=0;opcode<256;opcode++){q.data[0]=opcode;assert(SeatDemo_IsLegacyVersionQuery(&q)==(opcode==0x10));} q.data[0]=0x10; for(unsigned i=4;i<8;i++){q.data[i]=1;assert(!SeatDemo_IsLegacyVersionQuery(&q));q.data[i]=0;} q.identifier=0x6a0;assert(!SeatDemo_IsLegacyVersionQuery(&q));q.identifier=0x300; q.dlc=7;assert(!SeatDemo_IsLegacyVersionQuery(&q));q.dlc=8; q.data[1]=0;assert(!SeatDemo_IsLegacyVersionQuery(&q));q.data[1]=0x10; for(unsigned i=0;i<200;i++)frames[frameCount++]=q; SeatDemoCompat_Service(); assert(commandCount==0&&txCount==0&&ackCount==0&&seatDemoSequenceReference==123); assert(dynamicCalls==1&&taskCalls==1&&dispatchCalls==1&&thermalCalls==1&&feedbackCalls==1); assert(seatDemoServiceDepth==0); frameNext=frameCount=0; unsigned ops[]={1,3,9,0x0c,0x0e,0x0f}; for(unsigned i=0;i