54 lines
3.7 KiB
Python
54 lines
3.7 KiB
Python
from pathlib import Path
|
|
import hashlib,json,subprocess,datetime,time,os
|
|
R=Path(__file__).resolve().parent.parent
|
|
P=R/'.local/runtime-notices-20260913'
|
|
Q=R/'.local/runtime-notices-integration-20260913';Q.mkdir()
|
|
def sha(b):return hashlib.sha256(b).hexdigest()
|
|
def new(p,b):
|
|
with p.open('xb') as f:f.write(b)
|
|
def record(p):
|
|
b=p.read_bytes();return {'path':str(p.relative_to(R)),'bytes':len(b),'sha256':sha(b)}
|
|
manifest=R/'scripts/windows-notices/manifest.json';before=manifest.read_bytes()
|
|
assert sha(before)=='b39beaee5d8aeedcb45c7fd9b65c1b88a4fe784ddb9fe3d4126f5750e478c081'
|
|
entry=json.loads((P/'runtime-entry.json').read_bytes());base=json.loads(before)
|
|
expected=json.loads(json.dumps(base));expected['runtimes'].append(entry)
|
|
assert expected==json.loads((P/'notice-inputs/manifest.json').read_bytes())
|
|
nl=b'\r\n' if b'\r\n' in before else b'\n'
|
|
suffix=nl.join([b' }',b' ]',b'}',b''])
|
|
assert before.endswith(suffix)
|
|
encoded=nl.join((' '+s).encode() for s in json.dumps(entry,indent=2).splitlines())
|
|
after=before[:-len(suffix)]+b' },'+nl+encoded+nl+b' ]'+nl+b'}'+nl
|
|
assert json.loads(after)==expected
|
|
new(Q/'manifest-before.json',before)
|
|
manifest.write_bytes(after)
|
|
attributes=R/'.gitattributes';attrbefore=attributes.read_bytes()
|
|
line=b'harness/experiments/runtime-notices-20260913/** -text whitespace=-blank-at-eol,-blank-at-eof,cr-at-eol'
|
|
assert line not in attrbefore
|
|
attrnl=b'\r\n' if b'\r\n' in attrbefore else b'\n'
|
|
attributes.write_bytes(attrbefore+(b'' if attrbefore.endswith(b'\n') else attrnl)+line+attrnl)
|
|
new(Q/'attributes-before',attrbefore)
|
|
# Exact changed semantics and all actual notice-file digests, without collector/Cargo.
|
|
for group in ['packages','assets','runtimes']:
|
|
for row in expected[group]:
|
|
for n in row.get('notices',[]):
|
|
assert sha((R/'scripts/windows-notices'/n['file']).read_bytes())==n['sha256']
|
|
assert len([x for x in expected['runtimes'] if x['sha256']==entry['sha256']])==1
|
|
assert sha((R/'.local/toolchain/llvm-mingw-20260908-ucrt-x86_64/x86_64-w64-mingw32/bin/libunwind.dll').read_bytes())==entry['sha256']
|
|
test=R/'scripts/test-windows-notices.ps1';collector=R/'scripts/windows-notices.ps1'
|
|
testbytes=test.read_bytes()
|
|
assert b'Remove-Item' not in testbytes and b'Directory]::Delete' not in testbytes and b'rm -' not in testbytes
|
|
assert b'Synthetic fixture retained for inspection:' in testbytes
|
|
shell=Path(os.environ['SystemRoot'])/'System32/WindowsPowerShell/v1.0/powershell.exe'
|
|
command=[str(shell),'-NoProfile','-ExecutionPolicy','Bypass','-File',str(test)]
|
|
inputs=[record(p) for p in [test,collector,manifest,attributes]]
|
|
start=datetime.datetime.now(datetime.timezone.utc).isoformat();clock=time.monotonic()
|
|
with (Q/'synthetic.stdout.log').open('xb') as stdout,(Q/'synthetic.stderr.log').open('xb') as stderr:
|
|
process=subprocess.run(command,cwd=R,stdout=stdout,stderr=stderr)
|
|
elapsed=time.monotonic()-clock
|
|
assert inputs==[record(p) for p in [test,collector,manifest,attributes]]
|
|
receipt={'start_utc':start,'end_utc':datetime.datetime.now(datetime.timezone.utc).isoformat(),'command':command,'powershell_executable':{'path':str(shell),'sha256':sha(shell.read_bytes())},'elapsed_seconds':elapsed,'exit':process.returncode,'inputs':inputs,'inputs_unchanged':True,'base_manifest_sha256':sha(before),'mapping_only_append':True,'all_notice_digests_pass':True,'runtime_digest_pass':True,'cleanup_review':'Original script retains GUID-named synthetic temp fixture; no recursive removal/move. Cargo/rustc are local mock functions; no actual compiler invoked.','stdout':record(Q/'synthetic.stdout.log'),'stderr':record(Q/'synthetic.stderr.log')}
|
|
new(Q/'result.json',(json.dumps(receipt,indent=2)+'\n').encode())
|
|
print(json.dumps(receipt,indent=2))
|
|
assert process.returncode==0
|
|
assert b'PASS:' in (Q/'synthetic.stdout.log').read_bytes()
|