telegraf/plugins/inputs/intel_powerstat/msr_test.go

189 lines
7.1 KiB
Go

//go:build linux
package intel_powerstat
import (
"context"
"errors"
"strings"
"testing"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"github.com/influxdata/telegraf/testutil"
)
func TestReadDataFromMsrPositive(t *testing.T) {
firstValue := uint64(1000000)
secondValue := uint64(5000000)
delta := secondValue - firstValue
cpuCores := []string{"cpu0", "cpu1"}
msr, fsMock := getMsrServiceWithMockedFs()
prepareTestData(fsMock, cpuCores, msr, t)
cores := trimCPUFromCores(cpuCores)
methodCallNumberForFirstValue := len(msr.msrOffsets) * len(cores)
methodCallNumberForSecondValue := methodCallNumberForFirstValue * 2
fsMock.On("readFileAtOffsetToUint64", mock.Anything, mock.Anything).
Return(firstValue, nil).Times(methodCallNumberForFirstValue)
for _, core := range cores {
require.NoError(t, msr.readDataFromMsr(core, nil))
}
fsMock.AssertNumberOfCalls(t, "readFileAtOffsetToUint64", methodCallNumberForFirstValue)
verifyCPUCoresData(cores, t, msr, firstValue, false, 0)
fsMock.On("readFileAtOffsetToUint64", mock.Anything, mock.Anything).
Return(secondValue, nil).Times(methodCallNumberForFirstValue)
for _, core := range cores {
require.NoError(t, msr.readDataFromMsr(core, nil))
}
fsMock.AssertNumberOfCalls(t, "readFileAtOffsetToUint64", methodCallNumberForSecondValue)
verifyCPUCoresData(cores, t, msr, secondValue, true, delta)
}
func trimCPUFromCores(cpuCores []string) []string {
cores := make([]string, 0)
for _, core := range cpuCores {
cores = append(cores, strings.TrimPrefix(core, "cpu"))
}
return cores
}
func TestReadDataFromMsrNegative(t *testing.T) {
firstValue := uint64(1000000)
cpuCores := []string{"cpu0", "cpu1"}
msr, fsMock := getMsrServiceWithMockedFs()
prepareTestData(fsMock, cpuCores, msr, t)
cores := trimCPUFromCores(cpuCores)
methodCallNumberPerCore := len(msr.msrOffsets)
// Normal execution for first core.
fsMock.On("readFileAtOffsetToUint64", mock.Anything, mock.Anything).
Return(firstValue, nil).Times(methodCallNumberPerCore).
// Fail to read file for second core.
On("readFileAtOffsetToUint64", mock.Anything, mock.Anything).
Return(uint64(0), errors.New("error reading file")).Times(methodCallNumberPerCore)
require.NoError(t, msr.readDataFromMsr(cores[0], nil))
require.Error(t, msr.readDataFromMsr(cores[1], nil))
}
func TestReadValueFromFileAtOffset(t *testing.T) {
cores := []string{"cpu0", "cpu1"}
msr, fsMock := getMsrServiceWithMockedFs()
ctx := context.Background()
testChannel := make(chan uint64, 1)
defer close(testChannel)
zero := uint64(0)
prepareTestData(fsMock, cores, msr, t)
fsMock.On("readFileAtOffsetToUint64", mock.Anything, mock.Anything).
Return(zero, errors.New("error reading file")).Once()
require.Error(t, msr.readValueFromFileAtOffset(ctx, testChannel, nil, 0))
fsMock.On("readFileAtOffsetToUint64", mock.Anything, mock.Anything).
Return(zero, nil).Once()
require.Equal(t, nil, msr.readValueFromFileAtOffset(ctx, testChannel, nil, 0))
require.Equal(t, zero, <-testChannel)
}
func TestCreateUncoreFreqPath(t *testing.T) {
path, err := createUncoreFreqPath("0", "initial", "min", "0")
expectedPath := "/sys/devices/system/cpu/intel_uncore_frequency/package_00_die_00/initial_min_freq_khz"
require.Equal(t, nil, err)
require.Equal(t, expectedPath, path)
path, err = createUncoreFreqPath("0", "initial", "max", "0")
expectedPath = "/sys/devices/system/cpu/intel_uncore_frequency/package_00_die_00/initial_max_freq_khz"
require.Equal(t, nil, err)
require.Equal(t, expectedPath, path)
path, err = createUncoreFreqPath("0", "current", "min", "0")
expectedPath = "/sys/devices/system/cpu/intel_uncore_frequency/package_00_die_00/min_freq_khz"
require.Equal(t, nil, err)
require.Equal(t, expectedPath, path)
path, err = createUncoreFreqPath("0", "current", "max", "0")
expectedPath = "/sys/devices/system/cpu/intel_uncore_frequency/package_00_die_00/max_freq_khz"
require.Equal(t, nil, err)
require.Equal(t, expectedPath, path)
path, err = createUncoreFreqPath("9", "current", "max", "0")
expectedPath = "/sys/devices/system/cpu/intel_uncore_frequency/package_09_die_00/max_freq_khz"
require.Equal(t, nil, err)
require.Equal(t, expectedPath, path)
path, err = createUncoreFreqPath("99", "current", "max", "0")
expectedPath = "/sys/devices/system/cpu/intel_uncore_frequency/package_99_die_00/max_freq_khz"
require.Equal(t, nil, err)
require.Equal(t, expectedPath, path)
path, err = createUncoreFreqPath("0", "current", "max", "9")
expectedPath = "/sys/devices/system/cpu/intel_uncore_frequency/package_00_die_09/max_freq_khz"
require.Equal(t, nil, err)
require.Equal(t, expectedPath, path)
path, err = createUncoreFreqPath("0", "current", "max", "99")
expectedPath = "/sys/devices/system/cpu/intel_uncore_frequency/package_00_die_99/max_freq_khz"
require.Equal(t, nil, err)
require.Equal(t, expectedPath, path)
path, err = createUncoreFreqPath("0", "foo", "max", "0")
expectedPath = ""
expectedError := errors.New("unknown frequency type foo, only 'initial' and 'current' are supported")
require.Equal(t, expectedError, err)
require.Equal(t, expectedPath, path)
path, err = createUncoreFreqPath("0", "current", "bar", "0")
expectedPath = ""
expectedError = errors.New("unknown frequency type bar, only 'min' and 'max' are supported")
require.Equal(t, expectedError, err)
require.Equal(t, expectedPath, path)
}
func prepareTestData(fsMock *mockFileService, cores []string, msr *msrServiceImpl, t *testing.T) {
// Prepare MSR offsets and CPUCoresData for test.
fsMock.On("getStringsMatchingPatternOnPath", mock.Anything).
Return(cores, nil).Once()
require.NoError(t, msr.setCPUCores())
fsMock.AssertCalled(t, "getStringsMatchingPatternOnPath", mock.Anything)
}
func verifyCPUCoresData(cores []string, t *testing.T, msr *msrServiceImpl, expectedValue uint64, verifyDelta bool, delta uint64) {
for _, core := range cores {
require.Equal(t, expectedValue, msr.cpuCoresData[core].c3)
require.Equal(t, expectedValue, msr.cpuCoresData[core].c6)
require.Equal(t, expectedValue, msr.cpuCoresData[core].c7)
require.Equal(t, expectedValue, msr.cpuCoresData[core].mperf)
require.Equal(t, expectedValue, msr.cpuCoresData[core].aperf)
require.Equal(t, expectedValue, msr.cpuCoresData[core].timeStampCounter)
require.Equal(t, int64((expectedValue>>16)&0xFF), msr.cpuCoresData[core].throttleTemp)
require.Equal(t, int64((expectedValue>>16)&0x7F), msr.cpuCoresData[core].temp)
if verifyDelta {
require.Equal(t, delta, msr.cpuCoresData[core].c3Delta)
require.Equal(t, delta, msr.cpuCoresData[core].c6Delta)
require.Equal(t, delta, msr.cpuCoresData[core].c7Delta)
require.Equal(t, delta, msr.cpuCoresData[core].mperfDelta)
require.Equal(t, delta, msr.cpuCoresData[core].aperfDelta)
require.Equal(t, delta, msr.cpuCoresData[core].timeStampCounterDelta)
}
}
}
func getMsrServiceWithMockedFs() (*msrServiceImpl, *mockFileService) {
cores := []string{"cpu0", "cpu1", "cpu2", "cpu3"}
logger := testutil.Logger{Name: "PowerPluginTest"}
fsMock := &mockFileService{}
fsMock.On("getStringsMatchingPatternOnPath", mock.Anything).
Return(cores, nil).Once()
msr := newMsrServiceWithFs(logger, fsMock)
return msr, fsMock
}