164 lines
4.3 KiB
JavaScript
164 lines
4.3 KiB
JavaScript
/* 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(); |