Merge pull request #110864 from claudiubelu/adds-unittests

unittests: Adds winstats unittests
This commit is contained in:
Kubernetes Prow Robot 2023-03-13 08:12:50 -07:00 committed by GitHub
commit 34537c1a1d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 569 additions and 88 deletions

View File

@ -40,14 +40,14 @@ const (
// networkCounter contains the counters for network adapters.
type networkCounter struct {
packetsReceivedPerSecondCounter *perfCounter
packetsSentPerSecondCounter *perfCounter
bytesReceivedPerSecondCounter *perfCounter
bytesSentPerSecondCounter *perfCounter
packetsReceivedDiscardedCounter *perfCounter
packetsReceivedErrorsCounter *perfCounter
packetsOutboundDiscardedCounter *perfCounter
packetsOutboundErrorsCounter *perfCounter
packetsReceivedPerSecondCounter perfCounter
packetsSentPerSecondCounter perfCounter
bytesReceivedPerSecondCounter perfCounter
bytesSentPerSecondCounter perfCounter
packetsReceivedDiscardedCounter perfCounter
packetsReceivedErrorsCounter perfCounter
packetsOutboundDiscardedCounter perfCounter
packetsOutboundErrorsCounter perfCounter
mu sync.RWMutex
adapterStats map[string]cadvisorapi.InterfaceStats

View File

@ -0,0 +1,176 @@
//go:build windows
// +build windows
/*
Copyright 2023 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package winstats
import (
"errors"
"testing"
cadvisorapi "github.com/google/cadvisor/info/v1"
"github.com/stretchr/testify/assert"
)
const fakeAdapterName = "fake-adapter"
type fakePerfCounterImpl struct {
// Returned name.
name string
// Returned value.
value uint64
// If the perfCounter should raise an error.
raiseError bool
}
func (p *fakePerfCounterImpl) getData() (uint64, error) {
if p.raiseError {
return 0, errors.New("Expected getData error.")
}
return p.value, nil
}
func (p *fakePerfCounterImpl) getDataList() (map[string]uint64, error) {
if p.raiseError {
return nil, errors.New("Expected getDataList error.")
}
data := make(map[string]uint64)
data[p.name] = p.value
return data, nil
}
func newFakedNetworkCounters(raiseError bool) *networkCounter {
counters := make([]*fakePerfCounterImpl, 8)
for i := 0; i < 8; i++ {
counters[i] = &fakePerfCounterImpl{
name: fakeAdapterName,
value: 1,
raiseError: raiseError,
}
}
return &networkCounter{
packetsReceivedPerSecondCounter: counters[0],
packetsSentPerSecondCounter: counters[1],
bytesReceivedPerSecondCounter: counters[2],
bytesSentPerSecondCounter: counters[3],
packetsReceivedDiscardedCounter: counters[4],
packetsReceivedErrorsCounter: counters[5],
packetsOutboundDiscardedCounter: counters[6],
packetsOutboundErrorsCounter: counters[7],
adapterStats: map[string]cadvisorapi.InterfaceStats{},
}
}
func TestNewNetworkCounters(t *testing.T) {
_, err := newNetworkCounters()
assert.NoError(t, err)
}
func TestNetworkGetData(t *testing.T) {
netCounter := newFakedNetworkCounters(false)
// Add a net adapter that no longer exists in the adapterStats cache. It will
// have to be cleaned up after processing the data.
netCounter.adapterStats["other-fake-adapter"] = cadvisorapi.InterfaceStats{}
data, err := netCounter.getData()
assert.NoError(t, err)
// Make sure that we only have data from a single net adapter.
expectedStats := cadvisorapi.InterfaceStats{
Name: fakeAdapterName,
RxPackets: 1,
TxPackets: 1,
RxBytes: 1,
TxBytes: 1,
RxDropped: 1,
RxErrors: 1,
TxDropped: 1,
TxErrors: 1,
}
assert.Equal(t, []cadvisorapi.InterfaceStats{expectedStats}, data)
// The returned data is cumulative, so the resulting values should be double on a second call.
data, err = netCounter.getData()
assert.NoError(t, err)
expectedStats = cadvisorapi.InterfaceStats{
Name: fakeAdapterName,
RxPackets: 2,
TxPackets: 2,
RxBytes: 2,
TxBytes: 2,
RxDropped: 1,
RxErrors: 1,
TxDropped: 1,
TxErrors: 1,
}
assert.Equal(t, []cadvisorapi.InterfaceStats{expectedStats}, data)
}
func TestNetworkGetDataFailures(t *testing.T) {
netCounter := newFakedNetworkCounters(true)
_, err := netCounter.getData()
expectedMsg := "Expected getDataList error."
if err == nil || err.Error() != expectedMsg {
t.Fatalf("expected error message `%s` but got `%v`", expectedMsg, err)
}
_, err = netCounter.getData()
netCounter.packetsReceivedPerSecondCounter.(*fakePerfCounterImpl).raiseError = false
if err == nil || err.Error() != expectedMsg {
t.Fatalf("expected error message `%s` but got `%v`", expectedMsg, err)
}
_, err = netCounter.getData()
netCounter.packetsSentPerSecondCounter.(*fakePerfCounterImpl).raiseError = false
if err == nil || err.Error() != expectedMsg {
t.Fatalf("expected error message `%s` but got `%v`", expectedMsg, err)
}
_, err = netCounter.getData()
netCounter.bytesReceivedPerSecondCounter.(*fakePerfCounterImpl).raiseError = false
if err == nil || err.Error() != expectedMsg {
t.Fatalf("expected error message `%s` but got `%v`", expectedMsg, err)
}
_, err = netCounter.getData()
netCounter.bytesSentPerSecondCounter.(*fakePerfCounterImpl).raiseError = false
if err == nil || err.Error() != expectedMsg {
t.Fatalf("expected error message `%s` but got `%v`", expectedMsg, err)
}
_, err = netCounter.getData()
netCounter.packetsReceivedDiscardedCounter.(*fakePerfCounterImpl).raiseError = false
if err == nil || err.Error() != expectedMsg {
t.Fatalf("expected error message `%s` but got `%v`", expectedMsg, err)
}
_, err = netCounter.getData()
netCounter.packetsReceivedErrorsCounter.(*fakePerfCounterImpl).raiseError = false
if err == nil || err.Error() != expectedMsg {
t.Fatalf("expected error message `%s` but got `%v`", expectedMsg, err)
}
_, err = netCounter.getData()
netCounter.packetsOutboundDiscardedCounter.(*fakePerfCounterImpl).raiseError = false
if err == nil || err.Error() != expectedMsg {
t.Fatalf("expected error message `%s` but got `%v`", expectedMsg, err)
}
}

View File

@ -202,9 +202,9 @@ func (p *perfCounterNodeStatsClient) getNodeInfo() nodeInfo {
return p.nodeInfo
}
func (p *perfCounterNodeStatsClient) collectMetricsData(cpuCounter, memWorkingSetCounter, memCommittedBytesCounter *perfCounter, networkAdapterCounter *networkCounter) {
func (p *perfCounterNodeStatsClient) collectMetricsData(cpuCounter, memWorkingSetCounter, memCommittedBytesCounter perfCounter, networkAdapterCounter *networkCounter) {
cpuValue, err := cpuCounter.getData()
cpuCores := runtime.NumCPU()
cpuCores := ProcessorCount()
if err != nil {
klog.ErrorS(err, "Unable to get cpu perf counter data")
return

View File

@ -0,0 +1,188 @@
//go:build windows
// +build windows
/*
Copyright 2023 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package winstats
import (
"os"
"strconv"
"testing"
"time"
cadvisorapi "github.com/google/cadvisor/info/v1"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"k8s.io/apimachinery/pkg/util/wait"
)
func TestMonitoring(t *testing.T) {
counterClient, err := NewPerfCounterClient()
assert.NoError(t, err)
// assert that startMonitoring has been called. nodeInfo should be set.
assert.NotNil(t, counterClient.(*StatsClient).client.getNodeInfo())
// Wait until we get a non-zero node metrics.
if pollErr := wait.Poll(100*time.Millisecond, 5*perfCounterUpdatePeriod, func() (bool, error) {
metrics, _ := counterClient.(*StatsClient).client.getNodeMetrics()
if metrics.memoryPrivWorkingSetBytes != 0 {
return true, nil
}
return false, nil
}); pollErr != nil {
t.Fatalf("Encountered error: `%v'", pollErr)
}
}
func TestGetMachineInfo(t *testing.T) {
p := perfCounterNodeStatsClient{
nodeInfo: nodeInfo{
memoryPhysicalCapacityBytes: 100,
},
}
machineInfo, err := p.getMachineInfo()
assert.NoError(t, err)
assert.Equal(t, uint64(100), machineInfo.MemoryCapacity)
hostname, _ := os.Hostname()
assert.Equal(t, hostname, machineInfo.MachineID)
// Check if it's an UUID.
_, err = uuid.Parse(machineInfo.SystemUUID)
assert.NoError(t, err)
id, err := strconv.Atoi(machineInfo.BootID)
assert.NoError(t, err)
assert.NotZero(t, id)
}
func TestGetVersionInfo(t *testing.T) {
client := perfCounterNodeStatsClient{
nodeInfo: nodeInfo{
kernelVersion: "foo",
osImageVersion: "lish",
},
}
info, _ := client.getVersionInfo()
expected := &cadvisorapi.VersionInfo{
KernelVersion: "foo",
ContainerOsVersion: "lish",
}
assert.Equal(t, expected, info)
}
func TestCollectMetricsData(t *testing.T) {
p := perfCounterNodeStatsClient{}
cpuCounter := &fakePerfCounterImpl{
value: 1,
raiseError: true,
}
memWorkingSetCounter := &fakePerfCounterImpl{
value: 2,
raiseError: true,
}
memCommittedBytesCounter := &fakePerfCounterImpl{
value: 3,
raiseError: true,
}
networkAdapterCounter := newFakedNetworkCounters(true)
// Checking the error cases first.
p.collectMetricsData(cpuCounter, memWorkingSetCounter, memCommittedBytesCounter, networkAdapterCounter)
metrics, _ := p.getNodeMetrics()
expectedMetrics := nodeMetrics{}
assert.Equal(t, expectedMetrics, metrics)
cpuCounter.raiseError = false
p.collectMetricsData(cpuCounter, memWorkingSetCounter, memCommittedBytesCounter, networkAdapterCounter)
metrics, _ = p.getNodeMetrics()
assert.Equal(t, expectedMetrics, metrics)
memWorkingSetCounter.raiseError = false
p.collectMetricsData(cpuCounter, memWorkingSetCounter, memCommittedBytesCounter, networkAdapterCounter)
metrics, _ = p.getNodeMetrics()
assert.Equal(t, expectedMetrics, metrics)
memCommittedBytesCounter.raiseError = false
p.collectMetricsData(cpuCounter, memWorkingSetCounter, memCommittedBytesCounter, networkAdapterCounter)
metrics, _ = p.getNodeMetrics()
assert.Equal(t, expectedMetrics, metrics)
networkAdapterCounter = newFakedNetworkCounters(false)
p.collectMetricsData(cpuCounter, memWorkingSetCounter, memCommittedBytesCounter, networkAdapterCounter)
metrics, _ = p.getNodeMetrics()
expectedMetrics = nodeMetrics{
cpuUsageCoreNanoSeconds: uint64(ProcessorCount()) * 1e7,
cpuUsageNanoCores: 0,
memoryPrivWorkingSetBytes: 2,
memoryCommittedBytes: 3,
interfaceStats: networkAdapterCounter.listInterfaceStats(),
timeStamp: time.Now(),
}
assert.Equal(t, expectedMetrics, metrics)
}
func TestConvertCPUValue(t *testing.T) {
testCases := []struct {
cpuValue uint64
expected uint64
}{
{cpuValue: uint64(50), expected: uint64(2000000000)},
{cpuValue: uint64(0), expected: uint64(0)},
{cpuValue: uint64(100), expected: uint64(4000000000)},
}
var cpuCores = 4
for _, tc := range testCases {
p := perfCounterNodeStatsClient{}
newValue := p.convertCPUValue(cpuCores, tc.cpuValue)
assert.Equal(t, tc.expected, newValue)
}
}
func TestGetCPUUsageNanoCores(t *testing.T) {
testCases := []struct {
latestValue uint64
previousValue uint64
expected uint64
}{
{latestValue: uint64(0), previousValue: uint64(0), expected: uint64(0)},
{latestValue: uint64(2000000000), previousValue: uint64(0), expected: uint64(200000000)},
{latestValue: uint64(5000000000), previousValue: uint64(2000000000), expected: uint64(300000000)},
}
for _, tc := range testCases {
p := perfCounterNodeStatsClient{}
p.cpuUsageCoreNanoSecondsCache = cpuUsageCoreNanoSecondsCache{
latestValue: tc.latestValue,
previousValue: tc.previousValue,
}
cpuUsageNanoCores := p.getCPUUsageNanoCores()
assert.Equal(t, tc.expected, cpuUsageNanoCores)
}
}
func testGetPhysicallyInstalledSystemMemoryBytes(t *testing.T) {
totalMemory, err := getPhysicallyInstalledSystemMemoryBytes()
assert.NoError(t, err)
assert.NotZero(t, totalMemory)
}

View File

@ -41,12 +41,17 @@ const (
defaultCachePeriod = 10 * time.Second
)
type perfCounter struct {
type perfCounter interface {
getData() (uint64, error)
getDataList() (map[string]uint64, error)
}
type perfCounterImpl struct {
queryHandle win_pdh.PDH_HQUERY
counterHandle win_pdh.PDH_HCOUNTER
}
func newPerfCounter(counter string) (*perfCounter, error) {
func newPerfCounter(counter string) (perfCounter, error) {
var queryHandle win_pdh.PDH_HQUERY
var counterHandle win_pdh.PDH_HCOUNTER
@ -65,35 +70,20 @@ func newPerfCounter(counter string) (*perfCounter, error) {
return nil, fmt.Errorf("unable to collect data from counter. Error code is %x", ret)
}
return &perfCounter{
return &perfCounterImpl{
queryHandle: queryHandle,
counterHandle: counterHandle,
}, nil
}
// getData is used for getting data without * in counter name.
func (p *perfCounter) getData() (uint64, error) {
ret := win_pdh.PdhCollectQueryData(p.queryHandle)
if ret != win_pdh.ERROR_SUCCESS {
return 0, fmt.Errorf("unable to collect data from counter. Error code is %x", ret)
}
var bufSize, bufCount uint32
var size = uint32(unsafe.Sizeof(win_pdh.PDH_FMT_COUNTERVALUE_ITEM_DOUBLE{}))
var emptyBuf [1]win_pdh.PDH_FMT_COUNTERVALUE_ITEM_DOUBLE // need at least 1 addressable null ptr.
var data uint64
ret = win_pdh.PdhGetFormattedCounterArrayDouble(p.counterHandle, &bufSize, &bufCount, &emptyBuf[0])
if ret != win_pdh.PDH_MORE_DATA {
return 0, fmt.Errorf("unable to collect data from counter. Error code is %x", ret)
}
filledBuf := make([]win_pdh.PDH_FMT_COUNTERVALUE_ITEM_DOUBLE, bufCount*size)
ret = win_pdh.PdhGetFormattedCounterArrayDouble(p.counterHandle, &bufSize, &bufCount, &filledBuf[0])
if ret != win_pdh.ERROR_SUCCESS {
return 0, fmt.Errorf("unable to collect data from counter. Error code is %x", ret)
func (p *perfCounterImpl) getData() (uint64, error) {
filledBuf, bufCount, err := p.getQueriedData()
if err != nil {
return 0, err
}
var data uint64 = 0
for i := 0; i < int(bufCount); i++ {
c := filledBuf[i]
data = uint64(c.FmtValue.DoubleValue)
@ -102,29 +92,14 @@ func (p *perfCounter) getData() (uint64, error) {
return data, nil
}
// getData is used for getting data with * in counter name.
func (p *perfCounter) getDataList() (map[string]uint64, error) {
ret := win_pdh.PdhCollectQueryData(p.queryHandle)
if ret != win_pdh.ERROR_SUCCESS {
return nil, fmt.Errorf("unable to collect data from counter. Error code is %x", ret)
// getDataList is used for getting data with * in counter name.
func (p *perfCounterImpl) getDataList() (map[string]uint64, error) {
filledBuf, bufCount, err := p.getQueriedData()
if err != nil {
return nil, err
}
var bufSize, bufCount uint32
var size = uint32(unsafe.Sizeof(win_pdh.PDH_FMT_COUNTERVALUE_ITEM_DOUBLE{}))
var emptyBuf [1]win_pdh.PDH_FMT_COUNTERVALUE_ITEM_DOUBLE // need at least 1 addressable null ptr.
data := map[string]uint64{}
ret = win_pdh.PdhGetFormattedCounterArrayDouble(p.counterHandle, &bufSize, &bufCount, &emptyBuf[0])
if ret != win_pdh.PDH_MORE_DATA {
return nil, fmt.Errorf("unable to collect data from counter. Error code is %x", ret)
}
filledBuf := make([]win_pdh.PDH_FMT_COUNTERVALUE_ITEM_DOUBLE, bufCount*size)
ret = win_pdh.PdhGetFormattedCounterArrayDouble(p.counterHandle, &bufSize, &bufCount, &filledBuf[0])
if ret != win_pdh.ERROR_SUCCESS {
return nil, fmt.Errorf("unable to collect data from counter. Error code is %x", ret)
}
for i := 0; i < int(bufCount); i++ {
c := filledBuf[i]
value := uint64(c.FmtValue.DoubleValue)
@ -134,3 +109,28 @@ func (p *perfCounter) getDataList() (map[string]uint64, error) {
return data, nil
}
// getQueriedData is used for getting data using the given query handle.
func (p *perfCounterImpl) getQueriedData() ([]win_pdh.PDH_FMT_COUNTERVALUE_ITEM_DOUBLE, uint32, error) {
ret := win_pdh.PdhCollectQueryData(p.queryHandle)
if ret != win_pdh.ERROR_SUCCESS {
return nil, 0, fmt.Errorf("unable to collect data from counter. Error code is %x", ret)
}
var bufSize, bufCount uint32
var size = uint32(unsafe.Sizeof(win_pdh.PDH_FMT_COUNTERVALUE_ITEM_DOUBLE{}))
var emptyBuf [1]win_pdh.PDH_FMT_COUNTERVALUE_ITEM_DOUBLE // need at least 1 addressable null ptr.
ret = win_pdh.PdhGetFormattedCounterArrayDouble(p.counterHandle, &bufSize, &bufCount, &emptyBuf[0])
if ret != win_pdh.PDH_MORE_DATA {
return nil, 0, fmt.Errorf("unable to collect data from counter. Error code is %x", ret)
}
filledBuf := make([]win_pdh.PDH_FMT_COUNTERVALUE_ITEM_DOUBLE, bufCount*size)
ret = win_pdh.PdhGetFormattedCounterArrayDouble(p.counterHandle, &bufSize, &bufCount, &filledBuf[0])
if ret != win_pdh.ERROR_SUCCESS {
return nil, 0, fmt.Errorf("unable to collect data from counter. Error code is %x", ret)
}
return filledBuf, bufCount, nil
}

View File

@ -0,0 +1,136 @@
//go:build windows
// +build windows
/*
Copyright 2023 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package winstats
import (
"testing"
"time"
"k8s.io/apimachinery/pkg/util/wait"
)
func TestPerfCounter(t *testing.T) {
testCases := map[string]struct {
counter string
skipCheck bool
expectErr bool
expectedErrMsg string
}{
"CPU Query": {
counter: cpuQuery,
},
"Memory Prvate Working Set Query": {
counter: memoryPrivWorkingSetQuery,
},
"Memory Committed Bytes Query": {
counter: memoryCommittedBytesQuery,
},
"Net Adapter Packets Received/sec Query": {
counter: packetsReceivedPerSecondQuery,
skipCheck: true,
},
"Net Adapter Packets Sent/sec Query": {
counter: packetsSentPerSecondQuery,
skipCheck: true,
},
"Net Adapter Bytes Received/sec Query": {
counter: bytesReceivedPerSecondQuery,
skipCheck: true,
},
"Net Adapter Bytes Sent/sec Query": {
counter: bytesSentPerSecondQuery,
skipCheck: true,
},
"Net Adapter Packets Received Discarded Query": {
counter: packetsReceivedDiscardedQuery,
skipCheck: true,
},
"Net Adapter Packets Received Errors Query": {
counter: packetsReceivedErrorsQuery,
skipCheck: true,
},
"Net Adapter Packets Outbound Discarded Query": {
counter: packetsOutboundDiscardedQuery,
skipCheck: true,
},
"Net Adapter Packets Outbound Errors Query": {
counter: packetsOutboundErrorsQuery,
skipCheck: true,
},
"Invalid Query": {
counter: "foo",
expectErr: true,
expectedErrMsg: "unable to add process counter: foo. Error code is c0000bc0",
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
counter, err := newPerfCounter(tc.counter)
if tc.expectErr {
if err == nil || err.Error() != tc.expectedErrMsg {
t.Fatalf("expected error message `%s` but got `%v`", tc.expectedErrMsg, err)
}
return
}
// There are some counters that we can't expect to see any non-zero values, like the
// networking-related counters.
if tc.skipCheck {
return
}
// Wait until we get a non-zero perf counter data.
if pollErr := wait.Poll(100*time.Millisecond, 5*perfCounterUpdatePeriod, func() (bool, error) {
data, err := counter.getData()
if err != nil {
return false, err
}
if data != 0 {
return true, nil
}
return false, nil
}); pollErr != nil {
t.Fatalf("Encountered error: `%v'", pollErr)
return
}
// Check that we have at least one non-zero value in the data list.
if pollErr := wait.Poll(100*time.Millisecond, 5*perfCounterUpdatePeriod, func() (bool, error) {
dataList, err := counter.getDataList()
if err != nil {
return false, err
}
for _, value := range dataList {
if value != 0 {
return true, nil
}
}
return false, nil
}); pollErr != nil {
t.Fatalf("Encountered error: `%v'", pollErr)
}
})
}
}

View File

@ -20,6 +20,7 @@ limitations under the License.
package winstats
import (
"os"
"testing"
"time"
@ -133,44 +134,24 @@ func TestWinVersionInfo(t *testing.T) {
KernelVersion: "v42"})
}
func TestConvertCPUValue(t *testing.T) {
testCases := []struct {
cpuValue uint64
expected uint64
}{
{cpuValue: uint64(50), expected: uint64(2000000000)},
{cpuValue: uint64(0), expected: uint64(0)},
{cpuValue: uint64(100), expected: uint64(4000000000)},
}
var cpuCores = 4
func TestGetDirFsInfo(t *testing.T) {
c := getClient(t)
for _, tc := range testCases {
p := perfCounterNodeStatsClient{}
newValue := p.convertCPUValue(cpuCores, tc.cpuValue)
assert.Equal(t, tc.expected, newValue)
}
}
func TestGetCPUUsageNanoCores(t *testing.T) {
testCases := []struct {
latestValue uint64
previousValue uint64
expected uint64
}{
{latestValue: uint64(0), previousValue: uint64(0), expected: uint64(0)},
{latestValue: uint64(2000000000), previousValue: uint64(0), expected: uint64(200000000)},
{latestValue: uint64(5000000000), previousValue: uint64(2000000000), expected: uint64(300000000)},
// Try with a non-existent path.
_, err := c.GetDirFsInfo("foo/lish")
expectedErrMsg := "The system cannot find the path specified."
if err == nil || err.Error() != expectedErrMsg {
t.Fatalf("expected error message `%s` but got `%v`", expectedErrMsg, err)
}
for _, tc := range testCases {
p := perfCounterNodeStatsClient{}
p.cpuUsageCoreNanoSecondsCache = cpuUsageCoreNanoSecondsCache{
latestValue: tc.latestValue,
previousValue: tc.previousValue,
}
cpuUsageNanoCores := p.getCPUUsageNanoCores()
assert.Equal(t, tc.expected, cpuUsageNanoCores)
}
dir, err := os.MkdirTemp("", "fsinfo")
assert.NoError(t, err)
defer os.RemoveAll(dir)
fsInfo, err := c.GetDirFsInfo(dir)
assert.NoError(t, err)
assert.NotZero(t, fsInfo.Capacity)
assert.NotZero(t, fsInfo.Available)
}
func getClient(t *testing.T) Client {