83 lines
4.6 KiB
Python
83 lines
4.6 KiB
Python
#!/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 <assert.h>
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#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<sizeof(ops)/sizeof(*ops);i++){
|
|
frames[frameCount++]=q;
|
|
ota_can_frame_t command=q;command.data[0]=ops[i];command.data[2]=i+1;command.data[3]=0;
|
|
frames[frameCount++]=command;
|
|
}
|
|
ota_can_frame_t thermal=q;thermal.identifier=0x29e;frames[frameCount++]=thermal;
|
|
SeatDemoCompat_Service();
|
|
assert(commandCount==6&&thermalFrames==1&&seatDemoSequenceReference==6&&txCount==0);
|
|
for(unsigned i=0;i<6;i++)assert(commands[i]==ops[i]);
|
|
assert(dynamicCalls==2&&taskCalls==2&&dispatchCalls==2&&thermalCalls==2&&feedbackCalls==2);
|
|
puts("PASS: 65536 legacy query sequences ignored; no query TX/ACK/sequence changes; mixed motion/STOP/dynamic/thermal frames retain routing and feedback service");
|
|
}
|
|
'''
|
|
with tempfile.TemporaryDirectory(prefix='n7-v40-query-') as tmp:
|
|
c=Path(tmp)/'test.c';exe=Path(tmp)/'test'
|
|
c.write_text(preamble+service+tests)
|
|
subprocess.run(['gcc','-std=c11','-Wall','-Wextra','-Werror','-I'+str(root/'firmware/bootloader/src'),'-I'+str(root/'firmware/application'),str(c),'-o',str(exe)],check=True)
|
|
subprocess.run([str(exe)],check=True)
|