436 lines
10 KiB
Go
436 lines
10 KiB
Go
|
//go:build !windows
|
||
|
|
||
|
package intel_rdt
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"testing"
|
||
|
"time"
|
||
|
|
||
|
"github.com/stretchr/testify/require"
|
||
|
|
||
|
"github.com/influxdata/telegraf/testutil"
|
||
|
)
|
||
|
|
||
|
var metricsValues = map[string]float64{
|
||
|
"IPC": 0.5,
|
||
|
"LLC_Misses": 61650,
|
||
|
"LLC": 1632,
|
||
|
"MBL": 0.6,
|
||
|
"MBR": 0.9,
|
||
|
"MBT": 1.9,
|
||
|
}
|
||
|
|
||
|
func TestParseCoresMeasurement(t *testing.T) {
|
||
|
timestamp := "2020-08-12 13:34:36"
|
||
|
cores := "\"37,44\""
|
||
|
|
||
|
t.Run("valid measurement string", func(t *testing.T) {
|
||
|
measurement := fmt.Sprintf("%s,%s,%f,%f,%f,%f,%f,%f",
|
||
|
timestamp,
|
||
|
cores,
|
||
|
metricsValues["IPC"],
|
||
|
metricsValues["LLC_Misses"],
|
||
|
metricsValues["LLC"],
|
||
|
metricsValues["MBL"],
|
||
|
metricsValues["MBR"],
|
||
|
metricsValues["MBT"])
|
||
|
|
||
|
expectedCores := "37,44"
|
||
|
expectedTimestamp := time.Date(2020, 8, 12, 13, 34, 36, 0, time.Local)
|
||
|
|
||
|
result, err := parseCoresMeasurement(measurement)
|
||
|
|
||
|
require.NoError(t, err)
|
||
|
require.Equal(t, expectedCores, result.cores)
|
||
|
require.Equal(t, expectedTimestamp, result.time)
|
||
|
require.InDelta(t, result.values[0], metricsValues["IPC"], testutil.DefaultDelta)
|
||
|
require.InDelta(t, result.values[1], metricsValues["LLC_Misses"], testutil.DefaultDelta)
|
||
|
require.InDelta(t, result.values[2], metricsValues["LLC"], testutil.DefaultDelta)
|
||
|
require.InDelta(t, result.values[3], metricsValues["MBL"], testutil.DefaultDelta)
|
||
|
require.InDelta(t, result.values[4], metricsValues["MBR"], testutil.DefaultDelta)
|
||
|
require.InDelta(t, result.values[5], metricsValues["MBT"], testutil.DefaultDelta)
|
||
|
})
|
||
|
t.Run("not valid measurement string", func(t *testing.T) {
|
||
|
measurement := "not, valid, measurement"
|
||
|
|
||
|
result, err := parseCoresMeasurement(measurement)
|
||
|
|
||
|
require.Error(t, err)
|
||
|
require.Empty(t, result.cores)
|
||
|
require.Nil(t, result.values)
|
||
|
require.Equal(t, time.Time{}, result.time)
|
||
|
})
|
||
|
t.Run("not valid values string", func(t *testing.T) {
|
||
|
measurement := fmt.Sprintf("%s,%s,%s,%s,%f,%f,%f,%f",
|
||
|
timestamp,
|
||
|
cores,
|
||
|
"%d",
|
||
|
"in",
|
||
|
metricsValues["LLC"],
|
||
|
metricsValues["MBL"],
|
||
|
metricsValues["MBR"],
|
||
|
metricsValues["MBT"])
|
||
|
|
||
|
result, err := parseCoresMeasurement(measurement)
|
||
|
|
||
|
require.Error(t, err)
|
||
|
require.Empty(t, result.cores)
|
||
|
require.Nil(t, result.values)
|
||
|
require.Equal(t, time.Time{}, result.time)
|
||
|
})
|
||
|
t.Run("not valid timestamp format", func(t *testing.T) {
|
||
|
invalidTimestamp := "2020-08-12-21 13:34:"
|
||
|
measurement := fmt.Sprintf("%s,%s,%f,%f,%f,%f,%f,%f",
|
||
|
invalidTimestamp,
|
||
|
cores,
|
||
|
metricsValues["IPC"],
|
||
|
metricsValues["LLC_Misses"],
|
||
|
metricsValues["LLC"],
|
||
|
metricsValues["MBL"],
|
||
|
metricsValues["MBR"],
|
||
|
metricsValues["MBT"])
|
||
|
|
||
|
result, err := parseCoresMeasurement(measurement)
|
||
|
|
||
|
require.Error(t, err)
|
||
|
require.Empty(t, result.cores)
|
||
|
require.Nil(t, result.values)
|
||
|
require.Equal(t, time.Time{}, result.time)
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestParseProcessesMeasurement(t *testing.T) {
|
||
|
timestamp := "2020-08-12 13:34:36"
|
||
|
cores := "\"37,44\""
|
||
|
pids := "\"12345,9999\""
|
||
|
processName := "process_name"
|
||
|
|
||
|
t.Run("valid measurement string", func(t *testing.T) {
|
||
|
measurement := fmt.Sprintf("%s,%s,%s,%f,%f,%f,%f,%f,%f",
|
||
|
timestamp,
|
||
|
pids,
|
||
|
cores,
|
||
|
metricsValues["IPC"],
|
||
|
metricsValues["LLC_Misses"],
|
||
|
metricsValues["LLC"],
|
||
|
metricsValues["MBL"],
|
||
|
metricsValues["MBR"],
|
||
|
metricsValues["MBT"])
|
||
|
|
||
|
expectedCores := "37,44"
|
||
|
expectedTimestamp := time.Date(2020, 8, 12, 13, 34, 36, 0, time.Local)
|
||
|
|
||
|
newMeasurement := processMeasurement{
|
||
|
name: processName,
|
||
|
measurement: measurement,
|
||
|
}
|
||
|
result, err := parseProcessesMeasurement(newMeasurement)
|
||
|
|
||
|
require.NoError(t, err)
|
||
|
require.Equal(t, processName, result.process)
|
||
|
require.Equal(t, expectedCores, result.cores)
|
||
|
require.Equal(t, expectedTimestamp, result.time)
|
||
|
require.InDelta(t, result.values[0], metricsValues["IPC"], testutil.DefaultDelta)
|
||
|
require.InDelta(t, result.values[1], metricsValues["LLC_Misses"], testutil.DefaultDelta)
|
||
|
require.InDelta(t, result.values[2], metricsValues["LLC"], testutil.DefaultDelta)
|
||
|
require.InDelta(t, result.values[3], metricsValues["MBL"], testutil.DefaultDelta)
|
||
|
require.InDelta(t, result.values[4], metricsValues["MBR"], testutil.DefaultDelta)
|
||
|
require.InDelta(t, result.values[5], metricsValues["MBT"], testutil.DefaultDelta)
|
||
|
})
|
||
|
|
||
|
invalidTimestamp := "2020-20-20-31"
|
||
|
negativeTests := []struct {
|
||
|
name string
|
||
|
measurement string
|
||
|
}{{
|
||
|
name: "not valid measurement string",
|
||
|
measurement: "invalid,measurement,format",
|
||
|
}, {
|
||
|
name: "not valid timestamp format",
|
||
|
measurement: fmt.Sprintf("%s,%s,%s,%f,%f,%f,%f,%f,%f",
|
||
|
invalidTimestamp,
|
||
|
pids,
|
||
|
cores,
|
||
|
metricsValues["IPC"],
|
||
|
metricsValues["LLC_Misses"],
|
||
|
metricsValues["LLC"],
|
||
|
metricsValues["MBL"],
|
||
|
metricsValues["MBR"],
|
||
|
metricsValues["MBT"]),
|
||
|
},
|
||
|
{
|
||
|
name: "not valid values string",
|
||
|
measurement: fmt.Sprintf("%s,%s,%s,%s,%s,%f,%f,%f,%f",
|
||
|
timestamp,
|
||
|
pids,
|
||
|
cores,
|
||
|
"1##",
|
||
|
"da",
|
||
|
metricsValues["LLC"],
|
||
|
metricsValues["MBL"],
|
||
|
metricsValues["MBR"],
|
||
|
metricsValues["MBT"]),
|
||
|
},
|
||
|
{
|
||
|
name: "not valid csv line with quotes",
|
||
|
measurement: "0000-08-02 0:00:00,,\",,,,,,,,,,,,,,,,,,,,,,,,\",,",
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, test := range negativeTests {
|
||
|
t.Run(test.name, func(t *testing.T) {
|
||
|
newMeasurement := processMeasurement{
|
||
|
name: processName,
|
||
|
measurement: test.measurement,
|
||
|
}
|
||
|
result, err := parseProcessesMeasurement(newMeasurement)
|
||
|
|
||
|
require.Error(t, err)
|
||
|
require.Empty(t, result.process)
|
||
|
require.Empty(t, result.cores)
|
||
|
require.Nil(t, result.values)
|
||
|
require.Equal(t, time.Time{}, result.time)
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestAddToAccumulatorCores(t *testing.T) {
|
||
|
t.Run("shortened false", func(t *testing.T) {
|
||
|
var acc testutil.Accumulator
|
||
|
publisher := publisher{acc: &acc}
|
||
|
|
||
|
cores := "1,2,3"
|
||
|
metricsValues := []float64{1, 2, 3, 4, 5, 6}
|
||
|
timestamp := time.Date(2020, 8, 12, 13, 34, 36, 0, time.Local)
|
||
|
|
||
|
publisher.addToAccumulatorCores(parsedCoresMeasurement{cores, metricsValues, timestamp})
|
||
|
|
||
|
for _, test := range testCoreMetrics {
|
||
|
acc.AssertContainsTaggedFields(t, "rdt_metric", test.fields, test.tags)
|
||
|
}
|
||
|
})
|
||
|
t.Run("shortened true", func(t *testing.T) {
|
||
|
var acc testutil.Accumulator
|
||
|
publisher := publisher{acc: &acc, shortenedMetrics: true}
|
||
|
|
||
|
cores := "1,2,3"
|
||
|
metricsValues := []float64{1, 2, 3, 4, 5, 6}
|
||
|
timestamp := time.Date(2020, 8, 12, 13, 34, 36, 0, time.Local)
|
||
|
|
||
|
publisher.addToAccumulatorCores(parsedCoresMeasurement{cores, metricsValues, timestamp})
|
||
|
|
||
|
for _, test := range testCoreMetricsShortened {
|
||
|
acc.AssertDoesNotContainsTaggedFields(t, "rdt_metric", test.fields, test.tags)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestAddToAccumulatorProcesses(t *testing.T) {
|
||
|
t.Run("shortened false", func(t *testing.T) {
|
||
|
var acc testutil.Accumulator
|
||
|
publisher := publisher{acc: &acc}
|
||
|
|
||
|
process := "process_name"
|
||
|
cores := "1,2,3"
|
||
|
metricsValues := []float64{1, 2, 3, 4, 5, 6}
|
||
|
timestamp := time.Date(2020, 8, 12, 13, 34, 36, 0, time.Local)
|
||
|
|
||
|
publisher.addToAccumulatorProcesses(parsedProcessMeasurement{process, cores, metricsValues, timestamp})
|
||
|
|
||
|
for _, test := range testCoreProcesses {
|
||
|
acc.AssertContainsTaggedFields(t, "rdt_metric", test.fields, test.tags)
|
||
|
}
|
||
|
})
|
||
|
t.Run("shortened true", func(t *testing.T) {
|
||
|
var acc testutil.Accumulator
|
||
|
publisher := publisher{acc: &acc, shortenedMetrics: true}
|
||
|
|
||
|
process := "process_name"
|
||
|
cores := "1,2,3"
|
||
|
metricsValues := []float64{1, 2, 3, 4, 5, 6}
|
||
|
timestamp := time.Date(2020, 8, 12, 13, 34, 36, 0, time.Local)
|
||
|
|
||
|
publisher.addToAccumulatorProcesses(parsedProcessMeasurement{process, cores, metricsValues, timestamp})
|
||
|
|
||
|
for _, test := range testCoreProcessesShortened {
|
||
|
acc.AssertDoesNotContainsTaggedFields(t, "rdt_metric", test.fields, test.tags)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
var (
|
||
|
testCoreMetrics = []struct {
|
||
|
fields map[string]interface{}
|
||
|
tags map[string]string
|
||
|
}{
|
||
|
{
|
||
|
map[string]interface{}{
|
||
|
"value": float64(1),
|
||
|
},
|
||
|
map[string]string{
|
||
|
"cores": "1,2,3",
|
||
|
"name": "IPC",
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
map[string]interface{}{
|
||
|
"value": float64(2),
|
||
|
},
|
||
|
map[string]string{
|
||
|
"cores": "1,2,3",
|
||
|
"name": "LLC_Misses",
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
map[string]interface{}{
|
||
|
"value": float64(3),
|
||
|
},
|
||
|
map[string]string{
|
||
|
"cores": "1,2,3",
|
||
|
"name": "LLC",
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
map[string]interface{}{
|
||
|
"value": float64(4),
|
||
|
},
|
||
|
map[string]string{
|
||
|
"cores": "1,2,3",
|
||
|
"name": "MBL",
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
map[string]interface{}{
|
||
|
"value": float64(5),
|
||
|
},
|
||
|
map[string]string{
|
||
|
"cores": "1,2,3",
|
||
|
"name": "MBR",
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
map[string]interface{}{
|
||
|
"value": float64(6),
|
||
|
},
|
||
|
map[string]string{
|
||
|
"cores": "1,2,3",
|
||
|
"name": "MBT",
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
testCoreMetricsShortened = []struct {
|
||
|
fields map[string]interface{}
|
||
|
tags map[string]string
|
||
|
}{
|
||
|
{
|
||
|
map[string]interface{}{
|
||
|
"value": float64(1),
|
||
|
},
|
||
|
map[string]string{
|
||
|
"cores": "1,2,3",
|
||
|
"name": "IPC",
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
map[string]interface{}{
|
||
|
"value": float64(2),
|
||
|
},
|
||
|
map[string]string{
|
||
|
"cores": "1,2,3",
|
||
|
"name": "LLC_Misses",
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
testCoreProcesses = []struct {
|
||
|
fields map[string]interface{}
|
||
|
tags map[string]string
|
||
|
}{
|
||
|
{
|
||
|
map[string]interface{}{
|
||
|
"value": float64(1),
|
||
|
},
|
||
|
map[string]string{
|
||
|
"cores": "1,2,3",
|
||
|
"name": "IPC",
|
||
|
"process": "process_name",
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
map[string]interface{}{
|
||
|
"value": float64(2),
|
||
|
},
|
||
|
map[string]string{
|
||
|
"cores": "1,2,3",
|
||
|
"name": "LLC_Misses",
|
||
|
"process": "process_name",
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
map[string]interface{}{
|
||
|
"value": float64(3),
|
||
|
},
|
||
|
map[string]string{
|
||
|
"cores": "1,2,3",
|
||
|
"name": "LLC",
|
||
|
"process": "process_name",
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
map[string]interface{}{
|
||
|
"value": float64(4),
|
||
|
},
|
||
|
map[string]string{
|
||
|
"cores": "1,2,3",
|
||
|
"name": "MBL",
|
||
|
"process": "process_name",
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
map[string]interface{}{
|
||
|
"value": float64(5),
|
||
|
},
|
||
|
map[string]string{
|
||
|
"cores": "1,2,3",
|
||
|
"name": "MBR",
|
||
|
"process": "process_name",
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
map[string]interface{}{
|
||
|
"value": float64(6),
|
||
|
},
|
||
|
map[string]string{
|
||
|
"cores": "1,2,3",
|
||
|
"name": "MBT",
|
||
|
"process": "process_name",
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
testCoreProcessesShortened = []struct {
|
||
|
fields map[string]interface{}
|
||
|
tags map[string]string
|
||
|
}{
|
||
|
{
|
||
|
map[string]interface{}{
|
||
|
"value": float64(1),
|
||
|
},
|
||
|
map[string]string{
|
||
|
"cores": "1,2,3",
|
||
|
"name": "IPC",
|
||
|
"process": "process_name",
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
map[string]interface{}{
|
||
|
"value": float64(2),
|
||
|
},
|
||
|
map[string]string{
|
||
|
"cores": "1,2,3",
|
||
|
"name": "LLC_Misses",
|
||
|
"process": "process_name",
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
)
|