grafana/pkg/services/live/telemetry/telegraf/convert_test.go
Jo 062d255124
Handle ioutil deprecations (#53526)
* replace ioutil.ReadFile -> os.ReadFile

* replace ioutil.ReadAll -> io.ReadAll

* replace ioutil.TempFile -> os.CreateTemp

* replace ioutil.NopCloser -> io.NopCloser

* replace ioutil.WriteFile -> os.WriteFile

* replace ioutil.TempDir -> os.MkdirTemp

* replace ioutil.Discard -> io.Discard
2022-08-10 15:37:51 +02:00

270 lines
8.3 KiB
Go

package telegraf
import (
"encoding/json"
"flag"
"fmt"
"os"
"path/filepath"
"testing"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana-plugin-sdk-go/experimental"
"github.com/stretchr/testify/require"
)
func loadTestData(tb testing.TB, file string) []byte {
tb.Helper()
// Safe to disable, this is a test.
// nolint:gosec
content, err := os.ReadFile(filepath.Join("testdata", file+".txt"))
require.NoError(tb, err, "expected to be able to read file")
require.True(tb, len(content) > 0)
return content
}
func checkTestData(t *testing.T, file string) *backend.DataResponse {
t.Helper()
// Safe to disable, this is a test.
// nolint:gosec
content, err := os.ReadFile(filepath.Join("testdata", file+".txt"))
require.NoError(t, err, "expected to be able to read file")
require.True(t, len(content) > 0)
converter := NewConverter(WithUseLabelsColumn(true))
frameWrappers, err := converter.Convert(content)
require.NoError(t, err)
dr := &backend.DataResponse{}
for _, w := range frameWrappers {
dr.Frames = append(dr.Frames, w.Frame())
}
experimental.CheckGoldenJSONResponse(t, "testdata", file, dr, false)
return dr
}
func TestNewConverter(t *testing.T) {
c := NewConverter(WithUseLabelsColumn(true))
require.True(t, c.useLabelsColumn)
}
func TestConverter_Convert(t *testing.T) {
testCases := []struct {
Name string
NumFields int
FieldLength int
NumFrames int
}{
{Name: "single_metric", NumFields: 6, FieldLength: 1, NumFrames: 1},
{Name: "same_metrics_same_labels_different_time", NumFields: 6, FieldLength: 1, NumFrames: 3},
{Name: "same_metrics_different_labels_different_time", NumFields: 6, FieldLength: 1, NumFrames: 2},
{Name: "same_metrics_different_labels_same_time", NumFields: 131, FieldLength: 1, NumFrames: 1},
}
for _, tt := range testCases {
t.Run(tt.Name, func(t *testing.T) {
testData := loadTestData(t, tt.Name)
converter := NewConverter()
frameWrappers, err := converter.Convert(testData)
require.NoError(t, err)
require.Len(t, frameWrappers, tt.NumFrames)
for _, fw := range frameWrappers {
frame := fw.Frame()
require.Len(t, frame.Fields, tt.NumFields)
require.Equal(t, tt.FieldLength, frame.Fields[0].Len())
_, err := data.FrameToJSON(frame, data.IncludeAll)
require.NoError(t, err)
}
})
}
}
func TestConverter_Convert_LabelsColumn(t *testing.T) {
testCases := []struct {
Name string
NumFields int
FieldLength int
NumFrames int
}{
{Name: "single_metric", NumFields: 7, FieldLength: 1, NumFrames: 1},
{Name: "same_metrics_same_labels_different_time", NumFields: 7, FieldLength: 3, NumFrames: 1},
{Name: "same_metrics_different_labels_different_time", NumFields: 7, FieldLength: 2, NumFrames: 1},
{Name: "same_metrics_different_labels_same_time", NumFields: 12, FieldLength: 13, NumFrames: 1},
{Name: "incomplete_fields", NumFields: 4, FieldLength: 4, NumFrames: 1},
{Name: "incomplete_fields_2", NumFields: 4, FieldLength: 5, NumFrames: 1},
{Name: "incomplete_fields_full", NumFrames: 5},
}
for _, tt := range testCases {
t.Run(tt.Name, func(t *testing.T) {
testData := loadTestData(t, tt.Name)
if *pprint {
fmt.Println(string(testData))
}
converter := NewConverter(WithUseLabelsColumn(true))
frameWrappers, err := converter.Convert(testData)
require.NoError(t, err)
require.Len(t, frameWrappers, tt.NumFrames)
for _, fw := range frameWrappers {
frame := fw.Frame()
if tt.NumFrames == 1 {
require.Len(t, frame.Fields, tt.NumFields)
require.Equal(t, tt.FieldLength, frame.Fields[0].Len())
}
_, err := data.FrameToJSON(frame, data.IncludeAll)
require.NoError(t, err)
if *pprint {
s, err := frame.StringTable(100, 100)
require.NoError(t, err)
fmt.Println(s)
}
}
})
}
}
var update = flag.Bool("update", false, "update golden files")
var pprint = flag.Bool("pprint", false, "pretty print test case")
func TestConverter_Convert_NumFrameFields(t *testing.T) {
testData := loadTestData(t, "same_metrics_different_labels_same_time")
converter := NewConverter()
frameWrappers, err := converter.Convert(testData)
require.NoError(t, err)
require.Len(t, frameWrappers, 1)
frameWrapper := frameWrappers[0]
goldenFile := filepath.Join("testdata", "golden_wide.json")
frame := frameWrapper.Frame()
require.Len(t, frame.Fields, 131) // 10 measurements across 13 metrics + time field.
frameJSON, err := json.MarshalIndent(frame, "", " ")
require.NoError(t, err)
if *update {
if err := os.WriteFile(goldenFile, frameJSON, 0600); err != nil {
t.Fatal(err)
}
}
// Safe to disable, this is a test.
// nolint:gosec
want, err := os.ReadFile(goldenFile)
if err != nil {
t.Fatal(err)
}
require.JSONEqf(t, string(frameJSON), string(want), "not matched with golden file")
}
func TestConverter_Convert_ChangingTypes(t *testing.T) {
dr := checkTestData(t, "changing_types_NaN")
require.NotNil(t, dr)
}
func TestConverter_Convert_FieldOrder(t *testing.T) {
converter := NewConverter()
testData := loadTestData(t, "single_metric")
frameWrappers, err := converter.Convert(testData)
require.NoError(t, err)
require.Len(t, frameWrappers, 1)
frameJSON1, err := data.FrameToJSON(frameWrappers[0].Frame(), data.IncludeAll)
require.NoError(t, err)
testDataDifferentOrder := loadTestData(t, "single_metric_different_field_order")
frameWrappers, err = converter.Convert(testDataDifferentOrder)
require.NoError(t, err)
require.Len(t, frameWrappers, 1)
frameJSON2, err := data.FrameToJSON(frameWrappers[0].Frame(), data.IncludeAll)
require.NoError(t, err)
require.JSONEqf(t, string(frameJSON1), string(frameJSON2), "frames must match")
}
func BenchmarkConverter_Convert_Wide(b *testing.B) {
testData := loadTestData(b, "same_metrics_different_labels_same_time")
converter := NewConverter()
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := converter.Convert(testData)
if err != nil {
b.Fatal(err)
}
}
}
func BenchmarkConverter_Convert_LabelsColumn(b *testing.B) {
testData := loadTestData(b, "same_metrics_different_labels_same_time")
converter := NewConverter(WithUseLabelsColumn(true))
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := converter.Convert(testData)
if err != nil {
b.Fatal(err)
}
}
}
func TestConverter_Convert_NumFrameFields_LabelsColumn(t *testing.T) {
testData := loadTestData(t, "same_metrics_different_labels_same_time")
converter := NewConverter(WithUseLabelsColumn(true))
frameWrappers, err := converter.Convert(testData)
require.NoError(t, err)
require.Len(t, frameWrappers, 1)
frameWrapper := frameWrappers[0]
goldenFile := filepath.Join("testdata", "golden_labels_column.json")
frame := frameWrapper.Frame()
require.Len(t, frame.Fields, 12)
frameJSON, err := json.MarshalIndent(frame, "", " ")
require.NoError(t, err)
if *update {
if err := os.WriteFile(goldenFile, frameJSON, 0600); err != nil {
t.Fatal(err)
}
}
// Safe to disable, this is a test.
// nolint:gosec
want, err := os.ReadFile(goldenFile)
if err != nil {
t.Fatal(err)
}
require.JSONEqf(t, string(frameJSON), string(want), "not matched with golden file")
}
func TestConverter_Convert_MixedNumberTypes_OK(t *testing.T) {
testData := loadTestData(t, "mixed_number_types")
converter := NewConverter(WithFloat64Numbers(true))
frameWrappers, err := converter.Convert(testData)
require.NoError(t, err)
require.Len(t, frameWrappers, 2)
}
func TestConverter_Convert_MixedNumberTypes_OK_LabelsColumn(t *testing.T) {
testData := loadTestData(t, "mixed_number_types")
converter := NewConverter(WithUseLabelsColumn(true), WithFloat64Numbers(true))
frameWrappers, err := converter.Convert(testData)
require.NoError(t, err)
require.Len(t, frameWrappers, 1)
}
func TestConverter_Convert_PartInput(t *testing.T) {
testData := loadTestData(t, "part_metrics_different_labels_different_time")
converter := NewConverter()
frameWrappers, err := converter.Convert(testData)
require.NoError(t, err)
require.Len(t, frameWrappers, 2)
}
func TestConverter_Convert_PartInput_LabelsColumn(t *testing.T) {
testData := loadTestData(t, "part_metrics_different_labels_different_time")
converter := NewConverter(WithUseLabelsColumn(true))
frameWrappers, err := converter.Convert(testData)
require.NoError(t, err)
require.Len(t, frameWrappers, 1)
}