2019-05-22 23:16:55 +02:00
|
|
|
package graphite
|
|
|
|
|
|
|
|
import (
|
2020-07-08 12:59:19 +02:00
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/fasttime"
|
2019-05-22 23:16:55 +02:00
|
|
|
"reflect"
|
2020-07-08 12:59:19 +02:00
|
|
|
"strings"
|
2019-05-22 23:16:55 +02:00
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestRowsUnmarshalFailure(t *testing.T) {
|
|
|
|
f := func(s string) {
|
|
|
|
t.Helper()
|
|
|
|
var rows Rows
|
2019-08-24 11:42:59 +02:00
|
|
|
rows.Unmarshal(s)
|
|
|
|
if len(rows.Rows) != 0 {
|
|
|
|
t.Fatalf("unexpected number of rows parsed; got %d; want 0", len(rows.Rows))
|
2019-05-22 23:16:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Try again
|
2019-08-24 11:42:59 +02:00
|
|
|
rows.Unmarshal(s)
|
|
|
|
if len(rows.Rows) != 0 {
|
|
|
|
t.Fatalf("unexpected number of rows parsed; got %d; want 0", len(rows.Rows))
|
2019-05-22 23:16:55 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-24 12:35:29 +02:00
|
|
|
// Missing metric
|
|
|
|
f(" 123 455")
|
|
|
|
|
2019-05-22 23:16:55 +02:00
|
|
|
// Missing value
|
|
|
|
f("aaa")
|
|
|
|
|
|
|
|
// missing tag
|
|
|
|
f("aa; 12 34")
|
|
|
|
|
|
|
|
// missing tag value
|
|
|
|
f("aa;bb 23 34")
|
2020-09-16 00:33:32 +02:00
|
|
|
|
|
|
|
// unexpected space in tag value
|
|
|
|
// See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/99
|
|
|
|
f("s;tag1=aaa1;tag2=bb b2;tag3=ccc3 1")
|
|
|
|
|
|
|
|
// invalid value
|
|
|
|
f("aa bb")
|
|
|
|
|
|
|
|
// invalid timestamp
|
|
|
|
f("aa 123 bar")
|
2019-05-22 23:16:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestRowsUnmarshalSuccess(t *testing.T) {
|
|
|
|
f := func(s string, rowsExpected *Rows) {
|
|
|
|
t.Helper()
|
|
|
|
var rows Rows
|
2019-08-24 11:42:59 +02:00
|
|
|
rows.Unmarshal(s)
|
2019-05-22 23:16:55 +02:00
|
|
|
if !reflect.DeepEqual(rows.Rows, rowsExpected.Rows) {
|
|
|
|
t.Fatalf("unexpected rows;\ngot\n%+v;\nwant\n%+v", rows.Rows, rowsExpected.Rows)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try unmarshaling again
|
2019-08-24 11:42:59 +02:00
|
|
|
rows.Unmarshal(s)
|
2019-05-22 23:16:55 +02:00
|
|
|
if !reflect.DeepEqual(rows.Rows, rowsExpected.Rows) {
|
|
|
|
t.Fatalf("unexpected rows;\ngot\n%+v;\nwant\n%+v", rows.Rows, rowsExpected.Rows)
|
|
|
|
}
|
|
|
|
|
|
|
|
rows.Reset()
|
|
|
|
if len(rows.Rows) != 0 {
|
|
|
|
t.Fatalf("non-empty rows after reset: %+v", rows.Rows)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Empty line
|
|
|
|
f("", &Rows{})
|
2019-08-24 11:42:59 +02:00
|
|
|
f("\r", &Rows{})
|
2019-05-22 23:16:55 +02:00
|
|
|
f("\n\n", &Rows{})
|
2019-08-24 11:42:59 +02:00
|
|
|
f("\n\r\n", &Rows{})
|
2019-05-22 23:16:55 +02:00
|
|
|
|
|
|
|
// Single line
|
|
|
|
f("foobar -123.456 789", &Rows{
|
|
|
|
Rows: []Row{{
|
|
|
|
Metric: "foobar",
|
|
|
|
Value: -123.456,
|
|
|
|
Timestamp: 789,
|
|
|
|
}},
|
|
|
|
})
|
|
|
|
f("foo.bar 123.456 789\n", &Rows{
|
|
|
|
Rows: []Row{{
|
|
|
|
Metric: "foo.bar",
|
|
|
|
Value: 123.456,
|
|
|
|
Timestamp: 789,
|
|
|
|
}},
|
|
|
|
})
|
|
|
|
|
2019-06-18 18:04:02 +02:00
|
|
|
// Missing timestamp
|
|
|
|
f("aaa 1123", &Rows{
|
|
|
|
Rows: []Row{{
|
|
|
|
Metric: "aaa",
|
|
|
|
Value: 1123,
|
|
|
|
}},
|
|
|
|
})
|
2020-07-08 13:10:31 +02:00
|
|
|
f("aaa 1123 -1", &Rows{
|
|
|
|
Rows: []Row{{
|
2020-07-08 13:12:10 +02:00
|
|
|
Metric: "aaa",
|
|
|
|
Value: 1123,
|
2020-07-08 13:10:31 +02:00
|
|
|
Timestamp: -1,
|
|
|
|
}},
|
|
|
|
})
|
2019-06-18 18:04:02 +02:00
|
|
|
|
2019-10-17 17:22:56 +02:00
|
|
|
// Timestamp bigger than 1<<31
|
|
|
|
f("aaa 1123 429496729600", &Rows{
|
|
|
|
Rows: []Row{{
|
2019-10-17 19:04:26 +02:00
|
|
|
Metric: "aaa",
|
|
|
|
Value: 1123,
|
2019-10-17 17:22:56 +02:00
|
|
|
Timestamp: 429496729600,
|
|
|
|
}},
|
|
|
|
})
|
|
|
|
|
2020-10-06 10:37:50 +02:00
|
|
|
// Floating-point timestamp
|
|
|
|
// See https://github.com/graphite-project/carbon/blob/b0ba62a62d40a37950fed47a8f6ae6d0f02e6af5/lib/carbon/protocols.py#L197
|
|
|
|
f("aaa 1123 4294.943", &Rows{
|
|
|
|
Rows: []Row{{
|
|
|
|
Metric: "aaa",
|
|
|
|
Value: 1123,
|
|
|
|
Timestamp: 4294,
|
|
|
|
}},
|
|
|
|
})
|
|
|
|
|
2019-05-22 23:16:55 +02:00
|
|
|
// Tags
|
|
|
|
f("foo;bar=baz 1 2", &Rows{
|
|
|
|
Rows: []Row{{
|
|
|
|
Metric: "foo",
|
|
|
|
Tags: []Tag{{
|
|
|
|
Key: "bar",
|
|
|
|
Value: "baz",
|
|
|
|
}},
|
|
|
|
Value: 1,
|
|
|
|
Timestamp: 2,
|
|
|
|
}},
|
|
|
|
})
|
2019-08-24 12:35:29 +02:00
|
|
|
// Empty tags
|
|
|
|
f("foo;bar=baz;aa=;x=y;=z 1 2", &Rows{
|
2019-05-22 23:16:55 +02:00
|
|
|
Rows: []Row{{
|
|
|
|
Metric: "foo",
|
|
|
|
Tags: []Tag{
|
|
|
|
{
|
|
|
|
Key: "bar",
|
|
|
|
Value: "baz",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Key: "x",
|
|
|
|
Value: "y",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Value: 1,
|
|
|
|
Timestamp: 2,
|
|
|
|
}},
|
|
|
|
})
|
|
|
|
|
|
|
|
// Multi lines
|
2019-06-18 18:04:02 +02:00
|
|
|
f("foo 0.3 2\naaa 3\nbar.baz 0.34 43\n", &Rows{
|
2019-05-22 23:16:55 +02:00
|
|
|
Rows: []Row{
|
|
|
|
{
|
|
|
|
Metric: "foo",
|
|
|
|
Value: 0.3,
|
|
|
|
Timestamp: 2,
|
|
|
|
},
|
2019-06-18 18:04:02 +02:00
|
|
|
{
|
|
|
|
Metric: "aaa",
|
|
|
|
Value: 3,
|
|
|
|
},
|
2019-05-22 23:16:55 +02:00
|
|
|
{
|
|
|
|
Metric: "bar.baz",
|
|
|
|
Value: 0.34,
|
|
|
|
Timestamp: 43,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
2019-08-24 11:42:59 +02:00
|
|
|
|
|
|
|
// Multi lines with invalid line
|
|
|
|
f("foo 0.3 2\naaa\nbar.baz 0.34 43\n", &Rows{
|
|
|
|
Rows: []Row{
|
|
|
|
{
|
|
|
|
Metric: "foo",
|
|
|
|
Value: 0.3,
|
|
|
|
Timestamp: 2,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Metric: "bar.baz",
|
|
|
|
Value: 0.34,
|
|
|
|
Timestamp: 43,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
2019-05-22 23:16:55 +02:00
|
|
|
}
|
2020-07-08 12:59:19 +02:00
|
|
|
|
|
|
|
func Test_streamContext_Read(t *testing.T) {
|
|
|
|
f := func(s string, rowsExpected *Rows) {
|
|
|
|
t.Helper()
|
2020-09-28 01:06:27 +02:00
|
|
|
ctx := getStreamContext(strings.NewReader(s))
|
2020-09-28 03:11:55 +02:00
|
|
|
if !ctx.Read() {
|
|
|
|
t.Fatalf("expecting successful read")
|
2020-07-08 12:59:19 +02:00
|
|
|
}
|
2020-09-28 03:11:55 +02:00
|
|
|
uw := getUnmarshalWork()
|
|
|
|
callbackCalls := 0
|
2020-11-13 12:03:54 +01:00
|
|
|
uw.callback = func(rows []Row) {
|
2020-09-28 03:11:55 +02:00
|
|
|
callbackCalls++
|
|
|
|
if len(rows) != len(rowsExpected.Rows) {
|
|
|
|
t.Fatalf("different len of expected rows;\ngot\n%+v;\nwant\n%+v", rows, rowsExpected.Rows)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(rows, rowsExpected.Rows) {
|
|
|
|
t.Fatalf("unexpected rows;\ngot\n%+v;\nwant\n%+v", rows, rowsExpected.Rows)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
uw.reqBuf = append(uw.reqBuf[:0], ctx.reqBuf...)
|
|
|
|
uw.Unmarshal()
|
|
|
|
if callbackCalls != 1 {
|
|
|
|
t.Fatalf("unexpected number of callback calls; got %d; want 1", callbackCalls)
|
2020-07-08 12:59:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-08 13:10:31 +02:00
|
|
|
// Full line without tags
|
|
|
|
f("aaa 1123 345", &Rows{
|
|
|
|
Rows: []Row{{
|
|
|
|
Metric: "aaa",
|
|
|
|
Value: 1123,
|
2020-07-08 13:12:10 +02:00
|
|
|
Timestamp: 345 * 1000,
|
2020-07-08 13:10:31 +02:00
|
|
|
}},
|
|
|
|
})
|
|
|
|
// Full line with tags
|
|
|
|
f("aaa;x=y 1123 345", &Rows{
|
|
|
|
Rows: []Row{{
|
2020-07-08 13:12:10 +02:00
|
|
|
Metric: "aaa",
|
2020-07-08 13:10:31 +02:00
|
|
|
Tags: []Tag{{
|
2020-07-08 13:12:10 +02:00
|
|
|
Key: "x",
|
2020-07-08 13:10:31 +02:00
|
|
|
Value: "y",
|
|
|
|
}},
|
|
|
|
Value: 1123,
|
2020-07-08 13:12:10 +02:00
|
|
|
Timestamp: 345 * 1000,
|
2020-07-08 13:10:31 +02:00
|
|
|
}},
|
|
|
|
})
|
|
|
|
// missing timestamp.
|
|
|
|
// Note that this test may be flaky due to timing issues. TODO: fix it
|
2020-07-08 12:59:19 +02:00
|
|
|
f("aaa 1123", &Rows{
|
|
|
|
Rows: []Row{{
|
|
|
|
Metric: "aaa",
|
|
|
|
Value: 1123,
|
2020-07-08 13:10:31 +02:00
|
|
|
Timestamp: int64(fasttime.UnixTimestamp()) * 1000,
|
|
|
|
}},
|
|
|
|
})
|
|
|
|
// -1 timestamp. See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/610
|
|
|
|
// Note that this test may be flaky due to timing issues. TODO: fix it.
|
|
|
|
f("aaa 1123 -1", &Rows{
|
|
|
|
Rows: []Row{{
|
|
|
|
Metric: "aaa",
|
|
|
|
Value: 1123,
|
|
|
|
Timestamp: int64(fasttime.UnixTimestamp()) * 1000,
|
2020-07-08 12:59:19 +02:00
|
|
|
}},
|
|
|
|
})
|
|
|
|
}
|