141 строка
5.1 KiB
Go
141 строка
5.1 KiB
Go
package webapp
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// makeFakeMetricsProc writes a minimal /proc tree with stat, meminfo,
|
|
// loadavg, uptime, and net/dev files so CollectSnapshot can parse
|
|
// it without a real /proc.
|
|
func makeFakeMetricsProc(t *testing.T) string {
|
|
t.Helper()
|
|
root := t.TempDir()
|
|
require.NoError(t, os.WriteFile(filepath.Join(root, "stat"), []byte(statFixture), 0o644))
|
|
require.NoError(t, os.WriteFile(filepath.Join(root, "meminfo"), []byte(meminfoFixture), 0o644))
|
|
require.NoError(t, os.WriteFile(filepath.Join(root, "loadavg"), []byte(loadavgFixture), 0o644))
|
|
require.NoError(t, os.WriteFile(filepath.Join(root, "uptime"), []byte(uptimeFixture), 0o644))
|
|
require.NoError(t, os.MkdirAll(filepath.Join(root, "net"), 0o755))
|
|
require.NoError(t, os.WriteFile(filepath.Join(root, "net", "dev"), []byte(netdevFixture), 0o644))
|
|
require.NoError(t, os.WriteFile(filepath.Join(root, "mounts"), []byte(mountsFixture), 0o644))
|
|
return root
|
|
}
|
|
|
|
const statFixture = `cpu 100 0 50 800 20 0 0 0 0 0
|
|
cpu0 25 0 12 200 5 0 0 0 0 0
|
|
intr 12345 0 0 0
|
|
ctxt 78910
|
|
btime 1700000000
|
|
`
|
|
|
|
const meminfoFixture = `MemTotal: 16384000 kB
|
|
MemFree: 4096000 kB
|
|
MemAvailable: 8192000 kB
|
|
Buffers: 512000 kB
|
|
Cached: 2048000 kB
|
|
SwapCached: 0 kB
|
|
SwapTotal: 2048000 kB
|
|
SwapFree: 2048000 kB
|
|
`
|
|
|
|
const loadavgFixture = "0.42 0.85 1.23 1/123 4567\n"
|
|
|
|
const uptimeFixture = "12345.67\n"
|
|
|
|
const netdevFixture = `Inter-| Receive | Transmit
|
|
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
|
|
lo: 1000000 1000 0 0 0 0 0 0 1000000 1000 0 0 0 0 0 0
|
|
eth0: 9999999 5000 1 2 0 0 0 0 8888888 4500 0 0 0 0 0 0
|
|
`
|
|
|
|
const mountsFixture = `/dev/sda1 / ext4 rw,relatime 0 0
|
|
tmpfs /run tmpfs rw,nosuid 0 0
|
|
`
|
|
|
|
func TestReadProcStatPercentages(t *testing.T) {
|
|
root := t.TempDir()
|
|
require.NoError(t, os.WriteFile(filepath.Join(root, "stat"), []byte(statFixture), 0o644))
|
|
cpu, err := readProcStat(filepath.Join(root, "stat"))
|
|
require.NoError(t, err)
|
|
// Fixture: user=100, nice=0, system=50, idle=800, iowait=20, steal=0
|
|
// Total = 970, idle+iowait = 820, busy = 150.
|
|
assert.InDelta(t, 10.31, cpu.UserPct, 0.01)
|
|
assert.InDelta(t, 5.15, cpu.SystemPct, 0.01)
|
|
assert.InDelta(t, 82.47, cpu.IdlePct, 0.01)
|
|
assert.InDelta(t, 15.46, cpu.TotalPct, 0.01)
|
|
}
|
|
|
|
func TestReadMemInfoBytes(t *testing.T) {
|
|
root := t.TempDir()
|
|
require.NoError(t, os.WriteFile(filepath.Join(root, "meminfo"), []byte(meminfoFixture), 0o644))
|
|
mem, err := readMemInfo(filepath.Join(root, "meminfo"))
|
|
require.NoError(t, err)
|
|
assert.Equal(t, uint64(16384000*1024), mem.Total)
|
|
assert.Equal(t, uint64(8192000*1024), mem.Available)
|
|
assert.Equal(t, uint64(2048000*1024), mem.SwapTotal)
|
|
// used = total - available = 8192 MiB
|
|
// pct = 8192 / 16384 * 100 = 50.00
|
|
assert.InDelta(t, 50.0, mem.UsedPct, 0.01)
|
|
}
|
|
|
|
func TestReadLoadAvg(t *testing.T) {
|
|
root := t.TempDir()
|
|
require.NoError(t, os.WriteFile(filepath.Join(root, "loadavg"), []byte(loadavgFixture), 0o644))
|
|
load, err := readLoadAvg(filepath.Join(root, "loadavg"))
|
|
require.NoError(t, err)
|
|
assert.InDelta(t, 0.42, load.One, 0.001)
|
|
assert.InDelta(t, 0.85, load.Five, 0.001)
|
|
assert.InDelta(t, 1.23, load.Fifteen, 0.001)
|
|
}
|
|
|
|
func TestReadUptime(t *testing.T) {
|
|
root := t.TempDir()
|
|
require.NoError(t, os.WriteFile(filepath.Join(root, "uptime"), []byte(uptimeFixture), 0o644))
|
|
d, err := readUptime(filepath.Join(root, "uptime"))
|
|
require.NoError(t, err)
|
|
assert.InDelta(t, 12345.67, d.Seconds(), 0.01)
|
|
}
|
|
|
|
func TestReadNetDev(t *testing.T) {
|
|
root := t.TempDir()
|
|
require.NoError(t, os.MkdirAll(filepath.Join(root, "net"), 0o755))
|
|
require.NoError(t, os.WriteFile(filepath.Join(root, "net", "dev"), []byte(netdevFixture), 0o644))
|
|
ifaces, err := readNetDev(filepath.Join(root, "net", "dev"))
|
|
require.NoError(t, err)
|
|
require.Len(t, ifaces, 2)
|
|
eth := ifaces[1]
|
|
assert.Equal(t, "eth0", eth.Name)
|
|
assert.Equal(t, uint64(9999999), eth.RxBytes)
|
|
assert.Equal(t, uint64(8888888), eth.TxBytes)
|
|
assert.Equal(t, uint64(5000), eth.RxPkt)
|
|
assert.Equal(t, uint64(1), eth.RxErr)
|
|
}
|
|
|
|
func TestReadMounts(t *testing.T) {
|
|
root := t.TempDir()
|
|
require.NoError(t, os.WriteFile(filepath.Join(root, "mounts"), []byte(mountsFixture), 0o644))
|
|
mounts, err := readMounts(filepath.Join(root, "mounts"))
|
|
require.NoError(t, err)
|
|
require.Len(t, mounts, 2)
|
|
assert.Equal(t, "/", mounts[0].Mount)
|
|
assert.Equal(t, "ext4", mounts[0].FSType)
|
|
}
|
|
|
|
func TestCollectSnapshotEndToEnd(t *testing.T) {
|
|
root := makeFakeMetricsProc(t)
|
|
snap, err := CollectSnapshot(root)
|
|
require.NoError(t, err)
|
|
assert.InDelta(t, 15.46, snap.CPU.TotalPct, 0.5,
|
|
"CPU busy should be in the expected range")
|
|
assert.InDelta(t, 50.0, snap.Memory.UsedPct, 0.5,
|
|
"memory used should be ~50% from the fixture")
|
|
assert.InDelta(t, 12345.67, snap.Uptime.Seconds(), 0.5)
|
|
require.Len(t, snap.Networks, 2)
|
|
require.Len(t, snap.Disks, 2)
|
|
assert.False(t, snap.BootAt.IsZero(), "boot time must be derivable")
|
|
}
|