from ops import *
p=read('plan.json');rt=Runtime(load_config(NEW),R);states=rt.states();result=read('ascent/result.json')
assert not result['runtime_error']
for row in p['rows']:
    q=states[row['stream_id']]
    assert q['state']==('running' if row['original'] else 'stopped')
    if row['original']:
        assert q['child_pid'] and not q['last_error'] and not q['metadata_path']['performance']['detail']
        assert q['inference_profile']['active_models']=={'det':'RFDETRFireSmoke'}
    else:
        c=q['last_cleanup'];assert not q['child_pid'] and c['completed'] and c['child_reaped'] and c['writer_released'] and not c['forced']
    assert rt.settings(row['stream_id'])==read('prepared.json')['settings'][row['stream_id']]
before=read('unused-model-before.json');after={n:rt.triton('v2/models/'+n+'/stats') for n in before}
def counts(v):return {(x['name'],x['version']):(x['inference_count'],x['execution_count']) for x in v['model_stats']}
assert all(counts(before[n])==counts(after[n]) for n in before)
code='''import json,glob,configparser
out=[]
for p in glob.glob('/tmp/contextra_cfg/medium_*.txt'):
 t=open(p).read()
 if 'RFDETRFireSmoke' not in t:continue
 c=configparser.ConfigParser();c.read(p+'.preprocess')
 assert 'enable_cuda_buffer_sharing: true' in t and c['property']['tensor-data-type']=='7'
 assert 'CreateContextraFireProcessor' in t
 assert c['property']['scaling-buf-pool-size']=='4' and c['property']['tensor-buf-pool-size']=='4'
 out.append(dict(path=p,dtype=7,sharing=True))
print(json.dumps(dict(configs=out,pids=[int(x.split('/')[2]) for x in glob.glob('/proc/[0-9]*/cmdline') if b'multiprocessing.spawn' in open(x,'rb').read()])))'''
render=json.loads(cmd(['docker','exec',rt.container,'python3','-c',code]));assert len(render['configs'])==16
live={q['child_pid'] for q in states.values() if q.get('child_pid')};assert len(live)==3
old={v['pid'] for v in read('ascent/window-16.json')['samples'][-1]['channels'].values()}
assert live<=set(render['pids']) and not ((old-live)&set(render['pids']))
def stable_sender(value):
 value=copy.deepcopy(value)
 for x in value:
  for k in ('packets','latestRtpTimestamp','lastPacketAgeSeconds','rtpFrames'):x.get('media',{}).pop(k,None)
  x.get('accessChecks',{}).get('senderLoopback',{}).pop('checkedAt',None)
 return value
assert stable_sender(json.loads(cmd(['python3',str(REPO/'tools/rtsp_test.py'),'list'])))==stable_sender(p['sender'])
assert json.loads(cmd(['docker','inspect','contextra-redis-1']))[0]['Id']==p['redis_id']
assert all(file_hash(f)==h for f,h in p['model_files'].items()) and file_hash(ENV)==p['env_hash']
assert all(file_hash(f)==h for f,h in p['presets'].items())
save('readback-'+str(time.time_ns())+'.json',dict(states=states,render=render,unused_models_unchanged=True,
    recovered_children=13,active_children=3,original_artifacts_preserved=True,sender_preserved=True,redis_preserved=True,
    preset_env_preserved=True,resource=rt.resources(),quality='user pending'))
print('Readback PASS: Fire3 running, thirteen reaped, detail Off, Medium/Pose/sender/Redis preserved')
