internal/agent/hostinfo/hostinfo_linux_test.go
Ref: Size: 3.9 KiB History
//go:build linux
package hostinfo
import (
"context"
"errors"
"runtime"
"syscall"
"testing"
"github.com/stretchr/testify/assert"
)
// These three tests stub sysinfoFn/statfsFn with syscall.Sysinfo_t/Statfs_t
// literals, which only exist on Linux — they live in this Linux-tagged file
// (rather than hostinfo_test.go) purely so the package still vets clean on
// other GOOS; the assertions are unchanged from before the per-OS split.
// TestCapacityExactArithmetic pins TOTALS (not free space): a regression that
// swaps in Bavail/Bfree or free-memory fields must fail this test, since the
// server derives available capacity by subtracting live VM specs from
// whatever Capacity reports.
func TestCapacityExactArithmetic(t *testing.T) {
oldSys, oldStat := sysinfoFn, statfsFn
defer func() { sysinfoFn, statfsFn = oldSys, oldStat }()
sysinfoFn = func(si *syscall.Sysinfo_t) error {
*si = syscall.Sysinfo_t{
Totalram: 8 * 1024 * 1024 * 1024, // 8 GiB
Unit: 1,
}
return nil
}
statfsFn = func(_ string, fs *syscall.Statfs_t) error {
*fs = syscall.Statfs_t{
Bsize: 4096,
Blocks: 26214400, // 100 GiB total
}
return nil
}
c := Capacity("/whatever")
assert.Equal(t, int64(runtime.NumCPU()), c.GetVcpus())
assert.Equal(t, int64(8192), c.GetMemMb())
assert.Equal(t, int64(100), c.GetDiskGb())
}
// TestCapacityBestEffortOnSyscallFailure covers the package's best-effort
// contract: a failing probe zeroes its own dimension rather than erroring or
// blocking, and the two probes fail independently of each other.
func TestCapacityBestEffortOnSyscallFailure(t *testing.T) {
oldSys, oldStat := sysinfoFn, statfsFn
defer func() { sysinfoFn, statfsFn = oldSys, oldStat }()
sysinfoFn = func(*syscall.Sysinfo_t) error { return errors.New("boom") }
statfsFn = func(_ string, fs *syscall.Statfs_t) error {
*fs = syscall.Statfs_t{Bsize: 4096, Blocks: 26214400}
return nil
}
c := Capacity("/whatever")
assert.Equal(t, int64(0), c.GetMemMb())
assert.Equal(t, int64(100), c.GetDiskGb())
sysinfoFn = func(si *syscall.Sysinfo_t) error {
*si = syscall.Sysinfo_t{Totalram: 8 * 1024 * 1024 * 1024, Unit: 1}
return nil
}
statfsFn = func(_ string, _ *syscall.Statfs_t) error { return errors.New("boom") }
c = Capacity("/whatever")
assert.Equal(t, int64(8192), c.GetMemMb())
assert.Equal(t, int64(0), c.GetDiskGb())
}
// TestFactsVirtComesFromTheRunner keeps the Linux virt expectation with the
// platform that has it: Facts asks systemd-detect-virt through the injected
// runner. Darwin answers "none" without a subprocess (hostinfo_darwin_test.go).
func TestFactsVirtComesFromTheRunner(t *testing.T) {
f := Facts(context.Background(), func(_ context.Context, _ string, _ ...string) (string, error) {
return "kvm\n", nil
})
assert.Equal(t, "kvm", f.GetVirt())
}
func TestMetricsComputes(t *testing.T) {
oldSys, oldStat, oldMem := sysinfoFn, statfsFn, memInfoPath
defer func() { sysinfoFn, statfsFn, memInfoPath = oldSys, oldStat, oldMem }()
sysinfoFn = func(si *syscall.Sysinfo_t) error {
*si = syscall.Sysinfo_t{
Uptime: 3600,
Loads: [3]uint64{65536, 32768, 0}, // 1.0, 0.5, 0.0
Totalram: 8 * 1024 * 1024 * 1024, // 8 GiB
Unit: 1,
}
return nil
}
memInfoPath = writeFixture(t, "meminfo", "MemTotal: 8388608 kB\nMemAvailable: 4194304 kB\n") // 4 GiB avail
statfsFn = func(_ string, fs *syscall.Statfs_t) error {
*fs = syscall.Statfs_t{
Bsize: 4096,
Blocks: 26214400, // 100 GiB total
Bfree: 13107200, // 50 GiB free (incl reserved)
Bavail: 10485760, // 40 GiB avail to non-root
}
return nil
}
m := Metrics("/whatever")
assert.Equal(t, int64(3600), m.GetUptimeS())
assert.InDelta(t, 1.0, m.GetLoad1(), 0.001)
assert.InDelta(t, 0.5, m.GetLoad5(), 0.001)
assert.Equal(t, int64(4096), m.GetMemAvailableMb())
assert.Equal(t, int64(4096), m.GetMemUsedMb()) // 8192 total − 4096 avail
assert.Equal(t, int64(40), m.GetDiskFreeGb())
assert.Equal(t, int64(50), m.GetDiskUsedGb()) // (Blocks − Bfree) × Bsize
}