TestData: support boolean and strings in CSV metric response (#33099)

This commit is contained in:
Ryan McKinley 2021-04-20 11:17:06 -07:00 committed by GitHub
parent fa620c1c38
commit 18bbbaf53e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 83 additions and 19 deletions

View File

@ -328,6 +328,47 @@ func (p *testDataPlugin) handleManualEntryScenario(ctx context.Context, req *bac
return resp, nil
}
func csvToFieldValues(stringInput string) (*data.Field, error) {
parts := strings.Split(strings.ReplaceAll(stringInput, " ", ""), ",")
if len(parts) < 1 {
return nil, fmt.Errorf("csv must have at least one value")
}
first := parts[0]
if first == "T" || first == "F" {
field := data.NewFieldFromFieldType(data.FieldTypeNullableBool, len(parts))
for idx, strVal := range parts {
if strVal == "null" || strVal == "" {
continue
}
field.SetConcrete(idx, strVal == "T")
}
return field, nil
}
// If we can not parse the first value as a number, assume strings
_, err := strconv.ParseFloat(first, 64)
if err != nil {
field := data.NewFieldFromFieldType(data.FieldTypeNullableString, len(parts))
for idx, strVal := range parts {
if strVal == "null" || strVal == "" {
continue
}
field.SetConcrete(idx, strVal)
}
return field, nil
}
// Set any valid numbers
field := data.NewFieldFromFieldType(data.FieldTypeNullableFloat64, len(parts))
for idx, strVal := range parts {
if val, err := strconv.ParseFloat(strVal, 64); err == nil {
field.SetConcrete(idx, val)
}
}
return field, nil
}
func (p *testDataPlugin) handleCSVMetricValuesScenario(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
resp := backend.NewQueryDataResponse()
@ -338,38 +379,32 @@ func (p *testDataPlugin) handleCSVMetricValuesScenario(ctx context.Context, req
}
stringInput := model.Get("stringInput").MustString()
stringInput = strings.ReplaceAll(stringInput, " ", "")
var values []*float64
for _, strVal := range strings.Split(stringInput, ",") {
if strVal == "null" {
values = append(values, nil)
}
if val, err := strconv.ParseFloat(strVal, 64); err == nil {
values = append(values, &val)
}
valueField, err := csvToFieldValues(stringInput)
if err != nil {
return nil, err
}
valueField.Name = frameNameForQuery(q, model, 0)
if len(values) == 0 {
return resp, nil
}
timeField := data.NewFieldFromFieldType(data.FieldTypeTime, valueField.Len())
timeField.Name = "time"
frame := data.NewFrame("",
data.NewField("time", nil, []*time.Time{}),
data.NewField(frameNameForQuery(q, model, 0), nil, []*float64{}))
startTime := q.TimeRange.From.UnixNano() / int64(time.Millisecond)
endTime := q.TimeRange.To.UnixNano() / int64(time.Millisecond)
count := valueField.Len()
var step int64 = 0
if len(values) > 1 {
step = (endTime - startTime) / int64(len(values)-1)
if count > 1 {
step = (endTime - startTime) / int64(count-1)
}
for _, val := range values {
for i := 0; i < count; i++ {
t := time.Unix(startTime/int64(1e+3), (startTime%int64(1e+3))*int64(1e+6))
frame.AppendRow(&t, val)
timeField.Set(i, t)
startTime += step
}
frame := data.NewFrame("", timeField, valueField)
respD := resp.Responses[q.RefID]
respD.Frames = append(respD.Frames, frame)
resp.Responses[q.RefID] = respD

View File

@ -263,3 +263,32 @@ func TestParseLabels(t *testing.T) {
assert.Equal(t, expectedTags, parseLabels(model), fmt.Sprintf("Actual tags in test case %d doesn't match expected tags", i+1))
}
}
func TestReadCSV(t *testing.T) {
fBool, err := csvToFieldValues("T, F,F,T ,")
require.NoError(t, err)
fNum, err := csvToFieldValues("1,2,,4,5")
require.NoError(t, err)
fStr, err := csvToFieldValues("a,b,,,c")
require.NoError(t, err)
frame := data.NewFrame("", fBool, fNum, fStr)
out, err := data.FrameToJSON(frame, true, true)
require.NoError(t, err)
// require.Equal(t, "", string(out))
require.JSONEq(t, `{"schema":{
"fields":[
{"type":"bool","typeInfo":{"frame":"bool","nullable":true}},
{"type":"number","typeInfo":{"frame":"float64","nullable":true}},
{"type":"string","typeInfo":{"frame":"string","nullable":true}}
]},"data":{
"values":[
[true,false,false,true,null],
[1,2,null,4,5],
["a","b",null,null,"c"]
]}}`, string(out))
}