From 534a478fcd19695256cdc83c3c3bdbc348f9d669 Mon Sep 17 00:00:00 2001 From: "Saro G." Date: Wed, 19 Jun 2024 12:23:59 -0400 Subject: [PATCH 1/9] TestBootTime() compare with system uptime binary output --- providers/freebsd/sysctl_freebsd_test.go | 39 +++++++++++++++++++++--- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/providers/freebsd/sysctl_freebsd_test.go b/providers/freebsd/sysctl_freebsd_test.go index 613371e..f2ba62b 100644 --- a/providers/freebsd/sysctl_freebsd_test.go +++ b/providers/freebsd/sysctl_freebsd_test.go @@ -20,11 +20,12 @@ package freebsd import ( - "testing" - "time" - + "encoding/json" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "os/exec" + "testing" + "time" ) func TestArchitecture(t *testing.T) { @@ -42,8 +43,36 @@ func TestBootTime(t *testing.T) { t.Fatal(err) } - // Apply a sanity check. This assumes the host has rebooted in the last year. - assert.WithinDuration(t, time.Now().UTC(), bootTime, 365*24*time.Hour) + bootDiff := time.Since(bootTime) + // t.Logf("bootTime in seconds: %#v", int64(bootDiff.Seconds())) + + cmd := exec.Command("/usr/bin/uptime", "--libxo=json") + upcmd, err := cmd.Output() + + if err != nil { + t.Fatal(err) + } + + t.Logf(string(upcmd)) + + type UptimeOutput struct { + UptimeInformation struct { + Uptime int64 `json:"uptime"` + } `json:"uptime-information"` + } + + var upInfo UptimeOutput + err = json.Unmarshal(upcmd, &upInfo) + + if err != nil { + t.Fatal(err) + } + + upsec := upInfo.UptimeInformation.Uptime + uptime := time.Duration(upsec * int64(time.Second)) + // t.Logf("uptime in seconds: %#v", int64(uptime.Seconds())) + + assert.InDelta(t, uptime, bootDiff, float64(5*time.Second)) } func TestCPUStateTimes(t *testing.T) { From f9fda7545352e82a561e566d82d9b7b48480b162 Mon Sep 17 00:00:00 2001 From: "Saro G." Date: Wed, 19 Jun 2024 13:16:13 -0400 Subject: [PATCH 2/9] Moved sysctl value casts into helper methods --- providers/freebsd/host_freebsd_cgo.go | 19 +++++++++---------- providers/freebsd/process_freebsd_cgo.go | 2 +- providers/freebsd/sysctl_freebsd.go | 24 ++++++++++++------------ 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/providers/freebsd/host_freebsd_cgo.go b/providers/freebsd/host_freebsd_cgo.go index 4862908..15fc9ae 100644 --- a/providers/freebsd/host_freebsd_cgo.go +++ b/providers/freebsd/host_freebsd_cgo.go @@ -128,11 +128,10 @@ func (r *reader) memInfo(m *types.HostMemoryInfo) { // free = free // available = buffers + inactive + cache + free - ps, err := pageSizeBytes() + pageSize, err := pageSizeBytes() if r.addErr(err) { return } - pageSize := uint64(ps) m.Total, err = totalPhysicalMem() if r.addErr(err) { @@ -144,31 +143,31 @@ func (r *reader) memInfo(m *types.HostMemoryInfo) { return } m.Metrics = make(map[string]uint64, 6) - m.Metrics["active_bytes"] = uint64(activePages) * pageSize + m.Metrics["active_bytes"] = activePages * pageSize wirePages, err := wirePageCount() if r.addErr(err) { return } - m.Metrics["wired_bytes"] = uint64(wirePages) * pageSize + m.Metrics["wired_bytes"] = wirePages * pageSize inactivePages, err := inactivePageCount() if r.addErr(err) { return } - m.Metrics["inactive_bytes"] = uint64(inactivePages) * pageSize + m.Metrics["inactive_bytes"] = inactivePages * pageSize cachePages, err := cachePageCount() if r.addErr(err) { return } - m.Metrics["cache_bytes"] = uint64(cachePages) * pageSize + m.Metrics["cache_bytes"] = cachePages * pageSize freePages, err := freePageCount() if r.addErr(err) { return } - m.Metrics["free_bytes"] = uint64(freePages) * pageSize + m.Metrics["free_bytes"] = freePages * pageSize buffers, err := buffersUsedBytes() if r.addErr(err) { @@ -176,9 +175,9 @@ func (r *reader) memInfo(m *types.HostMemoryInfo) { } m.Metrics["buffer_bytes"] = buffers - m.Used = uint64(activePages+wirePages) * pageSize - m.Free = uint64(freePages) * pageSize - m.Available = uint64(inactivePages+cachePages+freePages)*pageSize + buffers + m.Used = (activePages + wirePages) * pageSize + m.Free = freePages * pageSize + m.Available = (inactivePages+cachePages+freePages)*pageSize + buffers // Virtual (swap) Memory swap, err := kvmGetSwapInfo() diff --git a/providers/freebsd/process_freebsd_cgo.go b/providers/freebsd/process_freebsd_cgo.go index 83cbf12..ab6b506 100644 --- a/providers/freebsd/process_freebsd_cgo.go +++ b/providers/freebsd/process_freebsd_cgo.go @@ -285,7 +285,7 @@ func (p *process) Memory() (types.MemoryInfo, error) { p.kinfo = procs[0].kinfo return types.MemoryInfo{ - Resident: uint64(p.kinfo.ki_rssize) * uint64(pageSize), + Resident: uint64(p.kinfo.ki_rssize) * pageSize, Virtual: uint64(p.kinfo.ki_size), }, nil } diff --git a/providers/freebsd/sysctl_freebsd.go b/providers/freebsd/sysctl_freebsd.go index acb20e4..60c9120 100644 --- a/providers/freebsd/sysctl_freebsd.go +++ b/providers/freebsd/sysctl_freebsd.go @@ -42,7 +42,7 @@ var tickDuration = sync.OnceValues(func() (time.Duration, error) { return time.Duration(c.Tick) * time.Microsecond, nil }) -var pageSizeBytes = sync.OnceValues(func() (uint32, error) { +var pageSizeBytes = sync.OnceValues(func() (uint64, error) { const mib = "vm.stats.vm.v_page_size" v, err := unix.SysctlUint32(mib) @@ -50,17 +50,17 @@ var pageSizeBytes = sync.OnceValues(func() (uint32, error) { return 0, fmt.Errorf("failed to get %s: %w", mib, err) } - return v, nil + return uint64(v), nil }) -func activePageCount() (uint32, error) { +func activePageCount() (uint64, error) { const mib = "vm.stats.vm.v_active_count" v, err := unix.SysctlUint32(mib) if err != nil { return 0, fmt.Errorf("failed to get %s: %w", mib, err) } - return v, nil + return uint64(v), nil } func architecture() (string, error) { @@ -98,7 +98,7 @@ func buffersUsedBytes() (uint64, error) { return v, nil } -func cachePageCount() (uint32, error) { +func cachePageCount() (uint64, error) { const mib = "vm.stats.vm.v_cache_count" v, err := unix.SysctlUint32(mib) @@ -106,7 +106,7 @@ func cachePageCount() (uint32, error) { return 0, fmt.Errorf("failed to get %s: %w", mib, err) } - return v, nil + return uint64(v), nil } const sizeOfUint64 = int(unsafe.Sizeof(uint64(0))) @@ -143,7 +143,7 @@ func cpuStateTimes() (*types.CPUTimes, error) { }, nil } -func freePageCount() (uint32, error) { +func freePageCount() (uint64, error) { const mib = "vm.stats.vm.v_free_count" v, err := unix.SysctlUint32(mib) @@ -151,10 +151,10 @@ func freePageCount() (uint32, error) { return 0, fmt.Errorf("failed to get %s: %w", mib, err) } - return v, nil + return uint64(v), nil } -func inactivePageCount() (uint32, error) { +func inactivePageCount() (uint64, error) { const mib = "vm.stats.vm.v_inactive_count" v, err := unix.SysctlUint32(mib) @@ -162,7 +162,7 @@ func inactivePageCount() (uint32, error) { return 0, fmt.Errorf("failed to get %s: %w", mib, err) } - return v, nil + return uint64(v), nil } func kernelVersion() (string, error) { @@ -237,12 +237,12 @@ func totalPhysicalMem() (uint64, error) { return v, nil } -func wirePageCount() (uint32, error) { +func wirePageCount() (uint64, error) { const mib = "vm.stats.vm.v_wire_count" v, err := unix.SysctlUint32(mib) if err != nil { return 0, fmt.Errorf("failed to get %s: %w", mib, err) } - return v, nil + return uint64(v), nil } From d3d45dfe19a278a4d801c991f9a6068046fe4c15 Mon Sep 17 00:00:00 2001 From: "Saro G." Date: Wed, 19 Jun 2024 13:17:54 -0400 Subject: [PATCH 3/9] Use mib const in sysctlRaw() --- providers/freebsd/sysctl_freebsd.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/providers/freebsd/sysctl_freebsd.go b/providers/freebsd/sysctl_freebsd.go index 60c9120..52a51df 100644 --- a/providers/freebsd/sysctl_freebsd.go +++ b/providers/freebsd/sysctl_freebsd.go @@ -120,7 +120,7 @@ func cpuStateTimes() (*types.CPUTimes, error) { } const mib = "kern.cp_time" - buf, err := unix.SysctlRaw("kern.cp_time") + buf, err := unix.SysctlRaw(mib) if err != nil { return nil, fmt.Errorf("failed to get %s: %w", mib, err) } From bbb75c4687b7190303dcbfeff01cdfab1320069e Mon Sep 17 00:00:00 2001 From: "Saro G." Date: Wed, 19 Jun 2024 15:22:18 -0400 Subject: [PATCH 4/9] memInfo(): be less optimistic --- providers/freebsd/host_freebsd_cgo.go | 35 ++++------------- providers/freebsd/sysctl_freebsd.go | 56 +++++++++++++-------------- 2 files changed, 35 insertions(+), 56 deletions(-) diff --git a/providers/freebsd/host_freebsd_cgo.go b/providers/freebsd/host_freebsd_cgo.go index 15fc9ae..3b09fe3 100644 --- a/providers/freebsd/host_freebsd_cgo.go +++ b/providers/freebsd/host_freebsd_cgo.go @@ -133,46 +133,25 @@ func (r *reader) memInfo(m *types.HostMemoryInfo) { return } - m.Total, err = totalPhysicalMem() - if r.addErr(err) { - return - } + m.Total = totalPhysicalMem(r) + activePages := activePageCount(r) - activePages, err := activePageCount() - if r.addErr(err) { - return - } m.Metrics = make(map[string]uint64, 6) m.Metrics["active_bytes"] = activePages * pageSize - wirePages, err := wirePageCount() - if r.addErr(err) { - return - } + wirePages := wirePageCount(r) m.Metrics["wired_bytes"] = wirePages * pageSize - inactivePages, err := inactivePageCount() - if r.addErr(err) { - return - } + inactivePages := inactivePageCount(r) m.Metrics["inactive_bytes"] = inactivePages * pageSize - cachePages, err := cachePageCount() - if r.addErr(err) { - return - } + cachePages := cachePageCount(r) m.Metrics["cache_bytes"] = cachePages * pageSize - freePages, err := freePageCount() - if r.addErr(err) { - return - } + freePages := freePageCount(r) m.Metrics["free_bytes"] = freePages * pageSize - buffers, err := buffersUsedBytes() - if r.addErr(err) { - return - } + buffers := buffersUsedBytes(r) m.Metrics["buffer_bytes"] = buffers m.Used = (activePages + wirePages) * pageSize diff --git a/providers/freebsd/sysctl_freebsd.go b/providers/freebsd/sysctl_freebsd.go index 52a51df..0e3e15a 100644 --- a/providers/freebsd/sysctl_freebsd.go +++ b/providers/freebsd/sysctl_freebsd.go @@ -53,14 +53,14 @@ var pageSizeBytes = sync.OnceValues(func() (uint64, error) { return uint64(v), nil }) -func activePageCount() (uint64, error) { +func activePageCount(r *reader) uint64 { const mib = "vm.stats.vm.v_active_count" v, err := unix.SysctlUint32(mib) - if err != nil { - return 0, fmt.Errorf("failed to get %s: %w", mib, err) + if r.addErr(err) { + return 0 } - return uint64(v), nil + return uint64(v) } func architecture() (string, error) { @@ -87,26 +87,26 @@ func bootTime() (time.Time, error) { } // buffersUsedBytes returns the number memory bytes used as disk cache. -func buffersUsedBytes() (uint64, error) { +func buffersUsedBytes(r *reader) uint64 { const mib = "vfs.bufspace" v, err := unix.SysctlUint64(mib) - if err != nil { - return 0, fmt.Errorf("failed to get %s: %w", mib, err) + if r.addErr(err) { + return 0 } - return v, nil + return v } -func cachePageCount() (uint64, error) { +func cachePageCount(r *reader) uint64 { const mib = "vm.stats.vm.v_cache_count" v, err := unix.SysctlUint32(mib) - if err != nil { - return 0, fmt.Errorf("failed to get %s: %w", mib, err) + if r.addErr(err) { + return 0 } - return uint64(v), nil + return uint64(v) } const sizeOfUint64 = int(unsafe.Sizeof(uint64(0))) @@ -143,26 +143,26 @@ func cpuStateTimes() (*types.CPUTimes, error) { }, nil } -func freePageCount() (uint64, error) { +func freePageCount(r *reader) uint64 { const mib = "vm.stats.vm.v_free_count" v, err := unix.SysctlUint32(mib) - if err != nil { - return 0, fmt.Errorf("failed to get %s: %w", mib, err) + if r.addErr(err) { + return 0 } - return uint64(v), nil + return uint64(v) } -func inactivePageCount() (uint64, error) { +func inactivePageCount(r *reader) uint64 { const mib = "vm.stats.vm.v_inactive_count" v, err := unix.SysctlUint32(mib) - if err != nil { - return 0, fmt.Errorf("failed to get %s: %w", mib, err) + if r.addErr(err) { + return 0 } - return uint64(v), nil + return uint64(v) } func kernelVersion() (string, error) { @@ -227,22 +227,22 @@ func operatingSystem() (*types.OSInfo, error) { return info, nil } -func totalPhysicalMem() (uint64, error) { +func totalPhysicalMem(r *reader) uint64 { const mib = "hw.physmem" v, err := unix.SysctlUint64(mib) - if err != nil { - return 0, fmt.Errorf("failed to get %s: %w", mib, err) + if r.addErr(err) { + return 0 } - return v, nil + return v } -func wirePageCount() (uint64, error) { +func wirePageCount(r *reader) uint64 { const mib = "vm.stats.vm.v_wire_count" v, err := unix.SysctlUint32(mib) - if err != nil { - return 0, fmt.Errorf("failed to get %s: %w", mib, err) + if r.addErr(err) { + return 0 } - return uint64(v), nil + return uint64(v) } From be7058a03a083ca19a5fdee4d58dfa7ed51bc8d3 Mon Sep 17 00:00:00 2001 From: "Saro G." Date: Thu, 20 Jun 2024 10:36:24 -0400 Subject: [PATCH 5/9] Simplified reader.Err() --- providers/freebsd/host_freebsd_cgo.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/providers/freebsd/host_freebsd_cgo.go b/providers/freebsd/host_freebsd_cgo.go index 3b09fe3..52c9a28 100644 --- a/providers/freebsd/host_freebsd_cgo.go +++ b/providers/freebsd/host_freebsd_cgo.go @@ -107,10 +107,7 @@ func (r *reader) addErr(err error) bool { } func (r *reader) Err() error { - if len(r.errs) > 0 { - return errors.Join(r.errs...) - } - return nil + return errors.Join(r.errs...) } func (r *reader) cpuTime(cpu *types.CPUTimes) { From 1e82bbf1ac196f65faa0d420a95dd9df776b47dd Mon Sep 17 00:00:00 2001 From: "Saro G." Date: Thu, 20 Jun 2024 13:04:13 -0400 Subject: [PATCH 6/9] TestArchitecture(): compare with known machine architecture (MACHINE_ARCH) values --- providers/freebsd/sysctl_freebsd_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/providers/freebsd/sysctl_freebsd_test.go b/providers/freebsd/sysctl_freebsd_test.go index f2ba62b..61a1730 100644 --- a/providers/freebsd/sysctl_freebsd_test.go +++ b/providers/freebsd/sysctl_freebsd_test.go @@ -35,6 +35,7 @@ func TestArchitecture(t *testing.T) { } assert.NotEmpty(t, arch) + assert.Regexp(t, `(amd64|i386|powerpc(64(le)?|spe)?|armv(6|7)|aarch64|riscv64*|mips(n)?(32|64)?(el)?|sparc64)`, arch) } func TestBootTime(t *testing.T) { From b119ea8bedd34dc05866720dc7bb018a6b2371f8 Mon Sep 17 00:00:00 2001 From: "Saro G." Date: Thu, 20 Jun 2024 13:13:41 -0400 Subject: [PATCH 7/9] TestMachineID(): validate host UUID --- providers/freebsd/sysctl_freebsd_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/providers/freebsd/sysctl_freebsd_test.go b/providers/freebsd/sysctl_freebsd_test.go index 61a1730..434aa09 100644 --- a/providers/freebsd/sysctl_freebsd_test.go +++ b/providers/freebsd/sysctl_freebsd_test.go @@ -102,6 +102,7 @@ func TestMachineID(t *testing.T) { } assert.NotEmpty(t, machineID) + assert.Regexp(t, "^[a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12}$", machineID) } func TestOperatingSystem(t *testing.T) { From 144921732c7aceb657626ad443411df7c1401f01 Mon Sep 17 00:00:00 2001 From: "Saro G." Date: Thu, 20 Jun 2024 13:33:03 -0400 Subject: [PATCH 8/9] TestKernelVersion(): compare with currently running kernel version --- providers/freebsd/sysctl_freebsd_test.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/providers/freebsd/sysctl_freebsd_test.go b/providers/freebsd/sysctl_freebsd_test.go index 434aa09..a40ade3 100644 --- a/providers/freebsd/sysctl_freebsd_test.go +++ b/providers/freebsd/sysctl_freebsd_test.go @@ -24,6 +24,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "os/exec" + "strings" "testing" "time" ) @@ -92,7 +93,18 @@ func TestKernelVersion(t *testing.T) { t.Fatal(err) } + // Retrieve currently running kernel version + cmd := exec.Command("/bin/freebsd-version", "-r") + fbsdout, err := cmd.Output() + + if err != nil { + t.Fatal(err) + } + + fbsdver := strings.TrimSuffix(string(fbsdout), "\n") + assert.NotEmpty(t, kernel) + assert.EqualValues(t, kernel, fbsdver) } func TestMachineID(t *testing.T) { From 1106c15cd01752b5edd003b2bbdba130346041c1 Mon Sep 17 00:00:00 2001 From: "Saro G." Date: Thu, 20 Jun 2024 14:22:55 -0400 Subject: [PATCH 9/9] TestArchitecture(): revised architectures to compare against --- providers/freebsd/sysctl_freebsd_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/providers/freebsd/sysctl_freebsd_test.go b/providers/freebsd/sysctl_freebsd_test.go index a40ade3..2b12516 100644 --- a/providers/freebsd/sysctl_freebsd_test.go +++ b/providers/freebsd/sysctl_freebsd_test.go @@ -36,7 +36,7 @@ func TestArchitecture(t *testing.T) { } assert.NotEmpty(t, arch) - assert.Regexp(t, `(amd64|i386|powerpc(64(le)?|spe)?|armv(6|7)|aarch64|riscv64*|mips(n)?(32|64)?(el)?|sparc64)`, arch) + assert.Regexp(t, `(amd64|i386|powerpc|arm(64)?|riscv|mips|sparc64|pc98)`, arch) } func TestBootTime(t *testing.T) {