import test from 'brittle' import { parseProcStat, parseProcStatus, processMatchesQuery, processMatchesFilter, sortProcesses, listProcesses, _resetProcessMonitorForTests, } from '../server/services/processes.js' import { validateMethodArgs } from '../shared/schema.js' import { isProcessCollectorEnabled } from '../server/services/collectors/processes.js' test('parseProcStat extracts comm and counters', (t) => { const raw = '1 (systemd) S 0 1 1 0 -1 4194560 123 0 0 0 10 20 0 0 20 0 1 0 12345 1000000 100 18446744073709551615 1 1 0 0 0 0 0 0 0 0 0 0 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0' const st = parseProcStat(raw) t.ok(st) t.is(st.name, 'systemd') t.is(st.state, 'S') t.is(st.ppid, 0) t.is(st.utime, 10) t.is(st.stime, 20) }) test('parseProcStatus reads uid and threads', (t) => { const s = parseProcStatus('Name:\tfoo\nUid:\t1000\t1000\t1000\t1000\nThreads:\t4\nVmRSS:\t2048 kB\n') t.is(s.uid, 1000) t.is(s.threads, 4) t.is(s.vmRssKb, 2048) }) test('process filter + query helpers', (t) => { const row = { pid: 42, name: 'nginx', cmdline: '/usr/sbin/nginx -g daemon', user: 'www', stateLabel: 'running', cpu: 12, mem: 200, io: 3, kernel: false, } t.ok(processMatchesQuery(row, 'nginx')) t.ok(processMatchesQuery(row, '42')) t.absent(processMatchesQuery(row, 'postgres')) t.ok(processMatchesFilter(row, 'running')) t.ok(processMatchesFilter(row, 'highcpu')) t.ok(processMatchesFilter(row, 'highmem')) t.ok(processMatchesFilter(row, 'user')) t.absent(processMatchesFilter(row, 'zombie')) }) test('sortProcesses orders by cpu desc', (t) => { const rows = [ { pid: 1, name: 'a', cpu: 1, mem: 9 }, { pid: 2, name: 'b', cpu: 9, mem: 1 }, ] const sorted = sortProcesses(rows, 'cpu', 'desc') t.is(sorted[0].pid, 2) t.is(sortProcesses(rows, 'rss', 'desc')[0].pid, 1) }) test('validateMethodArgs listProcesses', (t) => { const ok = validateMethodArgs('listProcesses', { sort: 'cpu', limit: 50 }) t.ok(ok.ok) t.is(ok.args.sort, 'cpu') const bad = validateMethodArgs('listProcesses', { sort: 'nope' }) t.absent(bad.ok) }) test('listProcesses returns shape', (t) => { _resetProcessMonitorForTests() const res = listProcesses({ limit: 20, sort: 'cpu' }) t.ok(res.ok) t.ok(res.summary) t.ok(Array.isArray(res.processes)) if (process.platform === 'linux') { t.ok(res.supported) t.ok(res.summary.total > 0) // Second call should populate CPU rates after prev sample _resetProcessMonitorForTests() listProcesses({ limit: 5 }) const again = listProcesses({ limit: 5 }) t.ok(again.processes.length > 0) t.ok(again.processes[0].pid > 0) t.ok(again.processes[0].name) } else { t.absent(res.supported) } }) test('isProcessCollectorEnabled defaults on linux', (t) => { const prev = process.env.PEARDATA_PROCESSES delete process.env.PEARDATA_PROCESSES if (process.platform === 'linux') t.ok(isProcessCollectorEnabled()) else t.absent(isProcessCollectorEnabled()) process.env.PEARDATA_PROCESSES = '0' t.absent(isProcessCollectorEnabled()) process.env.PEARDATA_PROCESSES = '1' t.ok(isProcessCollectorEnabled()) if (prev == null) delete process.env.PEARDATA_PROCESSES else process.env.PEARDATA_PROCESSES = prev })