2023-06-20 07:55:12 +02:00
|
|
|
package logstorage
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"math"
|
|
|
|
"reflect"
|
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestValuesEncoder(t *testing.T) {
|
|
|
|
f := func(values []string, expectedValueType valueType, expectedMinValue, expectedMaxValue uint64) {
|
|
|
|
t.Helper()
|
|
|
|
ve := getValuesEncoder()
|
|
|
|
var dict valuesDict
|
|
|
|
vt, minValue, maxValue := ve.encode(values, &dict)
|
|
|
|
if vt != expectedValueType {
|
|
|
|
t.Fatalf("unexpected value type; got %d; want %d", vt, expectedValueType)
|
|
|
|
}
|
|
|
|
if minValue != expectedMinValue {
|
|
|
|
t.Fatalf("unexpected minValue; got %d; want %d", minValue, expectedMinValue)
|
|
|
|
}
|
|
|
|
if maxValue != expectedMaxValue {
|
|
|
|
t.Fatalf("unexpected maxValue; got %d; want %d", maxValue, expectedMaxValue)
|
|
|
|
}
|
|
|
|
encodedValues := append([]string{}, ve.values...)
|
|
|
|
putValuesEncoder(ve)
|
|
|
|
|
|
|
|
vd := getValuesDecoder()
|
|
|
|
if err := vd.decodeInplace(encodedValues, vt, &dict); err != nil {
|
|
|
|
t.Fatalf("unexpected error in decodeInplace(): %s", err)
|
|
|
|
}
|
|
|
|
if len(values) == 0 {
|
|
|
|
values = []string{}
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(values, encodedValues) {
|
|
|
|
t.Fatalf("unexpected values decoded\ngot\n%q\nwant\n%q", encodedValues, values)
|
|
|
|
}
|
|
|
|
putValuesDecoder(vd)
|
|
|
|
}
|
|
|
|
|
|
|
|
// An empty values list
|
|
|
|
f(nil, valueTypeString, 0, 0)
|
|
|
|
|
|
|
|
// string values
|
|
|
|
values := make([]string, maxDictLen+1)
|
|
|
|
for i := range values {
|
|
|
|
values[i] = fmt.Sprintf("value_%d", i)
|
|
|
|
}
|
|
|
|
f(values, valueTypeString, 0, 0)
|
|
|
|
|
|
|
|
// dict values
|
|
|
|
f([]string{"foobar"}, valueTypeDict, 0, 0)
|
|
|
|
f([]string{"foo", "bar"}, valueTypeDict, 0, 0)
|
|
|
|
f([]string{"1", "2foo"}, valueTypeDict, 0, 0)
|
|
|
|
|
|
|
|
// uint8 values
|
|
|
|
for i := range values {
|
2023-07-13 20:26:22 +02:00
|
|
|
values[i] = fmt.Sprintf("%d", uint64(i+1))
|
2023-06-20 07:55:12 +02:00
|
|
|
}
|
|
|
|
f(values, valueTypeUint8, 1, uint64(len(values)))
|
|
|
|
|
|
|
|
// uint16 values
|
|
|
|
for i := range values {
|
2023-07-13 20:26:22 +02:00
|
|
|
values[i] = fmt.Sprintf("%d", uint64(i+1)<<8)
|
2023-06-20 07:55:12 +02:00
|
|
|
}
|
2023-07-13 20:26:22 +02:00
|
|
|
f(values, valueTypeUint16, 1<<8, uint64(len(values))<<8)
|
2023-06-20 07:55:12 +02:00
|
|
|
|
|
|
|
// uint32 values
|
|
|
|
for i := range values {
|
2023-07-13 20:26:22 +02:00
|
|
|
values[i] = fmt.Sprintf("%d", uint64(i+1)<<16)
|
2023-06-20 07:55:12 +02:00
|
|
|
}
|
2023-07-13 20:26:22 +02:00
|
|
|
f(values, valueTypeUint32, 1<<16, uint64(len(values))<<16)
|
2023-06-20 07:55:12 +02:00
|
|
|
|
|
|
|
// uint64 values
|
|
|
|
for i := range values {
|
2023-07-13 20:26:22 +02:00
|
|
|
values[i] = fmt.Sprintf("%d", uint64(i+1)<<32)
|
2023-06-20 07:55:12 +02:00
|
|
|
}
|
2023-07-13 20:26:22 +02:00
|
|
|
f(values, valueTypeUint64, 1<<32, uint64(len(values))<<32)
|
2023-06-20 07:55:12 +02:00
|
|
|
|
|
|
|
// ipv4 values
|
|
|
|
for i := range values {
|
|
|
|
values[i] = fmt.Sprintf("1.2.3.%d", i)
|
|
|
|
}
|
|
|
|
f(values, valueTypeIPv4, 16909056, 16909064)
|
|
|
|
|
|
|
|
// iso8601 timestamps
|
|
|
|
for i := range values {
|
|
|
|
values[i] = fmt.Sprintf("2011-04-19T03:44:01.%03dZ", i)
|
|
|
|
}
|
|
|
|
f(values, valueTypeTimestampISO8601, 1303184641000000000, 1303184641008000000)
|
|
|
|
|
|
|
|
// float64 values
|
|
|
|
for i := range values {
|
|
|
|
values[i] = fmt.Sprintf("%g", math.Sqrt(float64(i+1)))
|
|
|
|
}
|
|
|
|
f(values, valueTypeFloat64, 4607182418800017408, 4613937818241073152)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTryParseIPv4(t *testing.T) {
|
|
|
|
f := func(s string, nExpected uint32, okExpected bool) {
|
|
|
|
t.Helper()
|
|
|
|
n, ok := tryParseIPv4(s)
|
|
|
|
if n != nExpected {
|
|
|
|
t.Fatalf("unexpected n; got %d; want %d", n, nExpected)
|
|
|
|
}
|
|
|
|
if ok != okExpected {
|
|
|
|
t.Fatalf("unexpected ok; got %v; want %v", ok, okExpected)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
f("", 0, false)
|
|
|
|
f("foo", 0, false)
|
|
|
|
f("a.b.c.d", 0, false)
|
|
|
|
f("1.2.3.4", 0x01020304, true)
|
|
|
|
f("255.255.255.255", 0xffffffff, true)
|
|
|
|
f("0.0.0.0", 0, true)
|
|
|
|
f("127.0.0.1", 0x7f000001, true)
|
|
|
|
f("127.0.0.x", 0, false)
|
|
|
|
f("127.0.x.0", 0, false)
|
|
|
|
f("127.x.0.0", 0, false)
|
|
|
|
f("x.0.0.0", 0, false)
|
|
|
|
f("127.127.127.256", 0, false)
|
|
|
|
f("127.127.256.127", 0, false)
|
|
|
|
f("127.256.127.127", 0, false)
|
|
|
|
f("256.127.127.127", 0, false)
|
|
|
|
f("-1.127.127.127", 0, false)
|
|
|
|
f("127.-1.127.127", 0, false)
|
|
|
|
f("127.127.-1.127", 0, false)
|
|
|
|
f("127.127.127.-1", 0, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTryParseTimestampISO8601(t *testing.T) {
|
|
|
|
f := func(s string, timestampExpected uint64, okExpected bool) {
|
|
|
|
t.Helper()
|
|
|
|
timestamp, ok := tryParseTimestampISO8601(s)
|
|
|
|
if timestamp != timestampExpected {
|
|
|
|
t.Fatalf("unexpected timestamp; got %d; want %d", timestamp, timestampExpected)
|
|
|
|
}
|
|
|
|
if ok != okExpected {
|
|
|
|
t.Fatalf("unexpected ok; got %v; want %v", ok, okExpected)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
f("2023-01-15T23:45:51.123Z", 1673826351123000000, true)
|
|
|
|
|
|
|
|
// Invalid milliseconds
|
|
|
|
f("2023-01-15T22:15:51.12345Z", 0, false)
|
|
|
|
f("2023-01-15T22:15:51.12Z", 0, false)
|
|
|
|
f("2023-01-15T22:15:51Z", 0, false)
|
|
|
|
|
|
|
|
// Missing Z
|
|
|
|
f("2023-01-15T23:45:51.123", 0, false)
|
|
|
|
|
|
|
|
// Invalid timestamp
|
|
|
|
f("foo", 0, false)
|
|
|
|
f("2023-01-15T23:45:51.123Zxyabcd", 0, false)
|
|
|
|
f("2023-01-15T23:45:51.123Z01:00", 0, false)
|
|
|
|
|
|
|
|
// timestamp with timezone
|
|
|
|
f("2023-01-16T00:45:51.123+01:00", 0, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTryParseFloat64(t *testing.T) {
|
|
|
|
f := func(s string, valueExpected float64, okExpected bool) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
value, ok := tryParseFloat64(s)
|
|
|
|
if value != valueExpected {
|
|
|
|
t.Fatalf("unexpected value; got %v; want %v", value, valueExpected)
|
|
|
|
}
|
|
|
|
if ok != okExpected {
|
|
|
|
t.Fatalf("unexpected ok; got %v; want %v", ok, okExpected)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
f("0", 0, true)
|
|
|
|
f("1234567890", 1234567890, true)
|
|
|
|
f("-1.234567", -1.234567, true)
|
|
|
|
|
|
|
|
// Empty value
|
|
|
|
f("", 0, false)
|
|
|
|
|
|
|
|
// Plus in the value isn't allowed, since it cannot be convered back to the same string representation
|
|
|
|
f("+123", 0, false)
|
|
|
|
|
|
|
|
// Dot at the beginning and the end of value isn't allowed, since it cannot converted back to the same string representation
|
|
|
|
f(".123", 0, false)
|
|
|
|
f("123.", 0, false)
|
|
|
|
|
|
|
|
// Multiple dots aren't allowed
|
|
|
|
f("123.434.55", 0, false)
|
|
|
|
|
|
|
|
// Invalid dots
|
|
|
|
f("-.123", 0, false)
|
|
|
|
f(".", 0, false)
|
|
|
|
|
|
|
|
// Scientific notation isn't allowed, since it cannot be converted back to the same string representation
|
|
|
|
f("12e5", 0, false)
|
|
|
|
|
|
|
|
// Minus in the middle of string isn't allowed
|
|
|
|
f("12-5", 0, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTryParseUint64(t *testing.T) {
|
|
|
|
f := func(s string, valueExpected uint64, okExpected bool) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
value, ok := tryParseUint64(s)
|
|
|
|
if value != valueExpected {
|
|
|
|
t.Fatalf("unexpected value; got %d; want %d", value, valueExpected)
|
|
|
|
}
|
|
|
|
if ok != okExpected {
|
|
|
|
t.Fatalf("unexpected ok; got %v; want %v", ok, okExpected)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
f("0", 0, true)
|
|
|
|
f("123456789012345678", 123456789012345678, true)
|
|
|
|
|
|
|
|
// empty value
|
|
|
|
f("", 0, false)
|
|
|
|
|
|
|
|
// too big value
|
|
|
|
f("1234567890123456789", 0, false)
|
|
|
|
|
|
|
|
// invalid value
|
|
|
|
f("foo", 0, false)
|
|
|
|
}
|