2023-07-20 10:10:55 +02:00
|
|
|
package loki
|
|
|
|
|
|
|
|
import (
|
2023-07-21 01:21:47 +02:00
|
|
|
"fmt"
|
2023-07-20 10:10:55 +02:00
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logstorage"
|
|
|
|
)
|
|
|
|
|
2023-07-21 01:21:47 +02:00
|
|
|
func TestParseJSONRequestFailure(t *testing.T) {
|
|
|
|
f := func(s string) {
|
2023-07-20 10:10:55 +02:00
|
|
|
t.Helper()
|
2023-10-02 16:26:02 +02:00
|
|
|
n, err := parseJSONRequest([]byte(s), func(timestamp int64, fields []logstorage.Field) {
|
2023-07-21 01:21:47 +02:00
|
|
|
t.Fatalf("unexpected call to parseJSONRequest callback!")
|
2023-07-20 10:10:55 +02:00
|
|
|
})
|
2023-07-21 01:21:47 +02:00
|
|
|
if err == nil {
|
|
|
|
t.Fatalf("expecting non-nil error")
|
2023-07-20 10:10:55 +02:00
|
|
|
}
|
2023-07-21 01:21:47 +02:00
|
|
|
if n != 0 {
|
|
|
|
t.Fatalf("unexpected number of parsed lines: %d; want 0", n)
|
2023-07-20 10:10:55 +02:00
|
|
|
}
|
|
|
|
}
|
2023-07-21 01:21:47 +02:00
|
|
|
f(``)
|
2023-07-20 10:10:55 +02:00
|
|
|
|
2023-07-21 01:21:47 +02:00
|
|
|
// Invalid json
|
|
|
|
f(`{}`)
|
|
|
|
f(`[]`)
|
|
|
|
f(`"foo"`)
|
|
|
|
f(`123`)
|
2023-07-20 10:10:55 +02:00
|
|
|
|
2023-07-21 01:21:47 +02:00
|
|
|
// invalid type for `streams` item
|
|
|
|
f(`{"streams":123}`)
|
2023-07-20 10:10:55 +02:00
|
|
|
|
2023-07-21 01:21:47 +02:00
|
|
|
// Missing `values` item
|
|
|
|
f(`{"streams":[{}]}`)
|
2023-07-20 10:10:55 +02:00
|
|
|
|
2023-07-21 01:21:47 +02:00
|
|
|
// Invalid type for `values` item
|
|
|
|
f(`{"streams":[{"values":"foobar"}]}`)
|
|
|
|
|
|
|
|
// Invalid type for `stream` item
|
|
|
|
f(`{"streams":[{"stream":[],"values":[]}]}`)
|
|
|
|
|
|
|
|
// Invalid type for `values` individual item
|
|
|
|
f(`{"streams":[{"values":[123]}]}`)
|
|
|
|
|
|
|
|
// Invalid length of `values` individual item
|
|
|
|
f(`{"streams":[{"values":[[]]}]}`)
|
|
|
|
f(`{"streams":[{"values":[["123"]]}]}`)
|
|
|
|
f(`{"streams":[{"values":[["123","456","789"]]}]}`)
|
|
|
|
|
|
|
|
// Invalid type for timestamp inside `values` individual item
|
|
|
|
f(`{"streams":[{"values":[[123,"456"]}]}`)
|
2023-07-20 10:10:55 +02:00
|
|
|
|
2023-07-21 01:21:47 +02:00
|
|
|
// Invalid type for log message
|
|
|
|
f(`{"streams":[{"values":[["123",1234]]}]}`)
|
2023-07-20 10:10:55 +02:00
|
|
|
}
|
|
|
|
|
2023-07-21 01:21:47 +02:00
|
|
|
func TestParseJSONRequestSuccess(t *testing.T) {
|
|
|
|
f := func(s string, resultExpected string) {
|
2023-07-20 10:10:55 +02:00
|
|
|
t.Helper()
|
2023-07-21 01:21:47 +02:00
|
|
|
var lines []string
|
2023-10-02 16:26:02 +02:00
|
|
|
n, err := parseJSONRequest([]byte(s), func(timestamp int64, fields []logstorage.Field) {
|
2023-07-21 01:21:47 +02:00
|
|
|
var a []string
|
|
|
|
for _, f := range fields {
|
|
|
|
a = append(a, f.String())
|
|
|
|
}
|
|
|
|
line := fmt.Sprintf("_time:%d %s", timestamp, strings.Join(a, " "))
|
|
|
|
lines = append(lines, line)
|
|
|
|
})
|
2023-07-20 10:10:55 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unexpected error: %s", err)
|
|
|
|
}
|
2023-07-21 01:21:47 +02:00
|
|
|
if n != len(lines) {
|
|
|
|
t.Fatalf("unexpected number of lines parsed; got %d; want %d", n, len(lines))
|
|
|
|
}
|
|
|
|
result := strings.Join(lines, "\n")
|
|
|
|
if result != resultExpected {
|
|
|
|
t.Fatalf("unexpected result;\ngot\n%s\nwant\n%s", result, resultExpected)
|
2023-07-20 10:10:55 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-21 01:21:47 +02:00
|
|
|
// Empty streams
|
|
|
|
f(`{"streams":[]}`, ``)
|
|
|
|
f(`{"streams":[{"values":[]}]}`, ``)
|
|
|
|
f(`{"streams":[{"stream":{},"values":[]}]}`, ``)
|
|
|
|
f(`{"streams":[{"stream":{"foo":"bar"},"values":[]}]}`, ``)
|
|
|
|
|
|
|
|
// Empty stream labels
|
|
|
|
f(`{"streams":[{"values":[["1577836800000000001", "foo bar"]]}]}`, `_time:1577836800000000001 "_msg":"foo bar"`)
|
|
|
|
f(`{"streams":[{"stream":{},"values":[["1577836800000000001", "foo bar"]]}]}`, `_time:1577836800000000001 "_msg":"foo bar"`)
|
|
|
|
|
|
|
|
// Non-empty stream labels
|
|
|
|
f(`{"streams":[{"stream":{
|
|
|
|
"label1": "value1",
|
|
|
|
"label2": "value2"
|
|
|
|
},"values":[
|
|
|
|
["1577836800000000001", "foo bar"],
|
|
|
|
["1477836900005000002", "abc"],
|
|
|
|
["147.78369e9", "foobar"]
|
|
|
|
]}]}`, `_time:1577836800000000001 "label1":"value1" "label2":"value2" "_msg":"foo bar"
|
|
|
|
_time:1477836900005000002 "label1":"value1" "label2":"value2" "_msg":"abc"
|
|
|
|
_time:147783690000 "label1":"value1" "label2":"value2" "_msg":"foobar"`)
|
|
|
|
|
|
|
|
// Multiple streams
|
|
|
|
f(`{
|
|
|
|
"streams": [
|
|
|
|
{
|
|
|
|
"stream": {
|
|
|
|
"foo": "bar",
|
|
|
|
"a": "b"
|
|
|
|
},
|
|
|
|
"values": [
|
|
|
|
["1577836800000000001", "foo bar"],
|
|
|
|
["1577836900005000002", "abc"]
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"stream": {
|
|
|
|
"x": "y"
|
|
|
|
},
|
|
|
|
"values": [
|
|
|
|
["1877836900005000002", "yx"]
|
|
|
|
]
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}`, `_time:1577836800000000001 "foo":"bar" "a":"b" "_msg":"foo bar"
|
|
|
|
_time:1577836900005000002 "foo":"bar" "a":"b" "_msg":"abc"
|
|
|
|
_time:1877836900005000002 "x":"y" "_msg":"yx"`)
|
2023-07-20 10:10:55 +02:00
|
|
|
}
|