LazyBoy2/tests/browser_cleanup.py

40 lines
2.3 KiB
Python

"""Headless browser shutdown regression; never opens visible windows or external sites."""
import json, os, subprocess, time
from pathlib import Path
HELPER=Path(__file__).resolve().parents[1]/'tools/playwright/browser_helper.mjs'
def processes():
rows={}
for line in subprocess.check_output(['ps','-axo','pid=,ppid=,command='],text=True).splitlines():
pid,parent,cmd=line.strip().split(None,2);rows[int(pid)]=(int(parent),cmd)
return rows
def main():
env={**os.environ,'GROKBOY_BROWSER_HEADED':'0'};env.pop('GROKBOY_BROWSER_PROFILE',None)
for mode in ('close','eof','signal','single'):
args=['node',str(HELPER)]
if mode=='single':args+=['--cmd',json.dumps({'id':'1','op':'navigate','url':'data:text/html,cleanup fixture'})]
p=subprocess.Popen(args,env=env,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,text=True)
tracked=set()
try:
if mode=='single':
while p.poll() is None:
tracked.update(pid for pid,(parent,cmd) in processes().items() if parent==p.pid and ('chrome' in cmd.lower() or 'chromium' in cmd.lower()))
time.sleep(.02)
assert p.returncode==0,p.stderr.read()
else:
p.stdin.write(json.dumps({'id':'1','op':'navigate','url':'data:text/html,cleanup fixture'})+'\n');p.stdin.flush()
assert json.loads(p.stdout.readline())['ok']
tracked={pid for pid,(parent,cmd) in processes().items() if parent==p.pid and ('chrome' in cmd.lower() or 'chromium' in cmd.lower())}
assert tracked,'must observe actual browser process'
if mode=='close':
p.stdin.write('{"id":"2","op":"close"}\n');p.stdin.flush();assert json.loads(p.stdout.readline())['ok'];p.stdin.close()
elif mode=='eof':p.stdin.close()
else:p.terminate()
p.wait(timeout=10)
deadline=time.monotonic()+5
while tracked.intersection(processes()) and time.monotonic()<deadline:time.sleep(.05)
assert not tracked.intersection(processes()),(mode,tracked)
print('PASS browser processes exit on',mode,flush=True)
finally:
if p.poll() is None:p.terminate();p.wait(timeout=10)
if __name__=='__main__':main()