"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const chai_1 = require("chai");
const os_1 = __importDefault(require("os"));
const macos_adapter_1 = require("../../../src/adapters/macos-adapter");
const errors_1 = require("../../../src/types/errors");
describe('MacOSAdapter 内部解析逻辑', () => {
    it('应当将 RSS 转换为字节并保留内存百分比', () => {
        const adapter = new macos_adapter_1.MacOSAdapter();
        const internal = adapter;
        const data = {
            summary: '123 1 20480 12.5 3.4 R user',
            command: '/usr/bin/example --flag',
            start: 'Mon Mar 11 10:00:00 2024'
        };
        const result = internal.parseProcessInfo(data, 123);
        (0, chai_1.expect)(result.pid).to.equal(123);
        (0, chai_1.expect)(result.ppid).to.equal(1);
        (0, chai_1.expect)(result.command).to.equal('/usr/bin/example --flag');
        (0, chai_1.expect)(result.memoryUsage).to.equal(20480 * 1024);
        (0, chai_1.expect)(result.memoryPercentage).to.be.closeTo(3.4, 0.0001);
        (0, chai_1.expect)(result.cpuUsage).to.be.closeTo(12.5, 0.0001);
        (0, chai_1.expect)(result.state).to.equal('R');
    });
    it('应当根据 vm_stat 中的页面大小正确计算内存', () => {
        const adapter = new macos_adapter_1.MacOSAdapter();
        const internal = adapter;
        const vmStatOutput = [
            'Mach Virtual Memory Statistics: (page size of 16384 bytes)',
            'Pages free:                               100.',
            'Pages active:                             200.',
            'Pages inactive:                           300.',
            'Pages wired down:                         400.',
            'Pages occupied by compressor:             50.',
            ''
        ].join('\n');
        const totalMem = (16 * 1024 * 1024 * 1024).toString();
        const pressureOutput = 'System-wide memory pressure: warn';
        const result = internal.parseMemoryInfo(vmStatOutput, totalMem, pressureOutput);
        const pageSize = 16384;
        (0, chai_1.expect)(result.total).to.equal(16 * 1024 * 1024 * 1024);
        (0, chai_1.expect)(result.free).to.equal(100 * pageSize);
        (0, chai_1.expect)(result.active).to.equal(200 * pageSize);
        (0, chai_1.expect)(result.inactive).to.equal(300 * pageSize);
        (0, chai_1.expect)(result.wired).to.equal(400 * pageSize);
        (0, chai_1.expect)(result.compressed).to.equal(50 * pageSize);
        (0, chai_1.expect)(result.used).to.equal((200 + 400 + 50) * pageSize);
        (0, chai_1.expect)(result.available).to.equal(result.total - result.used);
        (0, chai_1.expect)(result.pressure.level).to.equal('high');
    });
    it('应当正确解析 iostat 输出的磁盘数据', () => {
        const adapter = new macos_adapter_1.MacOSAdapter();
        const internal = adapter;
        const iostatOutput = `
            disk0           disk1
    KB/t tps  MB/s     KB/t tps  MB/s
    16.00   1  0.01    32.00   2  0.06
    `;
        const ioResult = internal.parseDiskIO(iostatOutput);
        const statsResult = internal.parseDiskStats(iostatOutput);
        (0, chai_1.expect)(ioResult).to.have.lengthOf(2);
        (0, chai_1.expect)(ioResult[0].device).to.equal('disk0');
        (0, chai_1.expect)(ioResult[0].kbPerTransfer).to.be.closeTo(16, 0.001);
        (0, chai_1.expect)(ioResult[0].mbPerSec).to.be.closeTo(0.01, 0.0001);
        (0, chai_1.expect)(ioResult[0].readSpeed).to.be.closeTo(0.01 * 1024 * 1024, 1e-6);
        (0, chai_1.expect)(statsResult[0].device).to.equal('disk0');
        (0, chai_1.expect)(statsResult[0].readCount).to.equal(1);
        (0, chai_1.expect)(statsResult[0].readSpeed).to.be.closeTo(0.01 * 1024 * 1024, 1e-6);
        (0, chai_1.expect)(statsResult[0].writeBytes).to.equal(0);
    });
    it('应当在解析进程环境变量时保留带空格的值', () => {
        const adapter = new macos_adapter_1.MacOSAdapter();
        const internal = adapter;
        const envOutput = [
            '123 ?? Ss 0:00.01 /usr/bin/node --inspect',
            'PATH=/usr/bin:/bin HOME=/Users/test PID=1234 APP_NAME=My App With Spaces LANG=en_US.UTF-8',
            'LOG_LEVEL="debug mode" EMPTY_VAR= NEXT=final'
        ].join('\n');
        const result = internal.parseEnvironment(envOutput);
        (0, chai_1.expect)(result.PATH).to.equal('/usr/bin:/bin');
        (0, chai_1.expect)(result.HOME).to.equal('/Users/test');
        (0, chai_1.expect)(result).to.not.have.property('PID');
        (0, chai_1.expect)(result.APP_NAME).to.equal('My App With Spaces');
        (0, chai_1.expect)(result.LANG).to.equal('en_US.UTF-8');
        (0, chai_1.expect)(result.LOG_LEVEL).to.equal('"debug mode"');
        (0, chai_1.expect)(result.EMPTY_VAR).to.equal('');
        (0, chai_1.expect)(result.NEXT).to.equal('final');
    });
    it('应当从 ifconfig 输出中提取 MAC 地址', () => {
        const adapter = new macos_adapter_1.MacOSAdapter();
        const internal = adapter;
        const ifconfigOutput = [
            'lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384',
            '\tinet 127.0.0.1 netmask 0xff000000',
            'en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500',
            '\tether f0:18:98:73:ad:10',
            '\tinet 192.168.1.2 netmask 0xffffff00 broadcast 192.168.1.255',
            '\tinet6 fe80::c86:abcd:ef12%en0 prefixlen 64'
        ].join('\n');
        const result = internal.parseNetworkInterfaces(ifconfigOutput);
        const en0 = result.find((iface) => iface.name === 'en0');
        (0, chai_1.expect)(en0).to.exist;
        (0, chai_1.expect)(en0.mac).to.equal('f0:18:98:73:ad:10');
        (0, chai_1.expect)(en0.addresses).to.have.lengthOf(2);
    });
    it('应当解析系统信息并计算启动时间', () => {
        const adapter = new macos_adapter_1.MacOSAdapter();
        const internal = adapter;
        const originalUptime = os_1.default.uptime;
        os_1.default.uptime = () => 1234;
        try {
            const uname = 'Darwin MacBook-Pro 23.4.0 Darwin Kernel Version';
            const uptime = ' 10:22 up  3:24,  2 users, load averages: 1.23 0.56 0.42';
            const loadavg = '{ 1.23 0.56 0.42 }';
            const swVers = 'ProductName: macOS\nProductVersion: 14.4\nBuildVersion: 23E214';
            const result = internal.parseSystemInfo(uname, uptime, loadavg, swVers);
            (0, chai_1.expect)(result.platform).to.equal('darwin');
            (0, chai_1.expect)(result.version).to.equal(swVers.trim());
            (0, chai_1.expect)(result.loadAverage.load1).to.be.closeTo(1.23, 0.0001);
            (0, chai_1.expect)(result.uptimeSeconds).to.equal(1234);
            (0, chai_1.expect)(result.bootTime).to.be.closeTo(Date.now() - 1234 * 1000, 50);
        }
        finally {
            os_1.default.uptime = originalUptime;
        }
    });
    it('应当解析 netstat 输出中的收发字节统计', () => {
        const adapter = new macos_adapter_1.MacOSAdapter();
        const internal = adapter;
        const netstatOutput = [
            'Name  Mtu   Net/Dest  Address             Ibytes  Obytes  Ipackets  Ierrs  Opackets  Oerrs  Collisions',
            'en0   1500  link#5    f0:18:98:73:ad:10   42      1       4096      84     0         8192    2'
        ].join('\n');
        const stats = internal.parseNetworkStats(netstatOutput);
        (0, chai_1.expect)(stats).to.have.lengthOf(1);
        (0, chai_1.expect)(stats[0].interface).to.equal('en0');
        (0, chai_1.expect)(stats[0].rxPackets).to.equal(42);
        (0, chai_1.expect)(stats[0].rxErrors).to.equal(1);
        (0, chai_1.expect)(stats[0].rxBytes).to.equal(4096);
        (0, chai_1.expect)(stats[0].txPackets).to.equal(84);
        (0, chai_1.expect)(stats[0].txBytes).to.equal(8192);
        (0, chai_1.expect)(stats[0].collisions).to.equal(2);
    });
    it('应当从 route 输出中解析默认网关', () => {
        const adapter = new macos_adapter_1.MacOSAdapter();
        const internal = adapter;
        const routeOutput = [
            '   route to: default',
            'destination: default',
            '       mask: default',
            '    gateway: 192.168.1.1',
            '  interface: en0',
            '      flags: <UP,GATEWAY,DONE,STATIC>'
        ].join('\n');
        const result = internal.parseDefaultGateway(routeOutput);
        (0, chai_1.expect)(result).to.deep.equal({ gateway: '192.168.1.1', interface: 'en0' });
    });
    it('T022: getCPUInfo() 在 sysctl 命令全部失败时应降级到 os.cpus() 数据而非抛出异常', async () => {
        const adapter = new macos_adapter_1.MacOSAdapter();
        const internal = adapter;
        // stub executeCommand 使所有 sysctl 命令失败
        internal.executeCommand = async () => {
            throw new errors_1.MonitorError('sysctl 不可用', errors_1.ErrorCode.COMMAND_FAILED, 'darwin');
        };
        const result = await adapter.getCPUInfo();
        (0, chai_1.expect)(result).to.be.an('object');
        (0, chai_1.expect)(result.cores).to.be.a('number').and.to.be.greaterThan(0);
        (0, chai_1.expect)(result.threads).to.be.a('number').and.to.be.greaterThan(0);
        (0, chai_1.expect)(result.model).to.be.a('string').and.to.have.length.greaterThan(0);
    });
    it('在 top 失败时应回退到 iostat 获取 CPU 使用率', async () => {
        const adapter = new macos_adapter_1.MacOSAdapter();
        const internal = adapter;
        const commands = [];
        internal.executeCommand = async (command) => {
            commands.push(command);
            if (command.startsWith('top')) {
                throw new Error('top failed');
            }
            if (command.startsWith('iostat')) {
                return {
                    stdout: '          cpu\n us sy id\n 12 5 83\n',
                    stderr: '',
                    exitCode: 0,
                    platform: 'darwin',
                    executionTime: 1,
                    command
                };
            }
            throw new Error(`unexpected command: ${command}`);
        };
        const usage = await adapter.getCPUUsage();
        (0, chai_1.expect)(commands).to.deep.equal(['top -l 1 -n 0', 'iostat -c 1']);
        (0, chai_1.expect)(usage.overall).to.be.closeTo(17, 0.0001);
        (0, chai_1.expect)(usage.user).to.be.closeTo(12, 0.0001);
        (0, chai_1.expect)(usage.system).to.be.closeTo(5, 0.0001);
        (0, chai_1.expect)(usage.idle).to.be.closeTo(83, 0.0001);
    });
    it('powermetrics 无法执行时应返回不支持错误', async () => {
        const adapter = new macos_adapter_1.MacOSAdapter();
        const internal = adapter;
        internal.executeCommand = async () => {
            throw Object.assign(new Error('permission denied'), { code: 'EACCES' });
        };
        try {
            await adapter.getCPUTemperature();
            chai_1.expect.fail('should not succeed');
        }
        catch (error) {
            (0, chai_1.expect)(error).to.be.instanceOf(errors_1.MonitorError);
            const monitorError = error;
            (0, chai_1.expect)(monitorError.code).to.equal(errors_1.ErrorCode.PLATFORM_NOT_SUPPORTED);
            (0, chai_1.expect)(monitorError.platform).to.equal('darwin');
        }
    });
    it('读取文件权限不足时应抛出权限错误', async () => {
        const adapter = new macos_adapter_1.MacOSAdapter();
        const internal = adapter;
        internal.executeCommand = async () => {
            throw Object.assign(new Error('permission denied'), { code: 'EACCES' });
        };
        try {
            await adapter.readFile('/private/secret');
            chai_1.expect.fail('should not succeed');
        }
        catch (error) {
            (0, chai_1.expect)(error).to.be.instanceOf(errors_1.MonitorError);
            const monitorError = error;
            (0, chai_1.expect)(monitorError.code).to.equal(errors_1.ErrorCode.PERMISSION_DENIED);
            (0, chai_1.expect)(monitorError.details.path).to.equal('/private/secret');
        }
    });
});
//# sourceMappingURL=macos-adapter.test.js.map