extends SceneTree ## 反例服务端(T-WIN-020 的**负例**夹具):故意不遵守 websocket-keypoints v0.2.0。 ## ## 用途:证明 `build/integration/ws-client.mjs` 的断言**真的会失败**。 ## 一个只跑通过用例的检查器,无法区分「契约被遵守」与「断言写得太松」。 ## ## 故意违反的条款: ## * §3.2 welcome **不声明** silentTimeoutMs / heartbeatIntervalMs(v0.2.0 硬性要求); ## * §3.2 welcome 不带 sessionId; ## * §3.6 收到应用层 ping **不回** pong; ## * §5 不做 deviceId 去重(第二个同 deviceId 连接不会踢掉第一个)。 ## ## 用法:与 probe-ws.gd 相同(`--port` / `--duration-ms` / `--report` / `--stop-file`), ## 但本文件只记录最小事实。期望结果:ws-client.mjs 出现多项 ✗ 并以非 0 退出。 const DEFAULT_PORT := 18770 const DEFAULT_DURATION_MS := 60_000 var _tcp := TCPServer.new() var _peers: Array = [] var _started := false var _done := false var _start_ms := 0 var _port := DEFAULT_PORT var _duration_ms := DEFAULT_DURATION_MS var _report_path := "" var _stop_file := "" func _initialize() -> void: var args := OS.get_cmdline_user_args() var i := 0 while i < args.size(): match args[i]: "--port": _port = int(args[i + 1]); i += 2 "--duration-ms": _duration_ms = int(args[i + 1]); i += 2 "--report": _report_path = args[i + 1]; i += 2 "--stop-file": _stop_file = args[i + 1]; i += 2 _: i += 1 func _process(_delta: float) -> bool: if not _started: _started = true _start_ms = Time.get_ticks_msec() var err := _tcp.listen(_port, "127.0.0.1") if err != OK: print("[bad-ws] ✗ listen 失败:%s" % error_string(err)) quit(2) return true print("[bad-ws] listening on 127.0.0.1:%d(**故意不合规**的服务端)" % _port) while _tcp.is_connection_available(): var conn := _tcp.take_connection() if conn == null: continue var peer := WebSocketPeer.new() peer.supported_protocols = PackedStringArray(["opendance.pose.v1"]) if peer.accept_stream(conn) == OK: _peers.append(peer) for peer in _peers: peer.poll() while peer.get_available_packet_count() > 0: # peer 来自无类型数组,返回值类型推不出来,这里显式标注 var packet: PackedByteArray = peer.get_packet() if peer.was_string_packet(): var text: String = packet.get_string_from_utf8() var parsed: Variant = JSON.parse_string(text) if typeof(parsed) == TYPE_DICTIONARY and str(parsed.get("type", "")) == "hello": # 违规 1/2/3:缺保活字段、缺 sessionId、且此后不回 pong peer.send_text(JSON.stringify({ "type": "welcome", "protocol": "opendance.pose.v1", "expectedFps": 30, })) if _done: return true var elapsed := Time.get_ticks_msec() - _start_ms if elapsed >= _duration_ms or (_stop_file != "" and FileAccess.file_exists(_stop_file)): if _report_path != "": var file := FileAccess.open(_report_path, FileAccess.WRITE) if file != null: file.store_string(JSON.stringify({"server": "bad-ws", "peers": _peers.size()}, " ")) file.close() print("[bad-ws] 收尾(连接 %d,未做去重、未回 pong)" % _peers.size()) _done = true quit(0) return _done