github.com/unionj-cloud/go-doudou@v1.3.8-0.20221011095552-0088008e5b31/toolkit/cpu/cpu_test.go (about)

     1  package cpu
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"os"
     7  	"runtime"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/unionj-cloud/go-doudou/toolkit/internal/common"
    12  	"github.com/stretchr/testify/assert"
    13  )
    14  
    15  func skipIfNotImplementedErr(t *testing.T, err error) {
    16  	if errors.Is(err, common.ErrNotImplementedError) {
    17  		t.Skip("not implemented")
    18  	}
    19  }
    20  
    21  func TestCpu_times(t *testing.T) {
    22  	v, err := Times(false)
    23  	skipIfNotImplementedErr(t, err)
    24  	if err != nil {
    25  		t.Errorf("error %v", err)
    26  	}
    27  	if len(v) == 0 {
    28  		t.Error("could not get CPUs ", err)
    29  	}
    30  	empty := TimesStat{}
    31  	for _, vv := range v {
    32  		if vv == empty {
    33  			t.Errorf("could not get CPU User: %v", vv)
    34  		}
    35  	}
    36  
    37  	// test sum of per cpu stats is within margin of error for cpu total stats
    38  	cpuTotal, err := Times(false)
    39  	skipIfNotImplementedErr(t, err)
    40  	if err != nil {
    41  		t.Errorf("error %v", err)
    42  	}
    43  	if len(cpuTotal) == 0 {
    44  		t.Error("could not get CPUs", err)
    45  	}
    46  	perCPU, err := Times(true)
    47  	skipIfNotImplementedErr(t, err)
    48  	if err != nil {
    49  		t.Errorf("error %v", err)
    50  	}
    51  	if len(perCPU) == 0 {
    52  		t.Error("could not get CPUs", err)
    53  	}
    54  	var perCPUUserTimeSum float64
    55  	var perCPUSystemTimeSum float64
    56  	var perCPUIdleTimeSum float64
    57  	for _, pc := range perCPU {
    58  		perCPUUserTimeSum += pc.User
    59  		perCPUSystemTimeSum += pc.System
    60  		perCPUIdleTimeSum += pc.Idle
    61  	}
    62  	margin := 2.0
    63  	t.Log(cpuTotal[0])
    64  
    65  	if cpuTotal[0].User == 0 && cpuTotal[0].System == 0 && cpuTotal[0].Idle == 0 {
    66  		t.Error("could not get cpu values")
    67  	}
    68  	if cpuTotal[0].User != 0 {
    69  		assert.InEpsilon(t, cpuTotal[0].User, perCPUUserTimeSum, margin)
    70  	}
    71  	if cpuTotal[0].System != 0 {
    72  		assert.InEpsilon(t, cpuTotal[0].System, perCPUSystemTimeSum, margin)
    73  	}
    74  	if cpuTotal[0].Idle != 0 {
    75  		assert.InEpsilon(t, cpuTotal[0].Idle, perCPUIdleTimeSum, margin)
    76  	}
    77  }
    78  
    79  func TestCpu_counts(t *testing.T) {
    80  	v, err := Counts(true)
    81  	skipIfNotImplementedErr(t, err)
    82  	if err != nil {
    83  		t.Errorf("error %v", err)
    84  	}
    85  	if v == 0 {
    86  		t.Errorf("could not get logical CPU counts: %v", v)
    87  	}
    88  	t.Logf("logical cores: %d", v)
    89  	v, err = Counts(false)
    90  	skipIfNotImplementedErr(t, err)
    91  	if err != nil {
    92  		t.Errorf("error %v", err)
    93  	}
    94  	if v == 0 {
    95  		t.Errorf("could not get physical CPU counts: %v", v)
    96  	}
    97  	t.Logf("physical cores: %d", v)
    98  }
    99  
   100  func TestCPUTimeStat_String(t *testing.T) {
   101  	v := TimesStat{
   102  		CPU:    "cpu0",
   103  		User:   100.1,
   104  		System: 200.1,
   105  		Idle:   300.1,
   106  	}
   107  	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}`
   108  	if e != fmt.Sprintf("%v", v) {
   109  		t.Errorf("CPUTimesStat string is invalid: %v", v)
   110  	}
   111  }
   112  
   113  func TestCpuInfo(t *testing.T) {
   114  	v, err := Info()
   115  	skipIfNotImplementedErr(t, err)
   116  	if err != nil {
   117  		t.Errorf("error %v", err)
   118  	}
   119  	if len(v) == 0 {
   120  		t.Errorf("could not get CPU Info")
   121  	}
   122  	for _, vv := range v {
   123  		if vv.ModelName == "" {
   124  			t.Errorf("could not get CPU Info: %v", vv)
   125  		}
   126  	}
   127  }
   128  
   129  func testCPUPercent(t *testing.T, percpu bool) {
   130  	numcpu := runtime.NumCPU()
   131  	testCount := 3
   132  
   133  	if runtime.GOOS != "windows" {
   134  		testCount = 100
   135  		v, err := Percent(time.Millisecond, percpu)
   136  		skipIfNotImplementedErr(t, err)
   137  		if err != nil {
   138  			t.Errorf("error %v", err)
   139  		}
   140  		// Skip CircleCI which CPU num is different
   141  		if os.Getenv("CIRCLECI") != "true" {
   142  			if (percpu && len(v) != numcpu) || (!percpu && len(v) != 1) {
   143  				t.Fatalf("wrong number of entries from CPUPercent: %v", v)
   144  			}
   145  		}
   146  	}
   147  	for i := 0; i < testCount; i++ {
   148  		duration := time.Duration(10) * time.Microsecond
   149  		v, err := Percent(duration, percpu)
   150  		skipIfNotImplementedErr(t, err)
   151  		if err != nil {
   152  			t.Errorf("error %v", err)
   153  		}
   154  		for _, percent := range v {
   155  			// Check for slightly greater then 100% to account for any rounding issues.
   156  			if percent < 0.0 || percent > 100.0001*float64(numcpu) {
   157  				t.Fatalf("CPUPercent value is invalid: %f", percent)
   158  			}
   159  		}
   160  	}
   161  }
   162  
   163  func testCPUPercentLastUsed(t *testing.T, percpu bool) {
   164  	numcpu := runtime.NumCPU()
   165  	testCount := 10
   166  
   167  	if runtime.GOOS != "windows" {
   168  		testCount = 2
   169  		v, err := Percent(time.Millisecond, percpu)
   170  		skipIfNotImplementedErr(t, err)
   171  		if err != nil {
   172  			t.Errorf("error %v", err)
   173  		}
   174  		// Skip CircleCI which CPU num is different
   175  		if os.Getenv("CIRCLECI") != "true" {
   176  			if (percpu && len(v) != numcpu) || (!percpu && len(v) != 1) {
   177  				t.Fatalf("wrong number of entries from CPUPercent: %v", v)
   178  			}
   179  		}
   180  	}
   181  	for i := 0; i < testCount; i++ {
   182  		v, err := Percent(0, percpu)
   183  		skipIfNotImplementedErr(t, err)
   184  		if err != nil {
   185  			t.Errorf("error %v", err)
   186  		}
   187  		time.Sleep(1 * time.Millisecond)
   188  		for _, percent := range v {
   189  			// Check for slightly greater then 100% to account for any rounding issues.
   190  			if percent < 0.0 || percent > 100.0001*float64(numcpu) {
   191  				t.Fatalf("CPUPercent value is invalid: %f", percent)
   192  			}
   193  		}
   194  	}
   195  }
   196  
   197  func TestCPUPercent(t *testing.T) {
   198  	testCPUPercent(t, false)
   199  }
   200  
   201  func TestCPUPercentPerCpu(t *testing.T) {
   202  	testCPUPercent(t, true)
   203  }
   204  
   205  func TestCPUPercentIntervalZero(t *testing.T) {
   206  	testCPUPercentLastUsed(t, false)
   207  }
   208  
   209  func TestCPUPercentIntervalZeroPerCPU(t *testing.T) {
   210  	testCPUPercentLastUsed(t, true)
   211  }