UNPKG

node-os-utils

Version:

Advanced cross-platform operating system monitoring utilities with TypeScript support

190 lines 8.89 kB
"use strict"; /** * CommandExecutor单元测试 * 测试命令执行器的核心功能和错误处理 */ Object.defineProperty(exports, "__esModule", { value: true }); const chai_1 = require("chai"); const command_executor_1 = require("../../../src/utils/command-executor"); const errors_1 = require("../../../src/types/errors"); describe('CommandExecutor Unit Tests', function () { let executor; beforeEach(function () { executor = new command_executor_1.CommandExecutor('test-platform', { timeout: 5000, encoding: 'utf8' }); }); describe('基本命令执行', function () { it('应该能够执行简单的系统命令', async function () { // 使用跨平台兼容的命令 const command = process.platform === 'win32' ? 'echo hello' : 'echo "hello"'; const result = await executor.execute(command); (0, chai_1.expect)(result.stdout.trim()).to.equal('hello'); (0, chai_1.expect)(result.stderr).to.equal(''); (0, chai_1.expect)(result.exitCode).to.equal(0); (0, chai_1.expect)(result.platform).to.equal('test-platform'); (0, chai_1.expect)(result.command).to.equal(command); (0, chai_1.expect)(result.executionTime).to.be.a('number'); }); it('应该正确处理命令执行失败', async function () { try { await executor.execute('nonexistent-command-12345'); // 如果没有抛出错误,则测试失败 chai_1.expect.fail('应该抛出错误'); } catch (error) { (0, chai_1.expect)(error).to.be.an('error'); // 检查是否是MonitorError if (error.code) { (0, chai_1.expect)(error.code).to.be.oneOf(['COMMAND_FAILED', 'FILE_NOT_FOUND']); } } }); it('应该正确处理有stderr输出但成功的命令', async function () { // 某些命令会向stderr输出信息但仍然成功 const command = process.platform === 'win32' ? 'echo error>&2 & echo success' : 'echo "error" >&2; echo "success"'; const result = await executor.execute(command); (0, chai_1.expect)(result.stdout.trim()).to.include('success'); (0, chai_1.expect)(result.exitCode).to.equal(0); }); }); describe('超时处理', function () { it('应该在超时后终止命令', async function () { this.timeout(3000); // 设置测试超时 const shortTimeout = new command_executor_1.CommandExecutor('test-platform', { timeout: 100 }); // 创建一个会运行较长时间的命令 const command = process.platform === 'win32' ? 'ping -n 10 127.0.0.1' : 'sleep 5'; try { await shortTimeout.execute(command); chai_1.expect.fail('应该抛出超时错误'); } catch (error) { (0, chai_1.expect)(error).to.be.an('error'); if (error.code) { (0, chai_1.expect)(error.code).to.equal('TIMEOUT'); } } }); }); describe('输出处理', function () { it('应该正确处理大量输出', async function () { // 生成大量输出的命令 const command = process.platform === 'win32' ? 'for /L %i in (1,1,10) do @echo Line %i' : 'for i in {1..10}; do echo "Line $i"; done'; const result = await executor.execute(command); const lines = result.stdout.trim().split('\n'); (0, chai_1.expect)(lines.length).to.be.at.least(5); // 至少有一些行 (0, chai_1.expect)(result.exitCode).to.equal(0); }); it('应该正确处理空输出', async function () { const command = process.platform === 'win32' ? 'echo.' : 'true'; const result = await executor.execute(command); (0, chai_1.expect)(result.exitCode).to.equal(0); }); }); describe('平台特定命令', function () { it('应该能够执行平台特定的系统信息命令', async function () { let command; switch (process.platform) { case 'darwin': command = 'uname -s'; break; case 'linux': command = 'uname -s'; break; case 'win32': command = 'ver'; break; default: this.skip(); return; } const result = await executor.execute(command); (0, chai_1.expect)(result.stdout).to.be.a('string'); (0, chai_1.expect)(result.stdout.length).to.be.greaterThan(0); (0, chai_1.expect)(result.exitCode).to.equal(0); }); }); describe('配置选项', function () { it('应该使用自定义配置', async function () { const customExecutor = new command_executor_1.CommandExecutor('custom-platform', { timeout: 1000, encoding: 'utf8' }); const command = process.platform === 'win32' ? 'echo test' : 'echo "test"'; const result = await customExecutor.execute(command); (0, chai_1.expect)(result.stdout.trim()).to.equal('test'); (0, chai_1.expect)(result.platform).to.equal('custom-platform'); }); }); describe('并发执行', function () { it('应该能够并发执行多个命令', async function () { const commands = [ process.platform === 'win32' ? 'echo 1' : 'echo "1"', process.platform === 'win32' ? 'echo 2' : 'echo "2"', process.platform === 'win32' ? 'echo 3' : 'echo "3"' ]; const promises = commands.map(cmd => executor.execute(cmd)); const results = await Promise.all(promises); results.forEach((result, index) => { (0, chai_1.expect)(result.stdout.trim()).to.equal((index + 1).toString()); (0, chai_1.expect)(result.exitCode).to.equal(0); }); }); }); describe('流式执行', function () { it('应该在禁用 shell 时正确处理包含空格的命令', async function () { const script = 'console.log("stream output")'; const command = executor.buildCommand(process.execPath, ['-e', script]); const chunks = []; const result = await executor.executeStream(command, (data) => { chunks.push(data); }, { shell: false }); (0, chai_1.expect)(result.exitCode).to.equal(0); (0, chai_1.expect)(chunks.join('')).to.contain('stream output'); }); }); }); describe('CommandExecutor — Deno 兼容性:非标准异常处理', function () { it('T023: 应将字符串类型的非标准异常统一捕获为 MonitorError(COMMAND_FAILED)', async function () { const executor = new command_executor_1.CommandExecutor('test-platform'); const internal = executor; // 模拟 Deno 兼容层抛出非 Error 实例(字符串) internal.executeWithTimeout = async () => { // eslint-disable-next-line @typescript-eslint/no-throw-literal throw 'Deno compat layer: exec failed unexpectedly'; }; try { await executor.execute('echo test'); chai_1.expect.fail('应该抛出错误'); } catch (error) { (0, chai_1.expect)(error).to.be.instanceOf(errors_1.MonitorError); (0, chai_1.expect)(error.code).to.equal(errors_1.ErrorCode.COMMAND_FAILED); } }); it('T023: 应将自定义对象类型的非标准异常统一捕获为 MonitorError(COMMAND_FAILED)', async function () { const executor = new command_executor_1.CommandExecutor('test-platform'); const internal = executor; // 模拟 Deno 兼容层抛出普通对象(非 Error 实例) internal.executeWithTimeout = async () => { // eslint-disable-next-line @typescript-eslint/no-throw-literal throw { message: 'DENO_EXEC_ERROR', code: 'ERR_DENO_COMPAT' }; }; try { await executor.execute('echo test'); chai_1.expect.fail('应该抛出错误'); } catch (error) { (0, chai_1.expect)(error).to.be.instanceOf(errors_1.MonitorError); (0, chai_1.expect)(error.code).to.equal(errors_1.ErrorCode.COMMAND_FAILED); } }); }); //# sourceMappingURL=command-executor.test.js.map