106 lines
3.2 KiB
JavaScript
106 lines
3.2 KiB
JavaScript
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
|
|
})
|