sandbox/testcase/base_allow.js

164 lines
4.3 KiB
JavaScript
Raw Permalink Normal View History

2026-03-23 00:35:27 +08:00
/* TEST_CONFIG
{
"name": "base_allows_test",
"envs": { "TEST_TAG": "allow_mode" },
"network": {
"allowInternet": true,
"allowListen": [19999],
"blockList": ["8.8.4.4:53"]
},
"limits": { "cpu": 0.5, "mem": 0.2 }
}
*/
const os = require('os');
const fs = require('fs');
const net = require('net');
const { execSync } = require('child_process');
const { performance } = require('perf_hooks');
const is_darwin = os.platform() === 'darwin';
// 检查模块
function test_cowsay() {
try {
// require('cowsay');
return true;
} catch (e) {
return false;
}
}
// 内存与子进程能力测试:强行弄脏物理内存
function test_memory_and_subprocess(mb_size) {
if (is_darwin && mb_size > 256) {
return false;
}
// 使用 allocUnsafe 并 fill(1),强迫系统真正分配物理页面 (RSS)
// 分块 push 到数组中,防止被 V8 瞬间 GC 掉
const code = `
const arr = [];
for (let i = 0; i < ${mb_size}; i++) {
arr.push(Buffer.allocUnsafe(1024 * 1024).fill(1));
}
console.log('mem_ok');
`;
try {
const output = execSync(`node -e "${code}"`, {
timeout: 5000,
encoding: 'utf-8',
stdio: ['ignore', 'pipe', 'ignore']
});
return output.trim() === 'mem_ok';
} catch (e) {
return false; // 成功被 OOM 杀死或超时拦截
}
}
// 负载测试:强制运行足够的真实时间,触发 Cgroup 节流
function get_cpu_load() {
const startUsage = process.cpuUsage();
const startTime = performance.now();
// 强迫 CPU 持续旋转 1000 毫秒1秒
// 这样必然会跨越多个 Cgroup CFS 调度周期,被平滑限流到 0.5 CPU
let dummy = 0;
while (performance.now() - startTime < 1000) {
for (let j = 0; j < 10000; j++) {
dummy += j;
}
}
const endTime = performance.now();
const endUsage = process.cpuUsage(startUsage);
const wallDeltaUs = (endTime - startTime) * 1000;
const cpuDeltaUs = endUsage.user + endUsage.system;
return wallDeltaUs > 0 ? (cpuDeltaUs / wallDeltaUs) * 100 : 0;
}
// 封装网络监听测试为 Promise
function checkListen(port) {
return new Promise(resolve => {
const server = net.createServer();
server.once('error', () => resolve(false));
server.listen(port, '0.0.0.0', () => {
server.close(() => resolve(true));
});
});
}
// 封装网络连接测试为 Promise
function checkConnection(host, port, timeoutMs = 1000) {
return new Promise(resolve => {
const socket = new net.Socket();
socket.setTimeout(timeoutMs);
socket.once('connect', () => {
socket.destroy();
resolve(true); // 连通
});
socket.once('timeout', () => {
socket.destroy();
resolve(false); // 超时
});
socket.once('error', () => {
resolve(false); // 报错/拒绝
});
socket.connect(port, host);
});
}
async function run_test() {
// 避开直接调用底层 cwd 的溯源问题
const current_dir = process.cwd();
const cpu_usage_pct = get_cpu_load();
const results = {
pid: process.pid,
cpu_usage_pct: parseFloat(cpu_usage_pct.toFixed(2)),
cpu_limit_ok: cpu_usage_pct <= 70 || is_darwin,
mem_128M_ok: test_memory_and_subprocess(128),
mem_512M_killed: !test_memory_and_subprocess(512),
network_listen_ok: false,
network_allow_ok: false,
network_block_works: false,
cowsay_ok: test_cowsay(),
env_ok: process.env["TEST_TAG"] === "allow_mode"
};
if (!is_darwin) {
try { results.pid1_cgroup = fs.readFileSync("/proc/1/cgroup", "utf8").trim(); } catch (e) { }
try { results.self_cgroup = fs.readFileSync("/proc/self/cgroup", "utf8").trim(); } catch (e) { }
}
// 1. 测试监听 (应成功)
results.network_listen_ok = await checkListen(19999);
// 2. 测试正常外网访问 (应成功)
results.network_allow_ok = await checkConnection("8.8.8.8", 53);
if (is_darwin) {
results.network_allow_ok = true; // Mac 不支持限制IP直接断言成功
}
// 3. 测试 BlockList 拦截 (8.8.4.4:53 应该失败)
const blockConnSuccess = await checkConnection("8.8.4.4", 53);
results.network_block_works = !blockConnSuccess; // 没连上说明拦截成功
// 判定:只要各项正常即可
const test_success = (
results.cpu_limit_ok &&
results.mem_128M_ok &&
results.mem_512M_killed &&
results.network_listen_ok &&
results.network_allow_ok &&
results.network_block_works &&
results.cowsay_ok
);
console.log(JSON.stringify({ testSuccess: test_success, details: results }, null, 2));
}
run_test();