package hwstats
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestGetCPUIdle(t *testing.T) {
st, err := NewCPUStats(nil)
require.NoError(t, err)
idle := st.GetCPUIdle()
require.GreaterOrEqual(t, idle, 0.0)
}
func TestAggregateMemoryStats(t *testing.T) {
const pageSize = 4096
const selfPID = 1
t.Run("self process only", func(t *testing.T) {
entries := []procEntry{
{pid: 1, ppid: 0, comm: "main", rss: 100},
}
memTotal, memory, groups := aggregateMemoryStats(entries, selfPID, pageSize)
require.Equal(t, 100*pageSize, memTotal)
require.Len(t, memory, 1)
require.Equal(t, 100*pageSize, memory[1].Total)
require.Len(t, memory[1].Procs, 1)
require.Equal(t, ProcMemoryEntry{Name: "main", Memory: 100 * pageSize}, memory[1].Procs[1])
require.Equal(t, 1, groups[1])
})
t.Run("direct children form separate groups", func(t *testing.T) {
entries := []procEntry{
{pid: 1, ppid: 0, comm: "main", rss: 100},
{pid: 10, ppid: 1, comm: "child1", rss: 200},
{pid: 20, ppid: 1, comm: "child2", rss: 300},
}
memTotal, memory, groups := aggregateMemoryStats(entries, selfPID, pageSize)
require.Equal(t, 600*pageSize, memTotal)
require.Len(t, memory, 3)
require.Equal(t, 10, groups[10])
require.Equal(t, 20, groups[20])
require.Equal(t, 200*pageSize, memory[10].Total)
require.Len(t, memory[10].Procs, 1)
require.Equal(t, 300*pageSize, memory[20].Total)
require.Len(t, memory[20].Procs, 1)
})
t.Run("nested processes grouped under first child", func(t *testing.T) {
entries := []procEntry{
{pid: 1, ppid: 0, comm: "main", rss: 50},
{pid: 10, ppid: 1, comm: "child", rss: 100},
{pid: 100, ppid: 10, comm: "grandchild", rss: 200},
{pid: 1000, ppid: 100, comm: "great-grandchild", rss: 300},
}
memTotal, memory, groups := aggregateMemoryStats(entries, selfPID, pageSize)
require.Equal(t, 650*pageSize, memTotal)
require.Equal(t, 10, groups[10])
require.Equal(t, 10, groups[100])
require.Equal(t, 10, groups[1000])
require.Equal(t, 600*pageSize, memory[10].Total)
require.Len(t, memory[10].Procs, 3)
require.Equal(t, 50*pageSize, memory[1].Total)
require.Len(t, memory[1].Procs, 1)
})
t.Run("multiple groups with nesting", func(t *testing.T) {
entries := []procEntry{
{pid: 1, ppid: 0, comm: "main", rss: 10},
{pid: 10, ppid: 1, comm: "child1", rss: 20},
{pid: 100, ppid: 10, comm: "gc1", rss: 30},
{pid: 101, ppid: 10, comm: "gc2", rss: 40},
{pid: 20, ppid: 1, comm: "child2", rss: 50},
{pid: 200, ppid: 20, comm: "gc3", rss: 60},
}
memTotal, memory, groups := aggregateMemoryStats(entries, selfPID, pageSize)
require.Equal(t, 210*pageSize, memTotal)
require.Equal(t, 10, groups[10])
require.Equal(t, 10, groups[100])
require.Equal(t, 10, groups[101])
require.Equal(t, 20, groups[20])
require.Equal(t, 20, groups[200])
require.Equal(t, 90*pageSize, memory[10].Total)
require.Len(t, memory[10].Procs, 3)
require.Equal(t, ProcMemoryEntry{Name: "child1", Memory: 20 * pageSize}, memory[10].Procs[10])
require.Equal(t, ProcMemoryEntry{Name: "gc1", Memory: 30 * pageSize}, memory[10].Procs[100])
require.Equal(t, ProcMemoryEntry{Name: "gc2", Memory: 40 * pageSize}, memory[10].Procs[101])
require.Equal(t, 110*pageSize, memory[20].Total)
require.Len(t, memory[20].Procs, 2)
require.Equal(t, 10*pageSize, memory[1].Total)
require.Len(t, memory[1].Procs, 1)
})
t.Run("unrelated processes group under their top ancestor", func(t *testing.T) {
entries := []procEntry{
{pid: 1, ppid: 0, comm: "main", rss: 10},
{pid: 50, ppid: 0, comm: "unrelated", rss: 100},
{pid: 500, ppid: 50, comm: "unrelated-child", rss: 200},
}
memTotal, memory, groups := aggregateMemoryStats(entries, selfPID, pageSize)
require.Equal(t, 310*pageSize, memTotal)
require.Equal(t, 50, groups[50])
require.Equal(t, 50, groups[500])
require.Equal(t, 300*pageSize, memory[50].Total)
require.Len(t, memory[50].Procs, 2)
})
t.Run("empty entries", func(t *testing.T) {
memTotal, memory, groups := aggregateMemoryStats(nil, selfPID, pageSize)
require.Equal(t, 0, memTotal)
require.Empty(t, memory)
require.Empty(t, groups)
})
}