2024-02-17 03:48:29 +00:00
|
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
2014-12-30 22:09:05 +09:00
|
|
|
package cpu
|
2014-04-18 16:34:47 +09:00
|
|
|
|
|
|
|
import (
|
2021-12-04 22:29:38 +01:00
|
|
|
"errors"
|
2014-05-12 11:51:08 +09:00
|
|
|
"fmt"
|
2016-02-12 22:44:17 +09:00
|
|
|
"os"
|
2014-11-02 04:05:52 +01:00
|
|
|
"runtime"
|
2014-04-18 16:34:47 +09:00
|
|
|
"testing"
|
2014-11-02 04:05:52 +01:00
|
|
|
"time"
|
2018-11-20 13:25:17 -08:00
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
2023-04-04 18:07:22 +00:00
|
|
|
|
2024-02-17 03:48:29 +00:00
|
|
|
"github.com/shirou/gopsutil/v4/internal/common"
|
2014-04-18 16:34:47 +09:00
|
|
|
)
|
|
|
|
|
2020-08-29 18:29:00 +02:00
|
|
|
func skipIfNotImplementedErr(t *testing.T, err error) {
|
2021-12-04 22:29:38 +01:00
|
|
|
if errors.Is(err, common.ErrNotImplementedError) {
|
2020-08-29 18:29:00 +02:00
|
|
|
t.Skip("not implemented")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-24 01:58:24 +00:00
|
|
|
func TestTimes(t *testing.T) {
|
2016-03-22 23:09:12 +09:00
|
|
|
v, err := Times(false)
|
2020-08-29 18:29:00 +02:00
|
|
|
skipIfNotImplementedErr(t, err)
|
2014-04-18 16:34:47 +09:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("error %v", err)
|
|
|
|
}
|
|
|
|
if len(v) == 0 {
|
2014-08-15 19:09:43 +02:00
|
|
|
t.Error("could not get CPUs ", err)
|
2014-04-18 16:34:47 +09:00
|
|
|
}
|
2016-03-22 23:09:12 +09:00
|
|
|
empty := TimesStat{}
|
2014-04-18 16:34:47 +09:00
|
|
|
for _, vv := range v {
|
2014-05-12 11:51:08 +09:00
|
|
|
if vv == empty {
|
2014-04-18 16:34:47 +09:00
|
|
|
t.Errorf("could not get CPU User: %v", vv)
|
|
|
|
}
|
|
|
|
}
|
2018-11-19 21:51:27 -08:00
|
|
|
|
|
|
|
// test sum of per cpu stats is within margin of error for cpu total stats
|
|
|
|
cpuTotal, err := Times(false)
|
2020-08-29 18:29:00 +02:00
|
|
|
skipIfNotImplementedErr(t, err)
|
2018-11-19 21:51:27 -08:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("error %v", err)
|
|
|
|
}
|
|
|
|
if len(cpuTotal) == 0 {
|
2020-10-25 19:01:38 +09:00
|
|
|
t.Error("could not get CPUs", err)
|
2018-11-19 21:51:27 -08:00
|
|
|
}
|
|
|
|
perCPU, err := Times(true)
|
2020-08-29 18:29:00 +02:00
|
|
|
skipIfNotImplementedErr(t, err)
|
2018-11-19 21:51:27 -08:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("error %v", err)
|
|
|
|
}
|
|
|
|
if len(perCPU) == 0 {
|
2020-10-25 19:01:38 +09:00
|
|
|
t.Error("could not get CPUs", err)
|
2018-11-19 21:51:27 -08:00
|
|
|
}
|
|
|
|
var perCPUUserTimeSum float64
|
|
|
|
var perCPUSystemTimeSum float64
|
|
|
|
var perCPUIdleTimeSum float64
|
|
|
|
for _, pc := range perCPU {
|
|
|
|
perCPUUserTimeSum += pc.User
|
|
|
|
perCPUSystemTimeSum += pc.System
|
|
|
|
perCPUIdleTimeSum += pc.Idle
|
|
|
|
}
|
|
|
|
margin := 2.0
|
2020-10-25 19:01:38 +09:00
|
|
|
t.Log(cpuTotal[0])
|
|
|
|
|
|
|
|
if cpuTotal[0].User == 0 && cpuTotal[0].System == 0 && cpuTotal[0].Idle == 0 {
|
|
|
|
t.Error("could not get cpu values")
|
|
|
|
}
|
|
|
|
if cpuTotal[0].User != 0 {
|
|
|
|
assert.InEpsilon(t, cpuTotal[0].User, perCPUUserTimeSum, margin)
|
|
|
|
}
|
|
|
|
if cpuTotal[0].System != 0 {
|
|
|
|
assert.InEpsilon(t, cpuTotal[0].System, perCPUSystemTimeSum, margin)
|
|
|
|
}
|
|
|
|
if cpuTotal[0].Idle != 0 {
|
|
|
|
assert.InEpsilon(t, cpuTotal[0].Idle, perCPUIdleTimeSum, margin)
|
|
|
|
}
|
2014-04-18 16:34:47 +09:00
|
|
|
}
|
|
|
|
|
2024-02-24 01:58:24 +00:00
|
|
|
func TestCounts(t *testing.T) {
|
2016-03-22 23:09:12 +09:00
|
|
|
v, err := Counts(true)
|
2020-08-29 18:29:00 +02:00
|
|
|
skipIfNotImplementedErr(t, err)
|
2014-04-18 16:34:47 +09:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("error %v", err)
|
|
|
|
}
|
|
|
|
if v == 0 {
|
2020-09-15 01:11:17 +02:00
|
|
|
t.Errorf("could not get logical CPU counts: %v", v)
|
2014-04-18 16:34:47 +09:00
|
|
|
}
|
2020-09-15 01:11:17 +02:00
|
|
|
t.Logf("logical cores: %d", v)
|
|
|
|
v, err = Counts(false)
|
|
|
|
skipIfNotImplementedErr(t, err)
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("error %v", err)
|
|
|
|
}
|
|
|
|
if v == 0 {
|
|
|
|
t.Errorf("could not get physical CPU counts: %v", v)
|
|
|
|
}
|
|
|
|
t.Logf("physical cores: %d", v)
|
2014-04-18 16:34:47 +09:00
|
|
|
}
|
2014-05-12 11:51:08 +09:00
|
|
|
|
2024-02-24 01:58:24 +00:00
|
|
|
func TestTimeStat_String(t *testing.T) {
|
2016-03-22 23:09:12 +09:00
|
|
|
v := TimesStat{
|
2014-05-12 11:51:08 +09:00
|
|
|
CPU: "cpu0",
|
|
|
|
User: 100.1,
|
|
|
|
System: 200.1,
|
|
|
|
Idle: 300.1,
|
|
|
|
}
|
2019-04-27 13:45:12 +09:00
|
|
|
e := `{"cpu":"cpu0","user":100.1,"system":200.1,"idle":300.1,"nice":0.0,"iowait":0.0,"irq":0.0,"softirq":0.0,"steal":0.0,"guest":0.0,"guestNice":0.0}`
|
2014-05-12 11:51:08 +09:00
|
|
|
if e != fmt.Sprintf("%v", v) {
|
|
|
|
t.Errorf("CPUTimesStat string is invalid: %v", v)
|
|
|
|
}
|
|
|
|
}
|
2014-05-16 18:12:18 +09:00
|
|
|
|
2024-02-24 01:58:24 +00:00
|
|
|
func TestInfo(t *testing.T) {
|
2016-03-22 23:09:12 +09:00
|
|
|
v, err := Info()
|
2020-08-29 18:29:00 +02:00
|
|
|
skipIfNotImplementedErr(t, err)
|
2014-05-16 18:12:18 +09:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("error %v", err)
|
|
|
|
}
|
2015-02-15 21:25:33 +09:00
|
|
|
if len(v) == 0 {
|
|
|
|
t.Errorf("could not get CPU Info")
|
|
|
|
}
|
2014-05-16 18:12:18 +09:00
|
|
|
for _, vv := range v {
|
2014-05-16 18:39:17 +09:00
|
|
|
if vv.ModelName == "" {
|
2014-05-16 18:12:18 +09:00
|
|
|
t.Errorf("could not get CPU Info: %v", vv)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-11-02 04:05:52 +01:00
|
|
|
|
2024-02-24 01:58:24 +00:00
|
|
|
func testPercent(t *testing.T, percpu bool) {
|
2014-11-02 04:05:52 +01:00
|
|
|
numcpu := runtime.NumCPU()
|
2015-03-11 23:00:06 +09:00
|
|
|
testCount := 3
|
|
|
|
|
2015-03-07 21:52:43 +09:00
|
|
|
if runtime.GOOS != "windows" {
|
2015-03-11 23:00:06 +09:00
|
|
|
testCount = 100
|
2016-03-22 23:09:12 +09:00
|
|
|
v, err := Percent(time.Millisecond, percpu)
|
2020-08-29 18:29:00 +02:00
|
|
|
skipIfNotImplementedErr(t, err)
|
2015-03-07 21:52:43 +09:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("error %v", err)
|
|
|
|
}
|
2023-08-30 14:07:47 +00:00
|
|
|
// Skip CI which CPU num is different
|
|
|
|
if os.Getenv("CI") != "true" {
|
2016-02-12 22:44:17 +09:00
|
|
|
if (percpu && len(v) != numcpu) || (!percpu && len(v) != 1) {
|
|
|
|
t.Fatalf("wrong number of entries from CPUPercent: %v", v)
|
|
|
|
}
|
2015-03-07 21:52:43 +09:00
|
|
|
}
|
2014-11-02 04:05:52 +01:00
|
|
|
}
|
2015-03-11 23:00:06 +09:00
|
|
|
for i := 0; i < testCount; i++ {
|
2014-11-12 11:17:55 +09:00
|
|
|
duration := time.Duration(10) * time.Microsecond
|
2016-03-22 23:09:12 +09:00
|
|
|
v, err := Percent(duration, percpu)
|
2020-08-29 18:29:00 +02:00
|
|
|
skipIfNotImplementedErr(t, err)
|
2014-11-02 04:05:52 +01:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("error %v", err)
|
|
|
|
}
|
|
|
|
for _, percent := range v {
|
2015-10-18 20:53:01 -07:00
|
|
|
// Check for slightly greater then 100% to account for any rounding issues.
|
|
|
|
if percent < 0.0 || percent > 100.0001*float64(numcpu) {
|
2014-11-02 04:05:52 +01:00
|
|
|
t.Fatalf("CPUPercent value is invalid: %f", percent)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-24 01:58:24 +00:00
|
|
|
func testPercentLastUsed(t *testing.T, percpu bool) {
|
2016-06-01 15:21:58 -06:00
|
|
|
numcpu := runtime.NumCPU()
|
|
|
|
testCount := 10
|
|
|
|
|
|
|
|
if runtime.GOOS != "windows" {
|
|
|
|
testCount = 2
|
|
|
|
v, err := Percent(time.Millisecond, percpu)
|
2020-08-29 18:29:00 +02:00
|
|
|
skipIfNotImplementedErr(t, err)
|
2016-06-01 15:21:58 -06:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("error %v", err)
|
|
|
|
}
|
2023-08-30 14:07:47 +00:00
|
|
|
// Skip CI which CPU num is different
|
|
|
|
if os.Getenv("CI") != "true" {
|
2016-06-01 15:21:58 -06:00
|
|
|
if (percpu && len(v) != numcpu) || (!percpu && len(v) != 1) {
|
|
|
|
t.Fatalf("wrong number of entries from CPUPercent: %v", v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for i := 0; i < testCount; i++ {
|
|
|
|
v, err := Percent(0, percpu)
|
2020-08-29 18:29:00 +02:00
|
|
|
skipIfNotImplementedErr(t, err)
|
2016-06-01 15:21:58 -06:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("error %v", err)
|
|
|
|
}
|
|
|
|
time.Sleep(1 * time.Millisecond)
|
|
|
|
for _, percent := range v {
|
|
|
|
// Check for slightly greater then 100% to account for any rounding issues.
|
|
|
|
if percent < 0.0 || percent > 100.0001*float64(numcpu) {
|
|
|
|
t.Fatalf("CPUPercent value is invalid: %f", percent)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-24 01:58:24 +00:00
|
|
|
func TestPercent(t *testing.T) {
|
|
|
|
testPercent(t, false)
|
2014-11-02 04:05:52 +01:00
|
|
|
}
|
|
|
|
|
2024-02-24 01:58:24 +00:00
|
|
|
func TestPercentPerCpu(t *testing.T) {
|
|
|
|
testPercent(t, true)
|
2014-11-02 04:05:52 +01:00
|
|
|
}
|
2016-06-01 15:21:58 -06:00
|
|
|
|
2024-02-24 01:58:24 +00:00
|
|
|
func TestPercentIntervalZero(t *testing.T) {
|
|
|
|
testPercentLastUsed(t, false)
|
2016-06-01 15:21:58 -06:00
|
|
|
}
|
|
|
|
|
2024-02-24 01:58:24 +00:00
|
|
|
func TestPercentIntervalZeroPerCPU(t *testing.T) {
|
|
|
|
testPercentLastUsed(t, true)
|
2016-06-01 15:21:58 -06:00
|
|
|
}
|