import pathlib,json,sys,copy
ROOT=pathlib.Path(__file__).resolve().parents[1]; sys.path.insert(0,str(ROOT/'src'))
from upload_boundary import *
policy=json.loads((ROOT/'fixture/golden-policy.json').read_text()); fixture=json.loads((ROOT/'fixture/baseline-upload.json').read_text()); items={x['fixture_id']:x for x in fixture['files']}; checks=[]
def c(n,x):checks.append((n,bool(x)))
r=evaluate_upload(items['AVATAR_OK'],policy); c('avatar_promote',r['decision']=='PROMOTE_APPROVED_REPRESENTATION'); c('avatar_state',r['state']=='PROMOTED'); c('approved_repr',str(r['public_representation']).startswith('approved://'))
r=evaluate_upload(items['TYPE_MISMATCH'],policy); c('type_mismatch',r['decision']=='DENY_TYPE_EVIDENCE_MISMATCH'); c('mismatch_quarantine',r['state']=='QUARANTINED')
r=evaluate_upload(items['CONTRACT_OK'],policy); c('contract_promote',r['decision']=='PROMOTE_APPROVED_REPRESENTATION')
def test(name,base,mut,expect):
 x=copy.deepcopy(items[base]);x.update(mut);c(name,evaluate_upload(x,policy)['decision']==expect)
test('missing_storage','AVATAR_OK',{'generated_storage_name':''},'DENY_STORAGE_IDENTITY_MISSING')
test('client_storage_identity','AVATAR_OK',{'generated_storage_name':'me.png'},'DENY_CLIENT_FILENAME_AS_STORAGE_IDENTITY')
test('missing_quarantine','AVATAR_OK',{'quarantine_location':''},'DENY_QUARANTINE_LOCATION_MISSING')
test('invalid_quarantine','AVATAR_OK',{'quarantine_location':'temp://x'},'DENY_QUARANTINE_LOCATION_INVALID')
test('public_raw','AVATAR_OK',{'quarantine_location':'public://raw/x.png'},'DENY_PUBLIC_RAW_STORAGE')
test('authz','AVATAR_OK',{'uploader_role':'anonymous'},'DENY_UNAUTHORIZED_UPLOADER')
test('zero_size','AVATAR_OK',{'size_bytes':0},'DENY_INVALID_SIZE')
test('negative_size','AVATAR_OK',{'size_bytes':-1},'DENY_INVALID_SIZE')
test('oversize','AVATAR_OK',{'size_bytes':9999999},'DENY_SIZE_LIMIT')
test('required_gate','CONTRACT_OK',{'scan_cdr_status':'MISSING'},'DENY_REQUIRED_GATE_MISSING')
row=build_record(items['AVATAR_OK'],evaluate_upload(items['AVATAR_OK'],policy));c('record_complete',evidence_row_complete(row)); row['residual_risk']='';c('record_missing',not evidence_row_complete(row))
a=classify_transfer('avatar');d=classify_transfer('contract_document');c('transfer_avatar',a['scan_required'] is False);c('transfer_contract',d['scan_required'] is True);c('transfer_types_differ',a['allowed_extensions']!=d['allowed_extensions']);c('client_ct_not_authority',policy['client_content_type_is_authority'] is False);c('client_name_not_storage',policy['client_filename_is_storage_identity'] is False);c('production_false',policy['production_proof'] is False)
for n,ok in checks:print(('PASS' if ok else 'FAIL'),n)
print(f'SUMMARY {sum(x[1] for x in checks)}/{len(checks)} PASS');raise SystemExit(0 if all(x[1] for x in checks) else 1)
