diff options
| author | Danilo M. <danix@danix.xyz> | 2026-10-13 11:35:00 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-10-13 11:35:00 +0200 |
| commit | 3943e08dabe684b409a3ac99c9371fbeb5df5cdb (patch) | |
| tree | 7dcedbb2d64a04e59ab239a8c40c04f0f0cf29aa /test/test_data.lua | |
| parent | b2fe3f493efc12dd300f0e2b2ede5660ee70c193 (diff) | |
| download | conky-theme-udt-3943e08dabe684b409a3ac99c9371fbeb5df5cdb.tar.gz conky-theme-udt-3943e08dabe684b409a3ac99c9371fbeb5df5cdb.zip | |
The quickshell island's performance panel now shows CPU, RAM,
temperatures, the GPU, disks and network, and warns from the status
pill when something runs hot, fills up, or the public IP drifts from
the pinned one. Two dashboards drawing the same numbers would drift
apart, so the four widgets go, with the disks and public IP samplers.
The island keeps writing ~/.cache/udt/pubip.txt in the same format.
The freed space is left empty for the user to rearrange.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Diffstat (limited to 'test/test_data.lua')
| -rw-r--r-- | test/test_data.lua | 263 |
1 files changed, 0 insertions, 263 deletions
diff --git a/test/test_data.lua b/test/test_data.lua index 549ce40..37a302e 100644 --- a/test/test_data.lua +++ b/test/test_data.lua @@ -20,141 +20,7 @@ local function read(path) return s end --- cpu_times: total and idle jiffies from the aggregate "cpu " line. -local total, idle = data.cpu_times(read('test/fixtures/proc_stat')) --- 209094+2199+135469+11604898+24408+0+946 = 11977014 -assert(total == 11977014, 'cpu total, got ' .. tostring(total)) --- idle field is the 4th value, 11604898; iowait (24408) counts as idle too -assert(idle == 11629306, 'cpu idle, got ' .. tostring(idle)) - --- mem_info: values in kB, as the file gives them. -local mem = data.mem_info(read('test/fixtures/proc_meminfo')) -assert(mem.total == 31943076, 'mem total, got ' .. tostring(mem.total)) -assert(mem.available == 25627088, 'mem available, got ' .. tostring(mem.available)) --- used is total minus available, which is what a user means by "used" -assert(mem.used == 6315988, 'mem used, got ' .. tostring(mem.used)) - --- millidegrees: hwmon temp*_input is millidegrees C, rounded to whole degrees. -assert(data.millidegrees(read('test/fixtures/temp1_input')) == 53, - 'temp, got ' .. tostring(data.millidegrees(read('test/fixtures/temp1_input')))) --- A missing or unreadable sensor must yield nil, not an error and not 0: --- 0 degrees is a plausible reading and would be indistinguishable from failure. -assert(data.millidegrees(nil) == nil, 'nil input must give nil') -assert(data.millidegrees('') == nil, 'empty input must give nil') -assert(data.millidegrees('garbage') == nil, 'unparseable input must give nil') - --- CPU load is a delta between two samples, so the counter holds state. --- The first call has no previous sample and must report nil, not a number: --- any number it invented would be wrong, and 100% on startup looks like a --- real spike. -local c = data.new_cpu_counter() -assert(c:sample(1000, 900) == nil, 'first sample must give nil') - --- Second sample: 100 more total jiffies, 50 of them idle, so 50% busy. --- Held in a local first: calling sample() again inside the assert message would --- advance the counter a third time. -local busy = c:sample(1100, 950) -assert(busy == 50.0, 'second sample, got ' .. tostring(busy)) - --- A counter that did not advance means no elapsed time, not 0% load. -local c2 = data.new_cpu_counter() -c2:sample(1000, 900) -assert(c2:sample(1000, 900) == nil, 'zero delta must give nil, not a division by zero') - --- === Per-core CPU ========================================================= --- The aggregate line answers "how busy is the machine"; the equaliser needs --- one entry per core. Both come from the same file, so they are parsed by the --- same rules and differ only in which lines they read. -local percore = read('test/fixtures/proc_stat_percore') -local cores = data.per_cpu_times(percore) -assert(#cores == 4, 'one entry per cpuN line, got ' .. tostring(#cores)) - --- cpu0: 6441+24+3225+1056496+1932+0+760 = 1068878 total, idle+iowait = 1058428 -assert(cores[1].total == 1068878, 'core 0 total, got ' .. tostring(cores[1].total)) -assert(cores[1].idle == 1058428, 'core 0 idle, got ' .. tostring(cores[1].idle)) - --- Ordering matters: bar N must be core N, so the list follows the file. -assert(cores[2].total == 1066406, 'core 1 total, got ' .. tostring(cores[2].total)) - --- The aggregate 'cpu ' line must NOT be counted as a core: it would draw a --- bar for the aggregate line showing the average, which looks like a real core. -for i, c in ipairs(cores) do - assert(c.total < 2000000, 'entry ' .. i .. ' looks like the aggregate line') -end - --- A counter per core is just another instance, which is why new_cpu_counter --- holds its own previous sample rather than using a module-level one. -local c0 = data.new_cpu_counter() -assert(c0:sample(cores[1].total, cores[1].idle) == nil, 'first sample is nil') -local busy = c0:sample(cores[1].total + 100, cores[1].idle + 25) -assert(busy == 75.0, 'second sample 75%, got ' .. tostring(busy)) - --- Malformed input yields an empty list, never an error: a raise here is a --- blank dashboard. -assert(#data.per_cpu_times('') == 0, 'empty input gives an empty list') -assert(#data.per_cpu_times('garbage\nlines\n') == 0, 'garbage gives an empty list') -assert(#data.per_cpu_times(nil) == 0, 'nil gives an empty list') --- A truncated line (fewer than the 5 fields the maths needs) is skipped --- rather than producing a nonsense total. -assert(#data.per_cpu_times('cpu0 1 2\n') == 0, 'a short line is skipped') - -- === Cache files ========================================================== --- df -P guarantees one line per mount with the mountpoint LAST, which is why --- the parser takes the last field rather than the sixth: an NFS device is --- 'server:/export' and a device name can carry surprises, but the mountpoint --- is always at the end. -local fs = data.df_parse(read('test/fixtures/df_output')) -assert(#fs == 6, 'one entry per mount, got ' .. tostring(#fs)) -assert(fs[1].mount == '/', 'first mount, got ' .. tostring(fs[1].mount)) -assert(fs[1].pct == 84, 'root percent, got ' .. tostring(fs[1].pct)) -assert(fs[1].size == 263174213632, 'root size in bytes, got ' .. tostring(fs[1].size)) -assert(fs[1].used == 208111570944, 'root used, got ' .. tostring(fs[1].used)) - --- Available is READ, never derived as size - used: the two differ by the --- root-reserved blocks, about 5%, which on this root is some 13GB that exists --- but cannot be used. A card claiming that space is free would be lying. -assert(fs[1].avail == 41746907136, 'root available, got ' .. tostring(fs[1].avail)) -assert(fs[1].size - fs[1].used ~= fs[1].avail, - 'the fixture must exercise the reserved-block gap, or this assertion proves nothing') - --- fs[3] is /dev/sda1: a device name ENDING IN A DIGIT, next to a numeric --- column. A parser counting fields from the left, or matching digits without --- anchoring, reads the partition number as a size. -assert(fs[3].mount == '/data', 'sda1 mount, got ' .. tostring(fs[3].mount)) -assert(fs[3].dev == '/dev/sda1', 'sda1 device, got ' .. tostring(fs[3].dev)) -assert(fs[3].size == 983350091776, 'sda1 size, got ' .. tostring(fs[3].size)) -assert(fs[3].used == 547869650944, 'sda1 used, got ' .. tostring(fs[3].used)) -assert(fs[3].avail == 385453473792, 'sda1 available, got ' .. tostring(fs[3].avail)) -assert(fs[3].pct == 59, 'sda1 percent, got ' .. tostring(fs[3].pct)) -assert(fs[3].host == nil, 'a local device has no host') - --- A full filesystem reports zero available, which is a real reading. -assert(fs[6].avail == 0, 'a full mount has 0 available, got ' .. tostring(fs[6].avail)) - --- The NFS rows are the reason the last field matters: a colon in the device --- would break a parser splitting on punctuation. -assert(fs[4].mount == '/mnt/nfs/Library', 'nfs mount, got ' .. tostring(fs[4].mount)) -assert(fs[4].pct == 79, 'nfs percent, got ' .. tostring(fs[4].pct)) - --- The device field carries the server, which is what lets the disks card --- label the two shares without an address hardcoded in the repo. -assert(fs[4].host == 'server-a', 'nfs host, got ' .. tostring(fs[4].host)) -assert(fs[1].host == nil, 'a local device has no host, got ' .. tostring(fs[1].host)) - --- A full filesystem is a real state, not an error. -assert(fs[6].pct == 100, 'a full mount reads 100, got ' .. tostring(fs[6].pct)) - --- The header line must not become a row. -for _, e in ipairs(fs) do - assert(e.mount ~= 'on' and e.mount ~= 'Mounted', 'the header leaked in as a row') -end - -assert(#data.df_parse('') == 0, 'empty input gives an empty list') -assert(#data.df_parse(nil) == 0, 'nil gives an empty list') --- A header with no rows is what a failed df produces. -assert(#data.df_parse('Filesystem 1-blocks Used Available Capacity Mounted on\n') == 0, - 'a header alone gives an empty list') - -- du -sh: total first, then children largest-first. The suffixes must be -- converted, not string-sorted: '1.1G' outranks '245M' numerically and loses -- to it alphabetically. @@ -199,46 +65,6 @@ assert(cut == string.rep('\u{00E9}', 9) .. '\u{2026}', assert(card.truncate(nil, 10) == '', 'nil truncates to empty') assert(card.truncate('abc', 0) == '', 'a zero limit gives empty') --- === Network rate ========================================================= --- Interface byte counters are cumulative, so a rate is a delta over elapsed --- time. The first call has no previous sample and must report nil: any number --- it invented would be wrong, and a spike at startup looks real. -local r = data.new_rate_counter() -assert(r:sample(1000, 100) == nil, 'first sample must give nil') - --- 2048 bytes over 2 seconds is 1024 B/s. -local rate = r:sample(3048, 102) -assert(rate == 1024, 'second sample, got ' .. tostring(rate)) - --- A counter that went backwards means a wrap or an interface reset. It must --- clamp to zero, never produce the huge positive an unsigned wrap implies: --- one bogus sample poisons the shared autoscale for the whole window. -local r2 = data.new_rate_counter() -r2:sample(5000, 100) -assert(r2:sample(10, 102) == 0, 'a counter reset must give 0') - --- Two samples inside the same clock second. os.time() has whole-second --- resolution against a 2s draw interval, so this happens in normal operation --- and must not divide by zero. -local r3 = data.new_rate_counter() -r3:sample(1000, 500) -local same_second = r3:sample(2000, 500) -assert(same_second ~= nil and same_second >= 0, - 'a zero time delta must fall back to the draw interval, got ' .. tostring(same_second)) - --- A missing interface reads nil, which must propagate rather than raise. -local r4 = data.new_rate_counter() -assert(r4:sample(nil, 100) == nil, 'a nil byte count gives nil') - --- The fallback interval is a constructor argument, and the widget passes --- conky's real update_interval rather than letting it default. That is the --- path that ships, so it is the path that gets a test: at a 5s interval the --- same 2048 bytes must read as 409.6 B/s, not 1024. -local r5 = data.new_rate_counter(5) -r5:sample(1000, 100) -assert(r5:sample(3048, 100) == 2048 / 5, - 'an explicit fallback interval must be used, got ' .. tostring(r5:sample(3048, 100))) - -- === kv_parse ============================================================= -- The slackware sampler writes 'key value' lines. The format is deliberately -- dumber than the data: epochs stay integers rather than becoming formatted @@ -260,68 +86,6 @@ assert(type(data.kv_parse('')) == 'table', 'empty input gives a table') assert(type(data.kv_parse(nil)) == 'table', 'nil gives a table') assert(data.kv_parse('keyonly\n').keyonly == nil, 'a line with no value is skipped') --- === Hardware identification ============================================== --- Both strings are constant for the machine's life, so the widget memoizes --- them. What is tested here is the stripping, which must be a rule rather --- than a special case for one host: the Intel fixture exists to prove it. -assert(data.cpu_model(read('test/fixtures/proc_cpuinfo')) == 'Ryzen 7 9700X', - 'amd cpu, got ' .. tostring(data.cpu_model(read('test/fixtures/proc_cpuinfo')))) -assert(data.cpu_model(read('test/fixtures/proc_cpuinfo_intel')) == 'Core i7-8700K', - 'intel cpu, got ' .. tostring(data.cpu_model(read('test/fixtures/proc_cpuinfo_intel')))) - --- Unparseable input yields nil, so the card shows nothing rather than a --- half-stripped string. -assert(data.cpu_model('') == nil, 'empty cpuinfo gives nil') -assert(data.cpu_model(nil) == nil, 'nil cpuinfo gives nil') -assert(data.cpu_model('processor\t: 0\n') == nil, 'cpuinfo with no model name gives nil') - --- The board is two sysfs files joined, with the vendor's corporate suffix --- dropped: it is boilerplate on every board and costs a third of the row. -assert(data.board_name('Gigabyte Technology Co., Ltd.\n', 'X870 EAGLE WIFI7\n') - == 'Gigabyte X870 EAGLE WIFI7', - 'board, got ' .. tostring(data.board_name('Gigabyte Technology Co., Ltd.\n', 'X870 EAGLE WIFI7\n'))) -assert(data.board_name('ASUSTeK COMPUTER INC.\n', 'PRIME B650-PLUS\n') - == 'ASUSTeK PRIME B650-PLUS', - 'asus board, got ' .. tostring(data.board_name('ASUSTeK COMPUTER INC.\n', 'PRIME B650-PLUS\n'))) - --- A machine that reports one and not the other shows what it has. -assert(data.board_name(nil, 'X870 EAGLE WIFI7\n') == 'X870 EAGLE WIFI7', - 'name alone, got ' .. tostring(data.board_name(nil, 'X870 EAGLE WIFI7\n'))) -assert(data.board_name('Gigabyte\n', nil) == 'Gigabyte', 'vendor alone') -assert(data.board_name(nil, nil) == nil, 'neither gives nil') - --- A virtual machine reports placeholder DMI strings. Showing 'To be filled by --- O.E.M.' as the motherboard is worse than showing nothing. -assert(data.board_name('To Be Filled By O.E.M.\n', 'To Be Filled By O.E.M.\n') == nil, - 'placeholder DMI gives nil') - --- Three Intel forms the single fixture does not cover. The first fixture --- happens to carry a literal 'CPU' before the clock, so a pattern requiring --- that token passes the fixture and still leaves '@ 2.40GHz' on the card for --- every other Intel part. These exist so the stripping stays a rule. -assert(data.cpu_model('model name\t: Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GHz\n') - == 'Xeon E5-2680 v4', - 'xeon, got ' .. tostring(data.cpu_model('model name\t: Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GHz\n'))) -assert(data.cpu_model('model name\t: 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz\n') - == 'Core i7-1165G7', - 'tiger lake, got ' .. tostring(data.cpu_model('model name\t: 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz\n'))) -assert(data.cpu_model('model name\t: AMD Ryzen 9 7950X3D 16-Core Processor\n') - == 'Ryzen 9 7950X3D', - 'x3d, got ' .. tostring(data.cpu_model('model name\t: AMD Ryzen 9 7950X3D 16-Core Processor\n'))) - --- === Interface address ==================================================== --- The fixture uses TEST-NET-1 (192.0.2.0/24, RFC 5737). This repository is --- public: no real LAN address belongs in it, and no test may assert one. -local addr = data.iface_addr_parse(read('test/fixtures/ip_addr')) -assert(addr == '192.0.2.15', 'lan address, got ' .. tostring(addr)) - --- A down interface has no inet line. nil, so the card shows '--' rather than --- a stale or invented address. -assert(data.iface_addr_parse('5: br0: <BROADCAST,MULTICAST> mtu 1500 state DOWN\n') == nil, - 'a down interface gives nil') -assert(data.iface_addr_parse('') == nil, 'empty gives nil') -assert(data.iface_addr_parse(nil) == nil, 'nil gives nil') - -- === Calendar ============================================================= -- The fixture uses generic event titles. This repository is public: a real -- appointment names a real person or a real appointment, and neither belongs @@ -479,33 +243,6 @@ assert(up.upgrade == 3 and up.bump == 1 and up.current == 46 and up.missing == 1 'updates summary') assert(data.nvtable_parse('') == nil, 'updates: empty cache is nil') --- drm_vram_parse: xe clients counted once across their fds, other drivers --- skipped, units honoured. -local fdinfo = table.concat({ - '/proc/1/fdinfo/5:drm-driver:\txe', - '/proc/1/fdinfo/5:drm-client-id:\t7', - '/proc/1/fdinfo/5:drm-resident-vram0:\t1024 KiB', - '/proc/1/fdinfo/6:drm-driver:\txe', - '/proc/1/fdinfo/6:drm-client-id:\t7', - '/proc/1/fdinfo/6:drm-resident-vram0:\t1024 KiB', - '/proc/2/fdinfo/9:drm-driver:\txe', - '/proc/2/fdinfo/9:drm-client-id:\t8', - '/proc/2/fdinfo/9:drm-resident-vram0:\t2 MiB', - '/proc/3/fdinfo/4:drm-driver:\tamdgpu', - '/proc/3/fdinfo/4:drm-client-id:\t9', - '/proc/3/fdinfo/4:drm-resident-vram0:\t5 GiB', -}, '\n') -assert(data.drm_vram_parse(fdinfo) == 3 * 1024 ^ 2, - 'drm vram: got ' .. tostring(data.drm_vram_parse(fdinfo))) -assert(data.drm_vram_parse('') == nil, 'drm vram: no clients is nil') - --- new_gate: opens at most once per interval on the clock it is given. -local gate = data.new_gate(1.9) -assert(gate(100.0) == true, 'gate: first call opens') -assert(gate(100.5) == false, 'gate: closed inside the interval') -assert(gate(101.95) == true, 'gate: opens after it') -assert(gate(102.0) == false, 'gate: interval restarts from the last open') - -- Emoji fall back to card.FONT_EMOJI: the toy API has no per-glyph fallback, -- so without the run split "x🦷" measured a tofu box in Noto Sans. do |
