diff options
| author | Danilo M. <danix@danix.xyz> | 2026-09-17 19:04:34 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-09-17 19:04:34 +0200 |
| commit | c521d9eb71c9ca96348598d20eecb5ffd746aabf (patch) | |
| tree | 7ffcc2d0426bfaeb6d6944c9360466daed864876 /test | |
| parent | 1aa67dbe3e711617895d7b1d6e4dffccc74fa95a (diff) | |
| download | conky-theme-udt-c521d9eb71c9ca96348598d20eecb5ffd746aabf.tar.gz conky-theme-udt-c521d9eb71c9ca96348598d20eecb5ffd746aabf.zip | |
feat: add a byte-rate counter for interface statistics
Mirrors new_cpu_counter: cumulative counters need two samples to yield a
rate, and each direction carries its own previous reading.
Clamps a negative delta to zero rather than letting a 32-bit wrap or an
interface reset produce a spike. One bogus sample sets the shared autoscale
and flattens the entire window.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Diffstat (limited to 'test')
| -rw-r--r-- | test/test_data.lua | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/test/test_data.lua b/test/test_data.lua index 4d3280c..478bf78 100644 --- a/test/test_data.lua +++ b/test/test_data.lua @@ -178,4 +178,35 @@ 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') + print('test_data: all assertions passed') |
