全方位推进合理、高效、快速处理上下文、禁止顺手扩功能 smoke:收紧WASM烟测守卫

This commit is contained in:
cnc
2026-06-01 23:59:41 +08:00
parent c474d45cdc
commit 37c2f08dfb
5 changed files with 185 additions and 192 deletions

View File

@@ -48,15 +48,10 @@ if [[ -z "$chromium_bin" ]]; then
elif [[ ! -x "$chromium_bin" ]]; then
missing+=("executable chromium at $chromium_bin")
fi
required_files=(
web/public/cnc_sim.js
web/public/cnc_sim.wasm
web/public/linuxcnc_switchkins_remap_config_cases.json
cdp_driver=web/test-browser-wasm-smoke-cdp.py
browser_smoke_modules=(
web/src/wasm-core.js
web/src/app.js
web/index.html
web/styles.css
web/test-browser-wasm-smoke.html
web/test-browser-wasm-smoke-helpers.js
web/test-browser-wasm-smoke-sections.js
web/test-browser-wasm-smoke-linuxcnc-sections.js
@@ -68,6 +63,16 @@ required_files=(
web/test-browser-wasm-smoke-opfs-policy-sections.js
web/test-browser-wasm-smoke-app-sections.js
)
required_files=(
web/public/cnc_sim.js
web/public/cnc_sim.wasm
web/public/linuxcnc_switchkins_remap_config_cases.json
web/index.html
web/styles.css
web/test-browser-wasm-smoke.html
"$cdp_driver"
"${browser_smoke_modules[@]}"
)
for required in \
node \
@@ -168,20 +173,7 @@ then
exit 1
fi
for web_module in \
web/src/wasm-core.js \
web/src/app.js \
web/test-browser-wasm-smoke-helpers.js \
web/test-browser-wasm-smoke-sections.js \
web/test-browser-wasm-smoke-linuxcnc-sections.js \
web/test-browser-wasm-smoke-opfs-workspace-sections.js \
web/test-browser-wasm-smoke-opfs-basic-sections.js \
web/test-browser-wasm-smoke-opfs-parameter-sections.js \
web/test-browser-wasm-smoke-opfs-mirror-sections.js \
web/test-browser-wasm-smoke-opfs-directory-sections.js \
web/test-browser-wasm-smoke-opfs-policy-sections.js \
web/test-browser-wasm-smoke-app-sections.js
do
for web_module in "${browser_smoke_modules[@]}"; do
if ! node --check "$web_module"; then
echo "WASM browser smoke web module syntax check failed for $web_module" >&2
exit 1
@@ -323,18 +315,9 @@ probe_http_resource "/styles.css" "" "text/css"
probe_http_resource "/public/cnc_sim.js" "" "text/javascript"
probe_http_resource "/public/cnc_sim.wasm" "" "application/wasm"
probe_http_resource "/public/linuxcnc_switchkins_remap_config_cases.json" "[" "application/json"
probe_http_resource "/src/app.js" "" "text/javascript"
probe_http_resource "/src/wasm-core.js" "" "text/javascript"
probe_http_resource "/test-browser-wasm-smoke-helpers.js" "" "text/javascript"
probe_http_resource "/test-browser-wasm-smoke-sections.js" "" "text/javascript"
probe_http_resource "/test-browser-wasm-smoke-linuxcnc-sections.js" "" "text/javascript"
probe_http_resource "/test-browser-wasm-smoke-opfs-workspace-sections.js" "" "text/javascript"
probe_http_resource "/test-browser-wasm-smoke-opfs-basic-sections.js" "" "text/javascript"
probe_http_resource "/test-browser-wasm-smoke-opfs-parameter-sections.js" "" "text/javascript"
probe_http_resource "/test-browser-wasm-smoke-opfs-mirror-sections.js" "" "text/javascript"
probe_http_resource "/test-browser-wasm-smoke-opfs-directory-sections.js" "" "text/javascript"
probe_http_resource "/test-browser-wasm-smoke-opfs-policy-sections.js" "" "text/javascript"
probe_http_resource "/test-browser-wasm-smoke-app-sections.js" "" "text/javascript"
for web_module in "${browser_smoke_modules[@]}"; do
probe_http_resource "${web_module#web}" "" "text/javascript"
done
debug_port=$(pick_free_port)
"$chromium_bin" \
@@ -346,161 +329,7 @@ debug_port=$(pick_free_port)
"http://127.0.0.1:$port/test-browser-wasm-smoke.html" >"$dom_log" 2>&1 &
chromium_pid=$!
if ! python3 - "$debug_port" "$dom_log" "$virtual_time_budget" <<'PY'
import base64
import http.client
import json
import os
import socket
import struct
import sys
import time
from urllib.parse import urlparse
debug_port = int(sys.argv[1])
dom_log = sys.argv[2]
timeout_ms = int(sys.argv[3])
deadline = time.monotonic() + (timeout_ms / 1000.0)
def http_json(path):
conn = http.client.HTTPConnection("127.0.0.1", debug_port, timeout=1)
try:
conn.request("GET", path)
response = conn.getresponse()
body = response.read()
finally:
conn.close()
if response.status != 200:
raise RuntimeError(f"{path} returned HTTP {response.status}")
return json.loads(body.decode("utf-8"))
def websocket_connect(url):
parsed = urlparse(url)
key = base64.b64encode(os.urandom(16)).decode("ascii")
sock = socket.create_connection((parsed.hostname, parsed.port), timeout=2)
request = (
f"GET {parsed.path} HTTP/1.1\r\n"
f"Host: {parsed.hostname}:{parsed.port}\r\n"
"Upgrade: websocket\r\n"
"Connection: Upgrade\r\n"
f"Sec-WebSocket-Key: {key}\r\n"
"Sec-WebSocket-Version: 13\r\n\r\n"
)
sock.sendall(request.encode("ascii"))
response = sock.recv(4096)
if b" 101 " not in response.split(b"\r\n", 1)[0]:
raise RuntimeError("DevTools websocket handshake failed")
sock.settimeout(1)
return sock
def websocket_send(sock, payload):
data = payload.encode("utf-8")
header = bytearray([0x81])
if len(data) < 126:
header.append(0x80 | len(data))
elif len(data) < 65536:
header.append(0x80 | 126)
header.extend(struct.pack("!H", len(data)))
else:
header.append(0x80 | 127)
header.extend(struct.pack("!Q", len(data)))
mask = os.urandom(4)
header.extend(mask)
masked = bytes(byte ^ mask[index % 4] for index, byte in enumerate(data))
sock.sendall(header + masked)
def recv_exact(sock, size):
chunks = []
remaining = size
while remaining:
chunk = sock.recv(remaining)
if not chunk:
raise RuntimeError("DevTools websocket closed")
chunks.append(chunk)
remaining -= len(chunk)
return b"".join(chunks)
def websocket_recv(sock):
first, second = recv_exact(sock, 2)
opcode = first & 0x0F
length = second & 0x7F
if length == 126:
length = struct.unpack("!H", recv_exact(sock, 2))[0]
elif length == 127:
length = struct.unpack("!Q", recv_exact(sock, 8))[0]
masked = bool(second & 0x80)
mask = recv_exact(sock, 4) if masked else b""
payload = recv_exact(sock, length)
if masked:
payload = bytes(byte ^ mask[index % 4] for index, byte in enumerate(payload))
if opcode == 8:
raise RuntimeError("DevTools websocket closed")
if opcode != 1:
return None
return json.loads(payload.decode("utf-8"))
def find_page_ws_url():
while time.monotonic() < deadline:
try:
for target in http_json("/json/list"):
if target.get("type") == "page" and target.get("url", "").endswith("/test-browser-wasm-smoke.html"):
return target["webSocketDebuggerUrl"]
except Exception:
pass
time.sleep(0.1)
raise RuntimeError("timed out waiting for browser DevTools page target")
sock = websocket_connect(find_page_ws_url())
next_id = 0
def cdp(method, params=None):
global next_id
next_id += 1
message_id = next_id
websocket_send(sock, json.dumps({"id": message_id, "method": method, "params": params or {}}))
while time.monotonic() < deadline:
try:
message = websocket_recv(sock)
except TimeoutError:
continue
except socket.timeout:
continue
if message and message.get("id") == message_id:
if "error" in message:
raise RuntimeError(message["error"])
return message["result"]
raise RuntimeError(f"timed out waiting for DevTools response to {method}")
def evaluate(expression):
result = cdp("Runtime.evaluate", {"expression": expression, "returnByValue": True})
return result.get("result", {}).get("value", "")
try:
cdp("Runtime.enable")
text = ""
while time.monotonic() < deadline:
text = evaluate('document.querySelector("#result")?.textContent || ""')
if "browser wasm smoke passed" in text:
html = evaluate("document.documentElement.outerHTML")
with open(dom_log, "w", encoding="utf-8") as handle:
handle.write(html)
sys.exit(0)
if "browser wasm smoke failed:" in text:
print(text, file=sys.stderr)
html = evaluate("document.documentElement.outerHTML")
with open(dom_log, "w", encoding="utf-8") as handle:
handle.write(html)
sys.exit(1)
time.sleep(0.2)
print(f"timed out waiting for browser smoke result; last status: {text}", file=sys.stderr)
html = evaluate("document.documentElement.outerHTML")
with open(dom_log, "w", encoding="utf-8") as handle:
handle.write(html)
sys.exit(1)
finally:
sock.close()
PY
then
if ! python3 "$cdp_driver" "$debug_port" "$dom_log" "$virtual_time_budget"; then
echo "browser WASM smoke failed or timed out" >&2
print_browser_failure_context
exit 1