from pathlib import Path
import subprocess
R=Path(__file__).resolve().parent;T=R/'firmware/固件/lamp_target';O=R/'adc_host_test';O.mkdir(exist_ok=True)
(O/'stm32g0xx.h').write_text('''#include "stm32g030xx.h"
#undef GPIOA
#undef RCC
#undef ADC1
#undef ADC1_COMMON
extern GPIO_TypeDef a;
extern RCC_TypeDef r;
extern ADC_TypeDef adc;
extern ADC_Common_TypeDef common;
#define GPIOA (&a)
#define RCC (&r)
#define ADC1 (&adc)
#define ADC1_COMMON (&common)
void test_clear_flags(uint32_t flags);
void test_set_channel(uint32_t mask);
''')
s=(T/'src/lamp_adc.c').read_text()
# Instrument only hardware write semantics: W1C and channel configuration event.
s=s.replace('ADC1->ISR=flags;', 'test_clear_flags(flags);')
s=s.replace('ADC1->CHSELR=1u<<channels[slot];','test_set_channel(1u<<channels[slot]);')
flags=['cc','-std=c11','-Wall','-Wextra','-Werror','-pedantic','-g','-fsanitize=address,undefined','-DSTM32G030xx','-I'+str(O),'-I'+str(T/'include'),'-I'+str(T/'Device/Include'),'-I'+str(T/'CMSIS/Core/Include')]
for name,source in [('actual',s),('premature_start',s.replace('if((ADC1->ISR & ADC_ISR_CCRDY)!=0u)', 'if(1)'))]:
 p=O/(name+'.c');p.write_text(source);exe=O/name
 subprocess.run(flags+[str(p),str(R/'test_adc.c'),'-o',str(exe)],check=True)
 x=subprocess.run([str(exe)],capture_output=True,text=True)
 (R/(name+'_ADC_test.log')).write_text(x.stdout+x.stderr)
 if name=='actual':assert x.returncode==0,x.stdout+x.stderr;print(x.stdout)
 else:assert x.returncode!=0 and '!channel_pending' in x.stderr,x.stderr;print('PASS: synthetic skipped-CCRDY mutant rejected')
