Files
BridgeSwarm/scripts/qvac-packed-selftest.py
T
snxraven 45b28df01b
CI / Build & Test (push) Failing after 1h10m52s
Updates CI
2026-09-08 10:13:13 -04:00

144 lines
4.2 KiB
Python
Executable File

#!/usr/bin/env python3
"""Send qvac.setEnabled over native messaging and fail on INVALID_VERSION."""
import json
import os
import struct
import subprocess
import sys
import threading
import time
def main():
binpath = sys.argv[1]
env = os.environ.copy()
env.setdefault('BRIDGE_SWARM_STORAGE', '/tmp/bs-qvac-packed-selftest')
proc = subprocess.Popen(
[binpath],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env=env,
)
err_chunks = []
def pump_err():
while True:
line = proc.stderr.readline()
if not line:
break
err_chunks.append(line)
sys.stderr.buffer.write(line)
sys.stderr.flush()
threading.Thread(target=pump_err, daemon=True).start()
time.sleep(1.5)
msg = json.dumps(
{
'id': 1,
'type': 'capability',
'payload': {
'pack': 'qvac',
'cmd': 'setEnabled',
'payload': {'enabled': True},
},
}
).encode()
proc.stdin.write(struct.pack('<I', len(msg)) + msg)
proc.stdin.flush()
hdr = proc.stdout.read(4)
if len(hdr) < 4:
print('FAIL: no native-messaging reply', file=sys.stderr)
stop_proc(proc)
return 1
n = struct.unpack('<I', hdr)[0]
body = proc.stdout.read(n).decode('utf-8', 'replace')
print('REPLY', body[:4000])
time.sleep(0.5)
stop_proc(proc)
blob = body + b''.join(err_chunks).decode('utf-8', 'replace')
if 'INVALID_VERSION' in blob:
print('FAIL: packed host still throws INVALID_VERSION', file=sys.stderr)
return 1
try:
reply = json.loads(body)
except json.JSONDecodeError:
print('FAIL: setEnabled reply is not JSON', file=sys.stderr)
return 1
payload = reply.get('payload') or reply
plugins = payload_plugins(payload)
audiogen = payload.get('audiogen') is True or 'audiogen' in plugins
if not audiogen:
print(
'FAIL: packed host did not bind AudioGen (plugins=%s audiogen=%s)%s'
% (plugins, payload.get('audiogen'), missing_native_hint(blob)),
file=sys.stderr,
)
return 1
diffusion = payload.get('diffusion') is True or 'diffusion' in plugins
if not diffusion:
print(
'FAIL: packed host did not bind diffusion (plugins=%s diffusion=%s)%s'
% (plugins, payload.get('diffusion'), missing_native_hint(blob)),
file=sys.stderr,
)
return 1
required = ('asr', 'tts', 'ocr', 'nmt', 'classification', 'bci', 'vla')
missing = [name for name in required if payload.get(name) is not True and name not in plugins]
if missing:
print(
'FAIL: packed host did not bind %s (plugins=%s)%s'
% (','.join(missing), plugins, missing_native_hint(blob)),
file=sys.stderr,
)
return 1
print('PASS: no INVALID_VERSION; QVAC plugins packed')
return 0
def stop_proc(proc):
try:
proc.kill()
except OSError:
pass
try:
proc.wait(timeout=2)
except (OSError, subprocess.TimeoutExpired):
pass
def vulkan_loader_ok():
if sys.platform != 'linux':
return True
candidates = (
'/usr/lib/x86_64-linux-gnu/libvulkan.so.1',
'/usr/lib/aarch64-linux-gnu/libvulkan.so.1',
'/usr/lib64/libvulkan.so.1',
'/usr/lib/libvulkan.so.1',
'/lib/x86_64-linux-gnu/libvulkan.so.1',
)
return any(os.path.exists(p) for p in candidates)
def missing_native_hint(body):
blob = body.lower()
if 'libvulkan.so.1' in blob or 'cannot open shared object file' in blob:
if not vulkan_loader_ok():
return (
' (libvulkan.so.1 is missing on this runner; '
'install libvulkan1 / vulkan-loader before the smoke test)'
)
return ' (native .bare failed to dlopen; see host stderr)'
return ''
def payload_plugins(payload):
raw = payload.get('plugins') if isinstance(payload, dict) else None
if isinstance(raw, list):
return [str(x) for x in raw]
return []
if __name__ == '__main__':
sys.exit(main())