from pathlib import Path
import subprocess
p=Path(__file__).resolve().parent;c=p/'firmware/固件/lamp_control';t=p/'firmware/固件/lamp_target';o=p/'async_host_test';o.mkdir(exist_ok=True)
flags=['cc','-std=c11','-Wall','-Wextra','-Werror','-fsanitize=address,undefined']
mut=o/'premature_bank.c';mut.write_text((c/'pca9956b_async_bank.c').read_text().replace('b->reads==24u','b->reads==23u'))
exe=o/'premature_bank';subprocess.run(flags+['-I'+str(c),str(c/'pca9956b_fault_monitor.c'),str(mut),str(p/'test_async.c'),'-o',str(exe)],check=True)
r=subprocess.run([str(exe)],capture_output=True,text=True);assert r.returncode!=0
(p/'negative_23_reads.log').write_text('Mutant publishes after23 of24 reads; expected failure, exit '+str(r.returncode)+'\n'+r.stdout+r.stderr)
mut=o/'double_cancel.c';s=(t/'src/lamp_i2c_read.c').read_text();a=s.index('    if(r==NULL || !r->bound)return;',s.index('void lamp_i2c_read_cancel'));b=s.index('\n}',a)
s=s[:a]+'    if(r!=NULL && r->bound)fail(r,I2C1->ISR);'+s[b:];mut.write_text(s)
exe=o/'double_cancel';subprocess.run(flags+['-I'+str(p/'read_host_test'),'-I'+str(t/'include'),str(mut),str(p/'test_read.c'),'-o',str(exe)],check=True)
r=subprocess.run([str(exe)],capture_output=True,text=True);assert r.returncode!=0
(p/'negative_double_cancel.log').write_text('Mutant re-aborts after cleared ARLO; expected failure, exit '+str(r.returncode)+'\n'+r.stdout+r.stderr)
print('PASS 23-read premature bank and repeated-ARLO-cancel mutants rejected')
