websocketd QA 测试计划全解析:以 CATEGORY-NNN 编号体系构建 WebSocket 服务器的工程质量保障
【免费下载链接】websocketdTurn any program that uses STDIN/STDOUT into a WebSocket server. Like inetd, but for WebSockets.项目地址: https://gitcode.com/gh_mirrors/we/websocketd
本篇技术指南以 qa/plans/README.md 为骨架,完整剖析 websocketd 项目的质量保障(QA)测试计划体系:从测试用例的组织格式、14 类测试分类,到核心 WebSocket、进程管理、CLI 配置、HTTP 路由、安全、CGI 环境、多平台兼容、性能与边界回归等全部测试维度。读完本文,你将掌握如何像官方 QA 一样系统性地验证一个"STDIN/STDOUT 即服务"型 WebSocket 服务器,并能将这套 P0–P3 优先级、编号可追溯的用例方法论直接复用到自己的服务端项目中。
一、测试计划文档体系:总纲与用例格式
websocketd的 QA 测试计划存放在仓库的 qa/plans/ 目录下,以 README.md 作为总纲,按功能类别拆分为多个独立计划文件。每个计划文件覆盖一类功能,测试用例在各自文件内按CATEGORY-NNN格式连续编号(例如CORE-001、PROC-008),保证用例 ID 全局唯一、可追踪、可回溯。
每个测试用例统一包含六个要素,这是整套计划可执行、可复现的基础:
| 要素 | 说明 |
|---|---|
| ID | 唯一标识符,如CORE-001 |
| Title | 简要描述测试目标 |
| Priority | 优先级:P0(关键)、P1(高)、P2(中)、P3(低) |
| Preconditions | 测试前的环境与前置准备 |
| Steps | 精确到命令级别的操作步骤 |
| Expected Result | 明确的预期行为 |
| Notes | 补充上下文、已知问题与回归历史 |
值得注意的一点:Notes字段不仅记录"怎么做",还承载了大量回归历史——每条备注往往关联一个具体 commit 或 issue 号(如eee5350、#159、#431),这使得 QA 计划同时具备"回归测试清单"的属性:凡是历史上出过 bug 的场景,都被固化成一条用例,防止问题复发。
二、十四类测试总览:类别地图
README 以表格形式给出了完整的测试分类。下表按仓库根目录转换后的相对路径列出:
| 文件 | 类别 | 覆盖范围 |
|---|---|---|
| 01-core-websocket.md | Core WebSocket | 基础连接生命周期、文本/二进制消息 |
| 02-process-management.md | Process Management | 子进程启动、stdio 管道、终止 |
| 03-cli-configuration.md | CLI & Configuration | 命令行参数、参数校验、默认值 |
| 04-http-routing.md | HTTP & Routing | 静态文件、CGI、开发控制台、脚本目录模式 |
| 05-security.md | Security | Origin 校验、TLS/SSL、环境隔离 |
| 06-environment-cgi.md | Environment Variables & CGI | RFC 3875 合规、HTTP 头透传 |
| 07-platform-windows.md | Windows Platform | Windows 特有行为、行尾、脚本类型 |
| 08-platform-unix.md | Unix Platforms | macOS、Linux、ARM、容器 |
| 09-protocol-compatibility.md | Protocol Compatibility | WebSocket 版本、HTTP 版本、浏览器测试 |
| 10-edge-cases-errors.md | Edge Cases & Errors | 畸形输入、崩溃、异常状态 |
| 11-performance-scalability.md | Performance & Scalability | 并发连接、大消息、资源限制 |
| 12-dev-console.md | Developer Console | 交互式测试 UI 功能 |
| 13-examples-languages.md | Language Examples | 跨语言示例脚本测试 |
| 14-build-release.md | Build & Release | 交叉编译、打包、版本管理 |
说明:README 的类别表列出了
14-build-release.md(构建与发布),但经核实当前 qa/plans/ 目录下仅有 01–13 号计划文件,该文件尚未落地。其余 13 个文件均为可读、可执行的完整计划。
三、核心 WebSocket 功能测试(CORE)
01-core-websocket.md 共 20 条用例(CORE-001 至 CORE-020),覆盖连接生命周期与消息行为的最基础层面,其中 9 条为 P0 关键用例。这些测试几乎全部可以直接复现:启动websocketd --port=8080 cat,再用wscat -c ws://localhost:8080/连接即可。
3.1 连接生命周期
- CORE-001 基本连接:服务端必须返回 HTTP 101 Switching Protocols,日志无错误。
- CORE-005 客户端断开:客户端断开后,子进程(如
cat)应被终止,日志记录断开事件,不留僵尸进程。 - CORE-006 服务端进程退出:脚本处理完一条消息后
exit 0,服务端应主动关闭连接。 - CORE-016 WebSocket Close Frame:客户端发送 code 1000 的关闭帧,服务端应答并干净地终止连接与子进程。
- CORE-017 Ping/Pong:服务端响应 pong 帧且连接保持打开(由 gorilla/websocket 库处理)。
3.2 文本模式的行缓冲语义
websocketd 的核心模型是"一行消息 = 一个 WebSocket 帧":
- CORE-010 行缓冲:客户端发送的每一行成为进程 stdin 的一行;进程 stdout 的每一行成为一帧,行分隔符为
\n。 - CORE-011 换行符剥离:进程输出
\n与\r\n结尾的行时,尾部换行均被剥离后作为独立消息发送。
CORE-011 的 Notes 直接指向实现:trimEOL函数同时处理\n与\r\n,单元测试位于 endpoint_test.go。源码佐证见 process_endpoint.go:"trimEOL cuts unixy style\nand windowsy style\r\nsuffix from the string"。
3.3 二进制模式
- CORE-008 二进制基础:
--binary模式下应使用二进制帧(opcode 0x02)回显原始字节,不做任何换行处理。Notes 记录了一个经典回归:二进制帧加倍 bug(2016 年 5 月由 commiteee5350修复),验证要点是数据长度必须与输入严格一致。 - CORE-009 大负载:1MB 二进制负载逐字节一致,无截断或损坏。
- CORE-020 标志变体:
--binary、--binary=true启用二进制模式;--binary=false或不加参数使用文本模式(默认)。
3.4 并发、大消息与 Unicode
- CORE-012 多并发连接:每个连接拥有独立的子进程,消息互不串线("Connection A receives from A, B receives from B")。
- CORE-013 快速连断:循环 100 次连接即断,服务端不得崩溃、泄漏资源或出现僵尸进程。
- CORE-014 大文本消息:单条 1MB 文本消息完整回显。
- CORE-015 Unicode 文本:覆盖 ASCII、拉丁扩展(
cafe\u0301)、CJK(你好世界)、Emoji(🎉🚀)、混合(hello 世界 🌍)均须原样回显。Notes 提示 issue #348 曾报告中文乱码问题,可能源于某些脚本语言的缓冲或编码处理——这是"跨语言 UTF-8 保真"的重要验证锚点。
3.5 异常路径
- CORE-018 进程崩溃:脚本
exit 1后,首个连接收到 "starting" 后关闭,第二个连接仍能正常工作(重新生成新进程),退出码 1 不会拖垮 websocketd。 - CORE-019 不存在的命令:
websocketd --port=8080 /nonexistent/command时服务端可启动,但连接优雅失败并返回适当错误,无 panic。
四、进程生命周期与资源管理测试(PROC)
02-process-management.md 的 22 条用例(PROC-001 至 PROC-022)把"子进程即连接"的架构模型拆解为可验证的行为契约。
4.1 每连接一进程
PROC-001 用打印 PID 的脚本验证:客户端 A、B 连接后收到的 PID必然不同——每个 WebSocket 连接都会 fork 一个新的子进程。这正是 websocketd 与常规常驻型 WebSocket 服务器的根本差异:并发能力 = 进程数,因此--maxforks这类限制器至关重要。
4.2 三路流:stdin / stdout / stderr
- PROC-002:客户端消息以
"test input\n"形式写入进程 stdin。 - PROC-003:进程启动即输出
welcome、ready,客户端连接后立即收到两条独立消息。 - PROC-004:stderr 内容只进服务端日志,绝不进 WebSocket(
--loglevel=debug时可在日志中看到)。 - PROC-022
--passstderr:开启后,stdout 与 stderr 均以 JSON 消息到达客户端,形如{"stream":"stdout","data":"..."}/{"stream":"stderr","data":"..."},且无论是否开启该标志,stderr 始终写入服务端日志;关闭时仅 stdout 到达客户端且不加标签(与旧版本行为一致)。关键约束:--binary与--passstderr互斥,同时指定会在启动时报错——这一约束在 help.go 的帮助文本中有明确记载。
4.3 优雅终止的信号升级序列(源码级验证)
PROC-005 是理解 websocketd 进程管理的核心用例:客户端断开后,子进程会收到逐级升级的终止信号。以捕获 INT/TERM 的脚本验证实际送达情况,对应实现位于 process_endpoint.go:
stdin 关闭 → 等待 100ms + closems → SIGINT → 等待 250ms + closems → SIGTERM → 等待 500ms + closems → SIGKILL → 等待 1000ms即:先关闭 stdin 给进程优雅收尾的机会(很多程序读到 EOF 自然退出),随后依次发送 SIGINT、SIGTERM,最后以 SIGKILL 兜底;每一步之间若进程已退出则立即返回。--closems为前三个等待阶段统一追加宽限期(PROC-006、PROC-007 分别验证--closems=3000与--closems=0立即击杀)。计划文件记录的期望时序为默认 100ms/250ms/500ms、带--closems时按比例延长,具体以运行二进制与源码为准。Notes 还记录了回归历史:进程挂起 bug由 commit3f89f2e(issue #159)修复。
4.4 --maxforks 并发上限
- PROC-008:
--maxforks=2时第三个连接收到HTTP 429 Too Many Requests,升级被拒,前两个连接不受影响。Notes 关联 issue #366——客户端难以区分"fork 数达上限"与"服务端错误"。 - PROC-009:客户端 A 断开后计数递减,之前被 429 拒绝的客户端 B 可再次连接成功。
- PROC-021:
--maxforks=0表示无限制(仅受系统资源约束)。
默认上限并非无限:config.go 中defaultMaxForks = 1024,注释明确它是"防止失控的后备闸(runaway backstop)而非容量规划",因为每个 fork 都是完整子进程,无限(0)会让单个客户端通过狂开连接 fork 轰炸主机。
4.5 异常退出与目录模式
- PROC-010/011/012/018:非零退出码(42)、C 程序段错误(segfault)、脚本无执行权限、进程立即退出——全部要求"连接关闭、错误入日志、websocketd 自身不崩溃、其他连接不受影响"。
- PROC-013/014:
--dir脚本目录模式下,每个 URL 映射到对应脚本,不存在则 404;ws://host/echo.sh/extra/path时SCRIPT_NAME=/echo.sh、PATH_INFO=/extra/path(Notes 指向 handler_test.go)。 - PROC-016 输出缓冲:这是新手最容易踩的坑——Python 脚本只写
"partial..."不换行时客户端收不到任何消息,直到换行出现才收到整条"partial...complete"。文本模式是行缓冲的,换行是分隔符。Notes 记录了 issues #406、#388(PHP)、#400 等大量缓冲问题:很多语言在 stdout 非终端时启用全缓冲,脚本必须主动 flush。
五、CLI 配置与参数校验测试(CLI)
03-cli-configuration.md 的 32 条用例验证命令行解析、校验与默认值。这部分与 help.go 中的完整选项清单一一对应,是理解 websocketd 配置面的最佳入口。
5.1 端口与监听地址
- CLI-001 默认端口:不带
--port时监听80(HTTP)或443(SSL)。源码佐证 config.go 的resolvePort函数。 - CLI-002/003/004:自定义端口、端口占用(第二个实例应报清晰错误且不影响第一个)、非法端口(99999/-1/abc)均须给出明确错误并拒绝启动。
- CLI-005/006/007/008:
--address支持多个(多地址同时监听)、127.0.0.1仅本机、0.0.0.0全接口、IPv6 需方括号--address=[::1]。
5.2 日志级别与基础标志
- CLI-009 日志级别(从最详细到最不详细):
debug(详细内部状态)、trace(逐请求细节)、access(连接/断开事件)、info(启动与重要事件)、error(仅错误)、fatal(仅致命错误);每个级别包含其之上所有更严重级别。 - CLI-010/011/012:
--version(如 "websocketd 0.4.1")、--help(完整选项说明,commit169ecec修复 issue #436)、--license(BSD-2-Clause 文本)均在打印后立即退出。
5.3 参数组合校验
- CLI-013:既无命令也无
--dir时报错并显示帮助。 - CLI-014:
--dir与命令同时指定报错。 - CLI-026/030:
--ssl缺证书/密钥时报错(panic 曾由 commit334a9ec修复,issue #431);--ssl不指定--address时正常启动。校验逻辑见 config.go 的validateSSL。 - CLI-031:
--binary三种写法的行为验证。 - CLI-029 解析边界:空格代替
=、未知标志、空值等均由 Go flag 包处理。
5.4 环境透传与请求头
- CLI-015/016/017:
--passenv=MY_VAR单选、逗号分隔多选(VAR1,VAR2,VAR3)、指定不存在的变量(不崩溃,仅不出现)。 - CLI-019/020:
--header应用于所有响应;--header-ws仅 WebSocket 升级响应、--header-http仅普通 HTTP 响应,两者互不串扰。
5.5 同源、静态资源与 Unix Socket
- CLI-021/022:
--sameorigin拒绝跨域;--origin=example.com:8080白名单精确匹配 host:port。 - CLI-023/024/025:
--devconsole提供交互式测试页;--staticdir让 HTTP 请求返回静态文件而 WebSocket 仍由命令处理;--cgidir执行 CGI 脚本。 - CLI-032 Unix Domain Socket(5 步完整生命周期验证):仅指定
--unixsocket时完全不启动 TCP 监听;客户端可直连 socket 路径;进程被 SIGKILL 后残留的陈旧 socket 文件会被自动清理而非报 "address already in use";可与 TCP 监听并存;第二个实例若指向仍被监听的 socket 路径则报 "socket ... is already in use by a running server" 且不得覆盖活着的 socket。对应实现见 config.go 的wantsUnixSocketOnly。
六、HTTP 路由测试(HTTP)
04-http-routing.md 的 23 条用例覆盖 URL 路由的完整矩阵。
6.1 升级与普通请求
- HTTP-001:带标准升级头的请求(
Upgrade: websocket、Connection: Upgrade、Sec-WebSocket-Key、Sec-WebSocket-Version: 13)返回 101。 - HTTP-002:普通 HTTP GET不得执行脚本,返回错误或空响应。
- HTTP-023:升级头变体(
Connection: keep-alive, Upgrade、小写、混合大小写Upgrade: WebSocket)均须被接受。
6.2 静态文件
- HTTP-003/004/005:MIME 类型正确、子目录嵌套文件可访问、缺失文件 404。
- HTTP-006(P0 安全)路径穿越防护:
../../../etc/passwd、URL 编码变体(..%2F..%2F、%2e%2e/)一律拦截(404 或 403),绝不越界服务文件。 - HTTP-007/019:静态文件与 WebSocket 同端口共存、10 个 WebSocket + 100 个 HTTP 请求并发互不干扰。
6.3 CGI 与目录模式
- HTTP-008/009/010:CGI 脚本执行、
QUERY_STRING传递、子目录脚本(issue #453 曾报告 cgi-dir 子目录问题)。 - HTTP-011/012/013:
--dir模式 URL 映射、不存在脚本 404、路径穿越(../../etc/passwd、%2e%2e/secret.sh)无法逃逸脚本目录。 - HTTP-014:脚本目录中的非可执行文件返回错误而非崩溃(commit
11610d0在协议切换前做最终存在性检查)。
6.4 头与请求语义
- HTTP-016/017:单条与多条自定义头。
- HTTP-018:Host 头解析(
example.com:8080与无端口)推导 SERVER_NAME/SERVER_PORT,缺失 Host 优雅处理(commit63bf0cb修复 80 端口处理)。 - HTTP-020/021/022:HEAD 请求无 body 不崩溃;WebSocket URL 带
?key=value时 QUERY_STRING 注入子进程环境;URL fragment 按规范不发送到服务端。
七、安全测试(SEC)
05-security.md 的 26 条用例把安全面切分为五个维度。
7.1 Origin 校验
- SEC-001/002:
--sameorigin下同源成功、跨源(http://evil.com)被拒(403)。 - SEC-004/005/006/007:
--origin白名单精确匹配 host:port(trusted.com:3000与trusted.com:4000严格区分,无端口不匹配);逗号分隔多白名单。 - SEC-008:
Origin: null(沙箱 iframe、file:// 页面发送)不得匹配同源——v0.2.10 修复。 - SEC-010:默认(不加任何标志)接受任意来源,这是默认行为,生产环境需自行决策。
7.2 环境隔离(安全关键)
- SEC-011:不指定
--passenv时,父进程的SECRET_KEY、DATABASE_URL等敏感变量不可见,子进程只见 CGI 标准变量。 - SEC-012:
--passenv=SAFE只透传白名单项。
7.3 TLS
- SEC-013/015/016:自签证书握手成功;证书与密钥不匹配、文件缺失均报清晰错误且不启动、不 panic。
- SEC-014 协议版本:SSL3 不再支持(v0.2.12 移除);TLS 1.2/1.3 应可用;更旧版本取决于 Go 的 TLS 默认(Go 1.18+ 默认禁用 TLS 1.0/1.1)。
7.4 注入与 DoS 防护
- SEC-017/018:脚本目录模式下 URL 路径中的
;ls、$(whoami)、|cat均按文件路径处理,无 shell 注入;query string 仅作为 QUERY_STRING 环境变量值传递,不做 shell 解释。 - SEC-019:请求头内嵌换行的响应拆分攻击被消毒或拒绝。
- SEC-020/021/022:
--maxforks=10下的超限请求全部 429 且现存连接不受影响;1MB+ 超大头部被 Go HTTP 服务器限制拒绝;Slowloris 慢速头部由 Go 内置超时兜底。
7.5 依赖与静态分析
- SEC-024:检查 gorilla/websocket 版本及 CVE(issue #441)。
- SEC-025:gosec SAST 扫描无 critical/high 发现(issue #418)。
- SEC-026 帧大小限制:超过默认读取限制的帧导致连接关闭而非内存耗尽(issue #445 曾请求可配置帧大小——当前版本已提供
--maxframesize,默认 1MiB,见 help.go)。
八、CGI 环境变量测试(ENV)
06-environment-cgi.md 的 20 条用例验证 RFC 3875 CGI 合规性。其核心洞察是:websocketd 把每个 WebSocket 连接当作一次 CGI 请求,通过环境变量向子进程注入全部请求上下文。
8.1 标准 CGI 变量(ENV-001)
连接env命令后,以下变量必须全部存在:
| 变量 | 期望值 |
|---|---|
SERVER_SOFTWARE | "websocketd/VERSION" |
GATEWAY_INTERFACE | "CGI/1.1" |
SERVER_PROTOCOL | "HTTP/1.1" |
SERVER_NAME | Host 头中的主机名 |
SERVER_PORT | 端口号 |
REQUEST_METHOD | "GET" |
SCRIPT_NAME | 路径部分 |
REMOTE_ADDR | 客户端 IP |
REMOTE_HOST | 主机名或 IP |
8.2 请求上下文变量
- ENV-002/003:
?key=value&foo=bar时QUERY_STRING原样注入;无查询串时置空。 - ENV-004:目录模式下
SCRIPT_NAME=/echo.sh、PATH_INFO=/extra/path。 - ENV-005/017:
REMOTE_ADDR/REMOTE_PORT有效,IPv6(::1)地址完整保留。 - ENV-006:每次连接
UNIQUE_ID唯一。 - ENV-007:
REQUEST_URI=/path?query=1。
8.3 HTTP 头转 HTTP_* 变量
- ENV-008/014/015:
X-Custom-Header→HTTP_X_CUSTOM_HEADER,规则为大写、连字符转下划线、加 HTTP_ 前缀;50+ 个头部无截断;Cookie→HTTP_COOKIE。 - ENV-009/010:SSL 下
HTTPS=on,非 SSL 不设置。 - ENV-011:
AUTH_TYPE、REMOTE_IDENT、REMOTE_USER、CONTENT_TYPE、CONTENT_LENGTH按 RFC 3875 对 WebSocket GET 请求置空。 - ENV-012/013:
--passenv=PATH透传 PATH(issue #144);含空格与引号的变量值原样保留。 - ENV-016:Host 头解析由 http_test.go 的
tellHostPort覆盖。 - ENV-018:CGI 目录模式下 POST 请求设置
CONTENT_LENGTH/CONTENT_TYPE。 - ENV-019(P0):父进程环境零泄漏——只出现 CGI 标准变量。这与 config.go 的平台相关
defaultPassEnv(如 Linux 默认透传PATH,LD_LIBRARY_PATH,Windows 默认透传PATH,SystemRoot,COMSPEC,PATHEXT,WINDIR)共同构成完整的环境隔离策略。 - ENV-020:
SERVER_SOFTWARE版本号与websocketd --version输出一致。
九、平台兼容性测试(Windows / Unix / 容器 / 跨平台)
9.1 Windows(07-platform-windows.md)
- WIN-001/003/004:
.bat、PowerShell(powershell.exe -File echo.ps1)均可作为后端。 - WIN-002 CRLF 处理:
\r\n尾随被trimEOL剥离(commit0559afd),客户端收到无回车符的干净文本。 - WIN-007 进程终止:Windows 无 SIGTERM/SIGINT(issue #362),使用
TerminateProcess等不同机制;断连后无孤儿进程。 - WIN-008/009/013/014/015:
--maxforks生效、反斜杠路径与含空格路径(issue #293)、staticdir 的 Windows 路径、SSL、环境变量透传。 - WIN-010/012:Windows 上 CGI 脚本(.bat/.exe,issue #454)、PHP(issue #320)。
- WIN-005/006/011:VBScript/JScript 示例、32 位(windows_386)构建。
9.2 Unix(08-platform-unix.md)
- macOS:Intel(darwin_amd64)与 Apple Silicon(darwin_arm64,
GOARCH=arm64 go build,注意 issue #425 的 M1 Max 段错误须验证)。 - Linux:amd64、ARM(树莓派,issue #295 安装脚本不识别 ARM)、ARM64(commit
ac4b25f、6909932)、386;DEB/RPM 包安装;systemd 服务(issue #329);SIGTERM 优雅关闭并终止子进程。 - 容器:Docker 内运行(issue #368 "input device is not a TTY")、无
-t时 STDIN/STDOUT 管道不需要终端、Termux(Android,issue #452)。 - 跨平台:MIPS 编译(issue #434)、进程组清理行为按 OS 记录(Linux/macOS 用信号,Windows 用 TerminateProcess)、Unix 无执行权限与 Windows 文件关联的差异。
十、协议与浏览器兼容性测试(PROTO / BROWSER / CLIENT)
10.1 WebSocket 协议(09-protocol-compatibility.md)
- PROTO-001/002/003:版本 13(RFC 6455)完整支持;不支持的版本与缺失
Sec-WebSocket-Key被拒绝。 - PROTO-004 关闭码:1000/1001/1006/1011 均优雅处理,子进程被终止、日志记录原因(关联 issues #456、#399)。
- PROTO-005/006/008:permessage-deflate 扩展(gorilla 可选压缩)、子协议协商(websocketd 不实现协商,头可能被忽略)、分片消息由库重组后完整送达子进程。
- PROTO-007 大帧:64KB/1MB/10MB 帧,超限帧按库配置关闭连接。
- PROTO-009 握手超时:慢速发送部分升级头最终超时,不无限等待(commit
b2b6022加入握手超时)。
10.2 HTTP 版本
- PROTO-010/011/012:HTTP/1.1 为标准传输;HTTP/1.0 可服务静态文件但 WebSocket 升级需要 1.1;HTTP/2 依赖 Go 服务器默认支持与库能力。
10.3 浏览器与客户端库
- BROWSER-001~007:Chrome/Firefox/Safari/Edge/移动 Safari/移动 Chrome 全兼容;
wss://安全连接;混合内容(https 页面连 ws://)被现代浏览器拦截。 - BROWSER-009/010:开发控制台 UI 在各大浏览器可用(commit
efd867b增加移动端 viewport),Tab 字符正确渲染(commit0e690fb)。 - CLIENT-001~005:wscat、Python
websockets库、Go gorilla/websocket 客户端、curl 7.86+ 手写升级请求、websocat 全部兼容。
十一、边界、性能与开发控制台测试
11.1 边界与错误(10-edge-cases-errors.md)
- 输入边界:10MB 单行文本不截断;空白字符保留(只剥尾随换行);二进制模式 null 字节保留;文本模式帧内嵌
\n成为进程的多个行;10000 条消息快速发送零丢失、有序。 - 错误条件:进程写已关闭的 WebSocket 时被检测并终止(无错误循环);向已退出进程发送消息被静默丢弃或关闭连接;进程提前关闭 stdin(broken pipe)不崩溃;不读 stdin 的进程消息进入管道缓冲。
- 竞态:进程退出与发送并发、关闭与输出并发、100 次快速重连——均无 panic、无 goroutine 泄漏、无死锁。
- 缺失/畸形数据:缺 Host 被拒、空 Origin 不崩溃、畸形帧/错误掩码/不可能长度由 gorilla 库拒绝并关连接。
- 资源限制:
ulimit -n 64下新连接优雅失败;内存压力下依赖 Go GC;SIGPIPE 由 Go 默认忽略。 - 回归清单(P0):
--ssl --port=8443无--address的 nil 指针回归(issue #431/commit334a9ec,另见 #342);二进制帧加倍回归(commiteee5350,响应长度必须等于输入);断连后进程挂起回归(issue #159/commit3f89f2e,无僵尸进程)。
11.2 性能与扩展性(11-performance-scalability.md)
- 并发连接:10/100/1000 并发(1000 需
ulimit -n 4096,issue #356 曾报告 150 封顶);每秒 100 次连断持续 5 分钟无泄漏。 - 吞吐与延迟:文本/二进制 10000 条消息吞吐;10MB 大消息完整性;本地回环往返延迟(期望亚毫秒级基线);首条消息延迟包含进程启动开销(issue #448);
--reverselookup增加 DNS 解析延迟。 - 资源:连接关闭后内存回落到基线(无稳态增长);goroutine 数回落(无泄漏);空闲时 CPU 近零。
- 压力:50 连接 1 小时持续负载稳定;空闲 30 分钟后突发 100 连接无延迟;
--maxforks=10满额下 100 个额外请求全部 429 且现存连接不受影响;静态文件服务不受 WebSocket 负载显著影响。
11.3 开发控制台(12-dev-console.md)
--devconsole内置的交互式测试控制台是快速验证端点的利器(访问http://[host]/foo即可测试ws://[host]/foo端点):
- DEV-001~004(P0):页面加载(含连接/断开按钮、消息输入与日志区)、Connect/Disconnect、消息发送与回显。
- DEV-005/006:上下方向键浏览消息历史、二进制消息显示。
- DEV-007~009:URL 栏随 WebSocket 路径更新、Tab 字符渲染、移动端 viewport(commit
efd867b)。 - DEV-011~014:不加
--devconsole时返回 404;与--staticdir并存时根路径优先级需文档化(help.go 明确二者不可同时使用);多窗口各自独立连接与子进程;服务重启后可重连。
十二、多语言示例测试(LANG)
13-examples-languages.md 覆盖仓库 examples/ 下的全部语言示例:Bash(greeter/count/send-receive/dump-env/chat)、Python、Node.js、Ruby、Perl、PHP、Java、C#、Rust、Lua、QuickJS(PR #396 新增)、Swift、Haskell,以及 examples/cgi-bin/ 的 CGI 示例和 examples/html/count.html 的 HTML 示例。
三条跨语言关注点是实战中最有迁移价值的结论:
- LANG-200 缓冲刷新矩阵:Python(
-u或flush=True)、PHP(fflush(STDOUT))、Perl($| = 1)、Java(System.out.flush())、C(fflush(stdout))必须显式刷新;Bash(默认行缓冲)、Ruby(通常行缓冲)自动刷新。 - LANG-201 退出码一致性:无论何种语言,websocketd 对退出码的处理行为一致。
- LANG-202 UTF-8 保真:CJK、Emoji、多字节字符经各语言 stdin/stdout 原样保留(issue #348 中文问题为验证重点)。
十三、测试环境要求与自动化运行
13.1 环境矩阵(README 原表继承)
| 维度 | 要求 |
|---|---|
| 操作系统 | Windows 10/11、macOS(Intel + ARM)、Ubuntu/Debian |
| 浏览器 | Chrome、Firefox、Safari、Edge(均最新版)、移动 Safari、移动 Chrome |
| 语言运行时 | Bash、Python 3、Node.js、Ruby、Perl、PHP、Go、Java、C#、Rust、Lua |
| 工具 | wscat或同类 WebSocket CLI、curl、openssl |
| 网络 | localhost、LAN、IPv4、IPv6 |
13.2 自动化测试基线
现有的 Go 测试套件覆盖单元级行为:
go test ./...README 明确指出:本目录下的计划覆盖超出单元测试之外的手动、集成与探索性测试。仓库 qa/integration/ 中实际存在大量 Go 集成测试(如 core_test.go、process_test.go、cli_test.go、http_test.go、security_test.go、env_test.go、performance_test.go 等),与计划文件形成"自动化 + 人工验证"的双层保障:单元/集成测试守护回归,计划文件则为新特性验收、跨平台验证与安全审查提供结构化执行清单。
结语:把 QA 计划方法论迁移到自己的项目
这套计划的工程价值不止于 websocketd 本身,其方法论完全可复用:用CATEGORY-NNN编号保证用例可追溯,用 P0–P3 优先级锚定发布门禁,用 Notes 字段沉淀回归历史,把每个历史 bug 固化为一条防复发用例。对于任何"外部命令 + 协议桥接"型服务(STDIN/STDOUT 转 WebSocket、CGI、进程编排网关),你都可以按"连接生命周期 → 进程管理 → 配置校验 → 路由 → 安全 → 环境隔离 → 平台矩阵 → 边界回归 → 性能压测"这条路径,复制出一套同样严谨、可执行、可验证的测试计划。
【免费下载链接】websocketdTurn any program that uses STDIN/STDOUT into a WebSocket server. Like inetd, but for WebSockets.项目地址: https://gitcode.com/gh_mirrors/we/websocketd
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考