第 9 章:验证边界,而不只是看到成功
为什么还要做失败实验
计算成功只能说明程序在当前环境能运行,不能说明限制都生效。边界测试需要提出一个应该被拒绝的动作,再观察系统是否真的拒绝。
先备份 input/analyze.py。每次实验只替换这个文件;运行前把旧报告移走,以免控制器误读上次的结果。不要把原始重要数据放进这些实验。
验证输入只读
把脚本临时改成:
from pathlib import Path
Path('/input/should-not-exist.txt').write_text('test')再运行控制器。预期写入失败并出现只读文件系统或类似权限错误,任务非零退出。宿主机 input 目录不应出现该文件。不同系统的错误文字可能不同,判断重点是操作是否被拒绝。
验证根目录只读
from pathlib import Path
Path('/root-test.txt').write_text('test')预期失败。因为程序同时以非 root 身份运行,错误可能来自权限或只读文件系统;这一条不能单独区分两个机制的贡献。它证明当前组合策略拒绝了该写入。
验证常规外部网络连接
import socket
try:
socket.create_connection(('1.1.1.1', 443), timeout=3)
except OSError as exc:
print('外部连接失败:', type(exc).__name__)
else:
raise SystemExit('外部连接意外成功,请检查配置')用 IP 地址可避免把 DNS 失败误当成所有网络限制的证据。预期连接失败。控制器随后还会提示没有报告,这是正常的:这个测试脚本没有生成报告。单次失败只是一个目标地址的检查;应结合 Docker 网络配置确认 –network=none,不能用一次失败证明所有可能外传通道都不存在。
验证超时停止
import time
time.sleep(120)控制器等待约 30 秒后开始清理。Docker 客户端被终止不保证容器随之终止,因此 finally 中的 docker rm -f 很重要。执行后可运行 docker ps -a,确认没有残留 sandbox-demo- 开头的容器。
实验完成后恢复原来的分析脚本,再运行一次成功案例。记录“尝试了什么、预期如何、实际如何”,比只保存一个成功截图更有学习价值。