tests: introduce helpers.Pos/helpers.Mark

This helps locating the position of a test.
This commit is contained in:
Vincent Bernat
2024-07-01 07:40:08 +02:00
parent 521b92486a
commit de65ee6072
15 changed files with 267 additions and 171 deletions

View File

@@ -11,27 +11,33 @@ import (
func TestTransformQueryOnCluster(t *testing.T) {
cases := []struct {
Pos helpers.Pos
Input string
Expected string
}{
{"SYSTEM RELOAD DICTIONARIES", "SYSTEM RELOAD DICTIONARIES ON CLUSTER akvorado"},
{"system reload dictionaries", "system reload dictionaries ON CLUSTER akvorado"},
{" system reload dictionaries ", "system reload dictionaries ON CLUSTER akvorado"},
{"DROP DATABASE IF EXISTS 02028_db", "DROP DATABASE IF EXISTS 02028_db ON CLUSTER akvorado"},
{helpers.Mark(), "SYSTEM RELOAD DICTIONARIES", "SYSTEM RELOAD DICTIONARIES ON CLUSTER akvorado"},
{helpers.Mark(), "system reload dictionaries", "system reload dictionaries ON CLUSTER akvorado"},
{helpers.Mark(), " system reload dictionaries ", "system reload dictionaries ON CLUSTER akvorado"},
{helpers.Mark(), "DROP DATABASE IF EXISTS 02028_db", "DROP DATABASE IF EXISTS 02028_db ON CLUSTER akvorado"},
{
helpers.Mark(),
"CREATE TABLE test_01148_atomic.rmt2 (n int, PRIMARY KEY n) ENGINE=ReplicatedMergeTree",
"CREATE TABLE test_01148_atomic.rmt2 ON CLUSTER akvorado (n int, PRIMARY KEY n) ENGINE=ReplicatedMergeTree",
},
{
helpers.Mark(),
"DROP TABLE IF EXISTS test_repl NO DELAY",
"DROP TABLE IF EXISTS test_repl ON CLUSTER akvorado NO DELAY",
},
{
helpers.Mark(),
"ALTER TABLE 02577_keepermap_delete_update UPDATE value2 = value2 * 10 + 2 WHERE value2 < 100",
"ALTER TABLE 02577_keepermap_delete_update ON CLUSTER akvorado UPDATE value2 = value2 * 10 + 2 WHERE value2 < 100",
},
{"ATTACH DICTIONARY db_01018.dict1", "ATTACH DICTIONARY db_01018.dict1 ON CLUSTER akvorado"},
{
helpers.Mark(), "ATTACH DICTIONARY db_01018.dict1", "ATTACH DICTIONARY db_01018.dict1 ON CLUSTER akvorado"},
{
helpers.Mark(),
`CREATE DICTIONARY default.asns
(
asn UInt32 INJECTIVE,
@@ -45,6 +51,7 @@ SETTINGS(format_csv_allow_single_quotes = 0)`,
`CREATE DICTIONARY default.asns ON CLUSTER akvorado ( asn UInt32 INJECTIVE, name String ) PRIMARY KEY asn SOURCE(HTTP(URL 'http://akvorado-orchestrator:8080/api/v0/orchestrator/clickhouse/asns.csv' FORMAT 'CSVWithNames')) LIFETIME(MIN 0 MAX 3600) LAYOUT(HASHED()) SETTINGS(format_csv_allow_single_quotes = 0)`,
},
{
helpers.Mark(),
`
CREATE TABLE queue (
timestamp UInt64,
@@ -55,6 +62,7 @@ CREATE TABLE queue (
`CREATE TABLE queue ON CLUSTER akvorado ( timestamp UInt64, level String, message String ) ENGINE = Kafka('localhost:9092', 'topic', 'group1', 'JSONEachRow')`,
},
{
helpers.Mark(),
`
CREATE MATERIALIZED VIEW consumer TO daily
AS SELECT toDate(toDateTime(timestamp)) AS day, level, count() as total
@@ -63,12 +71,12 @@ FROM queue GROUP BY day, level
`CREATE MATERIALIZED VIEW consumer ON CLUSTER akvorado TO daily AS SELECT toDate(toDateTime(timestamp)) AS day, level, count() as total FROM queue GROUP BY day, level`,
},
// Not modified
{"SELECT 1", "SELECT 1"},
{helpers.Mark(), "SELECT 1", "SELECT 1"},
}
for _, tc := range cases {
got := TransformQueryOnCluster(tc.Input, "akvorado")
if diff := helpers.Diff(got, tc.Expected); diff != "" {
t.Errorf("TransformQueryOnCluster(%q) (-got +want):\n%s", tc.Input, diff)
t.Errorf("%sTransformQueryOnCluster() (-got +want):\n%s", tc.Pos, diff)
}
}
}

View File

@@ -15,23 +15,24 @@ import (
func TestMapStructureMatchName(t *testing.T) {
cases := []struct {
pos Pos
mapKey string
fieldName string
expected bool
}{
{"one", "one", true},
{"one", "One", true},
{"one-two", "OneTwo", true},
{"onetwo", "OneTwo", true},
{"One-Two", "OneTwo", true},
{"two", "one", false},
{Mark(), "one", "one", true},
{Mark(), "one", "One", true},
{Mark(), "one-two", "OneTwo", true},
{Mark(), "onetwo", "OneTwo", true},
{Mark(), "One-Two", "OneTwo", true},
{Mark(), "two", "one", false},
}
for _, tc := range cases {
got := MapStructureMatchName(tc.mapKey, tc.fieldName)
if got && !tc.expected {
t.Errorf("%q == %q but expected !=", tc.mapKey, tc.fieldName)
t.Errorf("%s%q == %q but expected !=", tc.pos, tc.mapKey, tc.fieldName)
} else if !got && tc.expected {
t.Errorf("%q != %q but expected ==", tc.mapKey, tc.fieldName)
t.Errorf("%s%q != %q but expected ==", tc.pos, tc.mapKey, tc.fieldName)
}
}
}

View File

@@ -168,12 +168,12 @@ func TestSubnetMapUnmarshalHookWithMapValue(t *testing.T) {
Blop string
}
cases := []struct {
Description string
Input gin.H
Expected gin.H
Pos helpers.Pos
Input gin.H
Expected gin.H
}{
{
Description: "single value",
Pos: helpers.Mark(),
Input: gin.H{
"blip": "some",
"blop": "thing",
@@ -185,7 +185,7 @@ func TestSubnetMapUnmarshalHookWithMapValue(t *testing.T) {
},
},
}, {
Description: "proper map",
Pos: helpers.Mark(),
Input: gin.H{
"::/0": gin.H{
"blip": "some",
@@ -209,7 +209,7 @@ func TestSubnetMapUnmarshalHookWithMapValue(t *testing.T) {
},
}
for _, tc := range cases {
t.Run(tc.Description, func(t *testing.T) {
t.Run("sub", func(t *testing.T) {
var tree helpers.SubnetMap[SomeStruct]
decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
Result: &tree,
@@ -218,14 +218,14 @@ func TestSubnetMapUnmarshalHookWithMapValue(t *testing.T) {
DecodeHook: helpers.SubnetMapUnmarshallerHook[SomeStruct](),
})
if err != nil {
t.Fatalf("NewDecoder() error:\n%+v", err)
t.Fatalf("%sNewDecoder() error:\n%+v", tc.Pos, err)
}
err = decoder.Decode(tc.Input)
if err != nil {
t.Fatalf("Decode() error:\n%+v", err)
t.Fatalf("%sDecode() error:\n%+v", tc.Pos, err)
}
if diff := helpers.Diff(tree.ToMap(), tc.Expected); diff != "" {
t.Fatalf("Decode() (-got, +want):\n%s", diff)
t.Fatalf("%sDecode() (-got, +want):\n%s", tc.Pos, diff)
}
})
}

View File

@@ -10,8 +10,11 @@ package helpers
import (
"context"
"errors"
"fmt"
"net"
"os"
"path/filepath"
"runtime"
"testing"
"time"
)
@@ -98,3 +101,23 @@ type starter interface {
type stopper interface {
Stop() error
}
// Pos is a file:line recording a test data position.
type Pos struct {
file string
line int
}
// Mark reports the file:line position of the source file in which it appears.
func Mark() Pos {
_, file, line, _ := runtime.Caller(1)
return Pos{filepath.Base(file), line}
}
// String returns a textual representation of a Pos.
func (p Pos) String() string {
if p.file != "" {
return fmt.Sprintf("%s:%d", p.file, p.line)
}
return ""
}

View File

@@ -19,6 +19,7 @@ import (
// may mutate the configuration.
type ConfigurationDecodeCases []struct {
Description string
Pos Pos
Initial func() interface{} // initial value for configuration
Configuration func() interface{} // configuration to decode
Expected interface{}
@@ -45,10 +46,10 @@ func TestConfigurationDecode(t *testing.T, cases ConfigurationDecodeCases, optio
// Encode and decode with YAML
out, err := yaml.Marshal(tc.Configuration())
if err != nil {
t.Fatalf("yaml.Marshal() error:\n%+v", err)
t.Fatalf("%syaml.Marshal() error:\n%+v", tc.Pos, err)
}
if err := yaml.Unmarshal(out, &configuration); err != nil {
t.Fatalf("yaml.Unmarshal() error:\n%+v", err)
t.Fatalf("%syaml.Unmarshal() error:\n%+v", tc.Pos, err)
}
} else {
// Just use as is
@@ -58,11 +59,11 @@ func TestConfigurationDecode(t *testing.T, cases ConfigurationDecodeCases, optio
decoder, err := mapstructure.NewDecoder(GetMapStructureDecoderConfig(&got))
if err != nil {
t.Fatalf("NewDecoder() error:\n%+v", err)
t.Fatalf("%sNewDecoder() error:\n%+v", tc.Pos, err)
}
err = decoder.Decode(configuration)
if err != nil && !tc.Error {
t.Fatalf("Decode() error:\n%+v", err)
t.Fatalf("%sDecode() error:\n%+v", tc.Pos, err)
} else if tc.Error && err != nil {
return
}
@@ -70,21 +71,21 @@ func TestConfigurationDecode(t *testing.T, cases ConfigurationDecodeCases, optio
if !tc.SkipValidation {
err = Validate.Struct(got)
if err != nil && !tc.Error {
t.Fatalf("Validate() error:\n%+v", err)
t.Fatalf("%sValidate() error:\n%+v", tc.Pos, err)
} else if tc.Error && err != nil {
return
}
if tc.Error {
t.Errorf("Decode() and Validate() did not error")
t.Errorf("%sDecode() and Validate() did not error", tc.Pos)
}
} else {
if tc.Error {
t.Errorf("Decode() did not error")
t.Errorf("%sDecode() did not error", tc.Pos)
}
}
if diff := Diff(got, tc.Expected, options...); diff != "" && err == nil {
t.Fatalf("Decode() (-got, +want):\n%s", diff)
t.Fatalf("%sDecode() (-got, +want):\n%s", tc.Pos, diff)
}
})
}

View File

@@ -19,6 +19,7 @@ import (
// HTTPEndpointCases describes case for TestHTTPEndpoints
type HTTPEndpointCases []struct {
Pos Pos
Description string
Method string
URL string
@@ -42,7 +43,7 @@ func TestHTTPEndpoints(t *testing.T, serverAddr net.Addr, cases HTTPEndpointCase
t.Run(desc, func(t *testing.T) {
t.Helper()
if tc.FirstLines != nil && tc.JSONOutput != nil {
t.Fatalf("Cannot have both FirstLines and JSONOutput")
t.Fatalf("%sCannot have both FirstLines and JSONOutput", tc.Pos)
}
var resp *http.Response
var err error
@@ -62,13 +63,13 @@ func TestHTTPEndpoints(t *testing.T, serverAddr net.Addr, cases HTTPEndpointCase
}
resp, err = http.DefaultClient.Do(req)
if err != nil {
t.Fatalf("%s %s:\n%+v", tc.Method, tc.URL, err)
t.Fatalf("%s%s %s:\n%+v", tc.Pos, tc.Method, tc.URL, err)
}
} else {
payload := new(bytes.Buffer)
err = json.NewEncoder(payload).Encode(tc.JSONInput)
if err != nil {
t.Fatalf("Encode() error:\n%+v", err)
t.Fatalf("%sEncode() error:\n%+v", tc.Pos, err)
}
req, _ := http.NewRequest(tc.Method,
fmt.Sprintf("http://%s%s", serverAddr, tc.URL),
@@ -79,7 +80,7 @@ func TestHTTPEndpoints(t *testing.T, serverAddr net.Addr, cases HTTPEndpointCase
req.Header.Add("Content-Type", "application/json")
resp, err = http.DefaultClient.Do(req)
if err != nil {
t.Fatalf("%s %s:\n%+v", tc.Method, tc.URL, err)
t.Fatalf("%s%s %s:\n%+v", tc.Pos, tc.Method, tc.URL, err)
}
}
@@ -88,7 +89,8 @@ func TestHTTPEndpoints(t *testing.T, serverAddr net.Addr, cases HTTPEndpointCase
tc.StatusCode = 200
}
if resp.StatusCode != tc.StatusCode {
t.Errorf("%s %s: got status code %d, not %d", tc.URL,
t.Errorf("%s%s %s: got status code %d, not %d",
tc.Pos, tc.URL,
tc.Method, resp.StatusCode, tc.StatusCode)
}
if tc.JSONOutput != nil {
@@ -96,7 +98,8 @@ func TestHTTPEndpoints(t *testing.T, serverAddr net.Addr, cases HTTPEndpointCase
}
gotContentType := resp.Header.Get("Content-Type")
if gotContentType != tc.ContentType {
t.Errorf("%s %s Content-Type (-got, +want):\n-%s\n+%s",
t.Errorf("%s%s %s Content-Type (-got, +want):\n-%s\n+%s",
tc.Pos,
tc.Method, tc.URL, gotContentType, tc.ContentType)
}
if tc.JSONOutput == nil {
@@ -106,16 +109,16 @@ func TestHTTPEndpoints(t *testing.T, serverAddr net.Addr, cases HTTPEndpointCase
got = append(got, reader.Text())
}
if diff := Diff(got, tc.FirstLines); diff != "" {
t.Errorf("%s %s (-got, +want):\n%s", tc.Method, tc.URL, diff)
t.Errorf("%s%s %s (-got, +want):\n%s", tc.Pos, tc.Method, tc.URL, diff)
}
} else {
decoder := json.NewDecoder(resp.Body)
var got gin.H
if err := decoder.Decode(&got); err != nil {
t.Fatalf("%s %s:\n%+v", tc.Method, tc.URL, err)
t.Fatalf("%s%s %s:\n%+v", tc.Pos, tc.Method, tc.URL, err)
}
if diff := Diff(got, tc.JSONOutput); diff != "" {
t.Fatalf("%s %s (-got, +want):\n%s", tc.Method, tc.URL, diff)
t.Fatalf("%s%s %s (-got, +want):\n%s", tc.Pos, tc.Method, tc.URL, diff)
}
}
})

View File

@@ -15,28 +15,29 @@ func TestListenValidator(t *testing.T) {
Listen string `validate:"listen"`
}{}
cases := []struct {
Pos helpers.Pos
Listen string
Err bool
}{
{"127.0.0.1:161", false},
{"localhost:161", false},
{"0.0.0.0:161", false},
{"0.0.0.0:0", false},
{":161", false},
{":0", false},
{"127.0.0.1:0", false},
{"localhost", true},
{"127.0.0.1", true},
{"127.0.0.1:what", true},
{"127.0.0.1:100000", true},
{helpers.Mark(), "127.0.0.1:161", false},
{helpers.Mark(), "localhost:161", false},
{helpers.Mark(), "0.0.0.0:161", false},
{helpers.Mark(), "0.0.0.0:0", false},
{helpers.Mark(), ":161", false},
{helpers.Mark(), ":0", false},
{helpers.Mark(), "127.0.0.1:0", false},
{helpers.Mark(), "localhost", true},
{helpers.Mark(), "127.0.0.1", true},
{helpers.Mark(), "127.0.0.1:what", true},
{helpers.Mark(), "127.0.0.1:100000", true},
}
for _, tc := range cases {
s.Listen = tc.Listen
err := helpers.Validate.Struct(s)
if err == nil && tc.Err {
t.Errorf("Validate.Struct(%q) expected an error", tc.Listen)
t.Errorf("%sValidate.Struct(%q) expected an error", tc.Pos, tc.Listen)
} else if err != nil && !tc.Err {
t.Errorf("Validate.Struct(%q) error:\n%+v", tc.Listen, err)
t.Errorf("%sValidate.Struct(%q) error:\n%+v", tc.Pos, tc.Listen, err)
}
}
}
@@ -47,21 +48,22 @@ func TestNoIntersectWithValidator(t *testing.T) {
Set2 []string `validate:"ninterfield=Set1"`
}{}
cases := []struct {
Pos helpers.Pos
Set1 []string
Set2 []string
Err bool
}{
{nil, nil, false},
{nil, []string{"aaa"}, false},
{[]string{}, []string{"bbb"}, false},
{[]string{}, []string{"bbb"}, false},
{[]string{"bbb"}, nil, false},
{[]string{"aaa"}, []string{"bbb"}, false},
{[]string{"aaa", "ccc"}, []string{"bbb"}, false},
{[]string{"aaa"}, []string{"aaa"}, true},
{[]string{"aaa", "ccc"}, []string{"bbb", "ddd"}, false},
{[]string{"aaa", "ccc"}, []string{"bbb", "ccc"}, true},
{[]string{"aaa", "ccc"}, []string{"ccc", "bbb"}, true},
{helpers.Mark(), nil, nil, false},
{helpers.Mark(), nil, []string{"aaa"}, false},
{helpers.Mark(), []string{}, []string{"bbb"}, false},
{helpers.Mark(), []string{}, []string{"bbb"}, false},
{helpers.Mark(), []string{"bbb"}, nil, false},
{helpers.Mark(), []string{"aaa"}, []string{"bbb"}, false},
{helpers.Mark(), []string{"aaa", "ccc"}, []string{"bbb"}, false},
{helpers.Mark(), []string{"aaa"}, []string{"aaa"}, true},
{helpers.Mark(), []string{"aaa", "ccc"}, []string{"bbb", "ddd"}, false},
{helpers.Mark(), []string{"aaa", "ccc"}, []string{"bbb", "ccc"}, true},
{helpers.Mark(), []string{"aaa", "ccc"}, []string{"ccc", "bbb"}, true},
}
for _, tc := range cases {
s.Set1 = tc.Set1

View File

@@ -61,42 +61,54 @@ func TestGraphLineInputReverseDirection(t *testing.T) {
func TestGraphPreviousPeriod(t *testing.T) {
const longForm = "Jan 2, 2006 at 15:04"
cases := []struct {
Pos helpers.Pos
Start string
End string
ExpectedStart string
ExpectedEnd string
}{
{
helpers.Mark(),
"Jan 2, 2020 at 15:04", "Jan 2, 2020 at 16:04",
"Jan 2, 2020 at 14:04", "Jan 2, 2020 at 15:04",
}, {
helpers.Mark(),
"Jan 2, 2020 at 15:04", "Jan 2, 2020 at 16:34",
"Jan 2, 2020 at 14:04", "Jan 2, 2020 at 15:34",
}, {
helpers.Mark(),
"Jan 2, 2020 at 15:04", "Jan 2, 2020 at 17:34",
"Jan 1, 2020 at 15:04", "Jan 1, 2020 at 17:34",
}, {
helpers.Mark(),
"Jan 2, 2020 at 15:04", "Jan 3, 2020 at 17:34",
"Jan 1, 2020 at 15:04", "Jan 2, 2020 at 17:34",
}, {
helpers.Mark(),
"Jan 10, 2020 at 15:04", "Jan 13, 2020 at 17:34",
"Jan 3, 2020 at 15:04", "Jan 6, 2020 at 17:34",
}, {
helpers.Mark(),
"Jan 10, 2020 at 15:04", "Jan 15, 2020 at 17:34",
"Jan 3, 2020 at 15:04", "Jan 8, 2020 at 17:34",
}, {
helpers.Mark(),
"Jan 10, 2020 at 15:04", "Jan 20, 2020 at 17:34",
"Jan 3, 2020 at 15:04", "Jan 13, 2020 at 17:34",
}, {
helpers.Mark(),
"Feb 10, 2020 at 15:04", "Feb 25, 2020 at 17:34",
"Jan 13, 2020 at 15:04", "Jan 28, 2020 at 17:34",
}, {
helpers.Mark(),
"Feb 10, 2020 at 15:04", "Mar 25, 2020 at 17:34",
"Jan 13, 2020 at 15:04", "Feb 26, 2020 at 17:34",
}, {
helpers.Mark(),
"Feb 10, 2020 at 15:04", "Jul 25, 2020 at 17:34",
"Feb 10, 2019 at 15:04", "Jul 25, 2019 at 17:34",
}, {
helpers.Mark(),
"Feb 10, 2019 at 15:04", "Jul 25, 2020 at 17:34",
"Feb 10, 2018 at 15:04", "Jul 25, 2019 at 17:34",
},
@@ -105,19 +117,19 @@ func TestGraphPreviousPeriod(t *testing.T) {
t.Run(fmt.Sprintf("%s to %s", tc.Start, tc.End), func(t *testing.T) {
start, err := time.Parse(longForm, tc.Start)
if err != nil {
t.Fatalf("time.Parse(%q) error:\n%+v", tc.Start, err)
t.Fatalf("%stime.Parse(%q) error:\n%+v", tc.Pos, tc.Start, err)
}
end, err := time.Parse(longForm, tc.End)
if err != nil {
t.Fatalf("time.Parse(%q) error:\n%+v", tc.End, err)
t.Fatalf("%stime.Parse(%q) error:\n%+v", tc.Pos, tc.End, err)
}
expectedStart, err := time.Parse(longForm, tc.ExpectedStart)
if err != nil {
t.Fatalf("time.Parse(%q) error:\n%+v", tc.ExpectedStart, err)
t.Fatalf("%stime.Parse(%q) error:\n%+v", tc.Pos, tc.ExpectedStart, err)
}
expectedEnd, err := time.Parse(longForm, tc.ExpectedEnd)
if err != nil {
t.Fatalf("time.Parse(%q) error:\n%+v", tc.ExpectedEnd, err)
t.Fatalf("%stime.Parse(%q) error:\n%+v", tc.Pos, tc.ExpectedEnd, err)
}
input := graphLineHandlerInput{
graphCommonHandlerInput: graphCommonHandlerInput{
@@ -140,7 +152,7 @@ func TestGraphPreviousPeriod(t *testing.T) {
},
}
if diff := helpers.Diff(got, expected); diff != "" {
t.Fatalf("previousPeriod() (-got, +want):\n%s", diff)
t.Fatalf("%spreviousPeriod() (-got, +want):\n%s", tc.Pos, diff)
}
})
}
@@ -149,11 +161,13 @@ func TestGraphPreviousPeriod(t *testing.T) {
func TestGraphQuerySQL(t *testing.T) {
cases := []struct {
Description string
Pos helpers.Pos
Input graphLineHandlerInput
Expected string
}{
{
Description: "no dimensions, no filters, bps",
Pos: helpers.Mark(),
Input: graphLineHandlerInput{
graphCommonHandlerInput: graphCommonHandlerInput{
Start: time.Date(2022, 4, 10, 15, 45, 10, 0, time.UTC),
@@ -184,6 +198,7 @@ ORDER BY time WITH FILL
{{ end }}`,
}, {
Description: "no dimensions, no filters, l2 bps",
Pos: helpers.Mark(),
Input: graphLineHandlerInput{
graphCommonHandlerInput: graphCommonHandlerInput{
Start: time.Date(2022, 4, 10, 15, 45, 10, 0, time.UTC),
@@ -215,6 +230,7 @@ ORDER BY time WITH FILL
`,
}, {
Description: "no dimensions, no filters, pps",
Pos: helpers.Mark(),
Input: graphLineHandlerInput{
graphCommonHandlerInput: graphCommonHandlerInput{
Start: time.Date(2022, 4, 10, 15, 45, 10, 0, time.UTC),
@@ -245,6 +261,7 @@ ORDER BY time WITH FILL
{{ end }}`,
}, {
Description: "truncated source address",
Pos: helpers.Mark(),
Input: graphLineHandlerInput{
graphCommonHandlerInput: graphCommonHandlerInput{
Start: time.Date(2022, 4, 10, 15, 45, 10, 0, time.UTC),
@@ -278,6 +295,7 @@ ORDER BY time WITH FILL
{{ end }}`,
}, {
Description: "no dimensions",
Pos: helpers.Mark(),
Input: graphLineHandlerInput{
graphCommonHandlerInput: graphCommonHandlerInput{
Start: time.Date(2022, 4, 10, 15, 45, 10, 0, time.UTC),
@@ -308,6 +326,7 @@ ORDER BY time WITH FILL
{{ end }}`,
}, {
Description: "no dimensions, escaped filter",
Pos: helpers.Mark(),
Input: graphLineHandlerInput{
graphCommonHandlerInput: graphCommonHandlerInput{
Start: time.Date(2022, 4, 10, 15, 45, 10, 0, time.UTC),
@@ -338,6 +357,7 @@ ORDER BY time WITH FILL
{{ end }}`,
}, {
Description: "no dimensions, reverse direction",
Pos: helpers.Mark(),
Input: graphLineHandlerInput{
graphCommonHandlerInput: graphCommonHandlerInput{
Start: time.Date(2022, 4, 10, 15, 45, 10, 0, time.UTC),
@@ -385,6 +405,7 @@ ORDER BY time WITH FILL
{{ end }}`,
}, {
Description: "no dimensions, reverse direction, inl2%",
Pos: helpers.Mark(),
Input: graphLineHandlerInput{
graphCommonHandlerInput: graphCommonHandlerInput{
Start: time.Date(2022, 4, 10, 15, 45, 10, 0, time.UTC),
@@ -432,6 +453,7 @@ ORDER BY time WITH FILL
{{ end }}`,
}, {
Description: "no filters",
Pos: helpers.Mark(),
Input: graphLineHandlerInput{
graphCommonHandlerInput: graphCommonHandlerInput{
Start: time.Date(2022, 4, 10, 15, 45, 10, 0, time.UTC),
@@ -467,6 +489,7 @@ ORDER BY time WITH FILL
{{ end }}`,
}, {
Description: "no filters, reverse",
Pos: helpers.Mark(),
Input: graphLineHandlerInput{
graphCommonHandlerInput: graphCommonHandlerInput{
Start: time.Date(2022, 4, 10, 15, 45, 10, 0, time.UTC),
@@ -519,6 +542,7 @@ ORDER BY time WITH FILL
{{ end }}`,
}, {
Description: "no filters, previous period",
Pos: helpers.Mark(),
Input: graphLineHandlerInput{
graphCommonHandlerInput: graphCommonHandlerInput{
Start: time.Date(2022, 4, 10, 15, 45, 10, 0, time.UTC),
@@ -574,17 +598,17 @@ ORDER BY time WITH FILL
for _, tc := range cases {
tc.Input.schema = schema.NewMock(t)
if err := query.Columns(tc.Input.Dimensions).Validate(tc.Input.schema); err != nil {
t.Fatalf("Validate() error:\n%+v", err)
t.Fatalf("%sValidate() error:\n%+v", tc.Pos, err)
}
if err := tc.Input.Filter.Validate(tc.Input.schema); err != nil {
t.Fatalf("Validate() error:\n%+v", err)
t.Fatalf("%sValidate() error:\n%+v", tc.Pos, err)
}
tc.Expected = strings.ReplaceAll(tc.Expected, "@@", "`")
t.Run(tc.Description, func(t *testing.T) {
got := tc.Input.toSQL()
if diff := helpers.Diff(strings.Split(strings.TrimSpace(got), "\n"),
strings.Split(strings.TrimSpace(tc.Expected), "\n")); diff != "" {
t.Errorf("toSQL (-got, +want):\n%s", diff)
t.Errorf("%stoSQL (-got, +want):\n%s", tc.Pos, diff)
}
})
}

View File

@@ -26,7 +26,7 @@ func TestUnmarshalQueryColumn(t *testing.T) {
for _, tc := range cases {
var qc query.Column
if err := qc.UnmarshalText([]byte(tc.Input)); err != nil {
t.Fatalf("UnmarshalText() error:\n%+v", err)
t.Fatalf("UnmarshalText(%q) error:\n%+v", tc.Input, err)
}
err := qc.Validate(schema.NewMock(t))
if err != nil && !tc.Error {

View File

@@ -6,39 +6,41 @@ package console
import (
"testing"
"akvorado/common/helpers"
"akvorado/common/schema"
"akvorado/console/query"
)
func TestRequireMainTable(t *testing.T) {
cases := []struct {
Pos helpers.Pos
Columns []query.Column
Filter query.Filter
Expected bool
}{
{[]query.Column{}, query.NewFilter(""), false},
{[]query.Column{query.NewColumn("SrcAS")}, query.NewFilter(""), false},
{[]query.Column{query.NewColumn("ExporterAddress")}, query.NewFilter(""), false},
{[]query.Column{query.NewColumn("SrcPort")}, query.NewFilter(""), true},
{[]query.Column{query.NewColumn("SrcAddr")}, query.NewFilter(""), true},
{[]query.Column{query.NewColumn("DstPort")}, query.NewFilter(""), true},
{[]query.Column{query.NewColumn("DstAddr")}, query.NewFilter(""), true},
{[]query.Column{query.NewColumn("SrcAS"), query.NewColumn("DstAddr")}, query.NewFilter(""), true},
{[]query.Column{query.NewColumn("DstAddr"), query.NewColumn("SrcAS")}, query.NewFilter(""), true},
{[]query.Column{query.NewColumn("DstNetPrefix")}, query.NewFilter(""), true},
{[]query.Column{}, query.NewFilter("SrcAddr = 203.0.113.15"), true},
{helpers.Mark(), []query.Column{}, query.NewFilter(""), false},
{helpers.Mark(), []query.Column{query.NewColumn("SrcAS")}, query.NewFilter(""), false},
{helpers.Mark(), []query.Column{query.NewColumn("ExporterAddress")}, query.NewFilter(""), false},
{helpers.Mark(), []query.Column{query.NewColumn("SrcPort")}, query.NewFilter(""), true},
{helpers.Mark(), []query.Column{query.NewColumn("SrcAddr")}, query.NewFilter(""), true},
{helpers.Mark(), []query.Column{query.NewColumn("DstPort")}, query.NewFilter(""), true},
{helpers.Mark(), []query.Column{query.NewColumn("DstAddr")}, query.NewFilter(""), true},
{helpers.Mark(), []query.Column{query.NewColumn("SrcAS"), query.NewColumn("DstAddr")}, query.NewFilter(""), true},
{helpers.Mark(), []query.Column{query.NewColumn("DstAddr"), query.NewColumn("SrcAS")}, query.NewFilter(""), true},
{helpers.Mark(), []query.Column{query.NewColumn("DstNetPrefix")}, query.NewFilter(""), true},
{helpers.Mark(), []query.Column{}, query.NewFilter("SrcAddr = 203.0.113.15"), true},
}
sch := schema.NewMock(t)
for idx, tc := range cases {
if err := query.Columns(tc.Columns).Validate(sch); err != nil {
t.Fatalf("Validate() error:\n%+v", err)
t.Fatalf("%sValidate() error:\n%+v", tc.Pos, err)
}
if err := tc.Filter.Validate(sch); err != nil {
t.Fatalf("Validate() error:\n%+v", err)
t.Fatalf("%sValidate() error:\n%+v", tc.Pos, err)
}
got := requireMainTable(sch, tc.Columns, tc.Filter)
if got != tc.Expected {
t.Errorf("requireMainTable(%d) == %v but expected %v", idx, got, tc.Expected)
t.Errorf("%srequireMainTable(%d) == %v but expected %v", tc.Pos, idx, got, tc.Expected)
}
}
}

View File

@@ -19,11 +19,13 @@ import (
func TestSankeyQuerySQL(t *testing.T) {
cases := []struct {
Description string
Pos helpers.Pos
Input graphSankeyHandlerInput
Expected string
}{
{
Description: "two dimensions, no filters, l3 bps",
Pos: helpers.Mark(),
Input: graphSankeyHandlerInput{
graphCommonHandlerInput{
Start: time.Date(2022, 4, 10, 15, 45, 10, 0, time.UTC),
@@ -54,6 +56,7 @@ ORDER BY xps DESC
{{ end }}`,
}, {
Description: "two dimensions, no filters, l2 bps",
Pos: helpers.Mark(),
Input: graphSankeyHandlerInput{
graphCommonHandlerInput{
Start: time.Date(2022, 4, 10, 15, 45, 10, 0, time.UTC),
@@ -85,6 +88,7 @@ ORDER BY xps DESC
`,
}, {
Description: "two dimensions, no filters, pps",
Pos: helpers.Mark(),
Input: graphSankeyHandlerInput{
graphCommonHandlerInput{
Start: time.Date(2022, 4, 10, 15, 45, 10, 0, time.UTC),
@@ -115,6 +119,7 @@ ORDER BY xps DESC
{{ end }}`,
}, {
Description: "two dimensions, with filter",
Pos: helpers.Mark(),
Input: graphSankeyHandlerInput{
graphCommonHandlerInput{
Start: time.Date(2022, 4, 10, 15, 45, 10, 0, time.UTC),
@@ -148,17 +153,17 @@ ORDER BY xps DESC
for _, tc := range cases {
tc.Input.schema = schema.NewMock(t)
if err := query.Columns(tc.Input.Dimensions).Validate(tc.Input.schema); err != nil {
t.Fatalf("Validate() error:\n%+v", err)
t.Fatalf("%sValidate() error:\n%+v", tc.Pos, err)
}
if err := tc.Input.Filter.Validate(tc.Input.schema); err != nil {
t.Fatalf("Validate() error:\n%+v", err)
t.Fatalf("%sValidate() error:\n%+v", tc.Pos, err)
}
tc.Expected = strings.ReplaceAll(tc.Expected, "@@", "`")
t.Run(tc.Description, func(t *testing.T) {
got, _ := tc.Input.toSQL()
if diff := helpers.Diff(strings.Split(strings.TrimSpace(got), "\n"),
strings.Split(strings.TrimSpace(tc.Expected), "\n")); diff != "" {
t.Errorf("toSQL (-got, +want):\n%s", diff)
t.Errorf("%stoSQL (-got, +want):\n%s", tc.Pos, diff)
}
})
}

View File

@@ -62,27 +62,28 @@ func TestRandomIP(t *testing.T) {
func TestPeakHourDistance(t *testing.T) {
cases := []struct {
Pos helpers.Pos
Peak time.Duration
Now time.Duration
Expected float64
}{
{6 * time.Hour, 6 * time.Hour, 1},
{6 * time.Hour, 0, 0.5},
{6 * time.Hour, 18 * time.Hour, 0},
{12 * time.Hour, 13 * time.Hour, 11. / 12},
{12 * time.Hour, 11 * time.Hour, 11. / 12},
{12 * time.Hour, 14 * time.Hour, 10. / 12},
{12 * time.Hour, 15 * time.Hour, 9. / 12},
{12 * time.Hour, 16 * time.Hour, 8. / 12},
{12 * time.Hour, 17 * time.Hour, 7. / 12},
{12 * time.Hour, 18 * time.Hour, 6. / 12},
{12 * time.Hour, 19 * time.Hour, 5. / 12},
{helpers.Mark(), 6 * time.Hour, 6 * time.Hour, 1},
{helpers.Mark(), 6 * time.Hour, 0, 0.5},
{helpers.Mark(), 6 * time.Hour, 18 * time.Hour, 0},
{helpers.Mark(), 12 * time.Hour, 13 * time.Hour, 11. / 12},
{helpers.Mark(), 12 * time.Hour, 11 * time.Hour, 11. / 12},
{helpers.Mark(), 12 * time.Hour, 14 * time.Hour, 10. / 12},
{helpers.Mark(), 12 * time.Hour, 15 * time.Hour, 9. / 12},
{helpers.Mark(), 12 * time.Hour, 16 * time.Hour, 8. / 12},
{helpers.Mark(), 12 * time.Hour, 17 * time.Hour, 7. / 12},
{helpers.Mark(), 12 * time.Hour, 18 * time.Hour, 6. / 12},
{helpers.Mark(), 12 * time.Hour, 19 * time.Hour, 5. / 12},
}
for _, tc := range cases {
got := peakHourDistance(tc.Now, tc.Peak)
if math.Abs(got-tc.Expected) > tc.Expected*0.01 {
t.Errorf("peakHourDistance(%s, %s) == %f, expected %f",
tc.Peak, tc.Now, got, tc.Expected)
t.Errorf("%speakHourDistance(%s, %s) == %f, expected %f",
tc.Pos, tc.Peak, tc.Now, got, tc.Expected)
}
}
}
@@ -129,10 +130,12 @@ func TestChooseRandom(t *testing.T) {
func TestGenerateFlows(t *testing.T) {
cases := []struct {
Pos helpers.Pos
FlowConfiguration
Expected []generatedFlow
}{
{
Pos: helpers.Mark(),
FlowConfiguration: FlowConfiguration{
PerSecond: 1,
InIfIndex: []int{10},
@@ -187,6 +190,7 @@ func TestGenerateFlows(t *testing.T) {
},
},
}, {
Pos: helpers.Mark(),
FlowConfiguration: FlowConfiguration{
PerSecond: 1,
InIfIndex: []int{20},
@@ -223,6 +227,7 @@ func TestGenerateFlows(t *testing.T) {
},
},
}, {
Pos: helpers.Mark(),
FlowConfiguration: FlowConfiguration{
PerSecond: 1,
InIfIndex: []int{20},
@@ -280,11 +285,11 @@ func TestGenerateFlows(t *testing.T) {
},
}
now := time.Date(2022, 3, 18, 15, 0, 0, 0, time.UTC)
for i, tc := range cases {
t.Run(fmt.Sprintf("case %d", i+1), func(t *testing.T) {
for _, tc := range cases {
t.Run(fmt.Sprintf("case %s", tc.Pos), func(t *testing.T) {
got := generateFlows([]FlowConfiguration{tc.FlowConfiguration}, 0, now)
if diff := helpers.Diff(got, tc.Expected); diff != "" {
t.Fatalf("generatedFlows() (-got, +want):\n%s", diff)
t.Fatalf("%sgeneratedFlows() (-got, +want):\n%s", tc.Pos, diff)
}
})
}

View File

@@ -621,6 +621,7 @@ ClassifyProviderRegex(Interface.Description, "^Transit: ([^ ]+)", "$1")`,
func TestGetASNumber(t *testing.T) {
cases := []struct {
Pos helpers.Pos
Addr string
FlowAS uint32
BMPAS uint32
@@ -628,22 +629,21 @@ func TestGetASNumber(t *testing.T) {
Expected uint32
}{
// 1
{"1.0.0.1", 12322, 0, []ASNProvider{ASNProviderFlow}, 12322},
{"::ffff:1.0.0.1", 12322, 0, []ASNProvider{ASNProviderFlow}, 12322},
{"1.0.0.1", 65536, 0, []ASNProvider{ASNProviderFlow}, 65536},
{"1.0.0.1", 65536, 0, []ASNProvider{ASNProviderFlowExceptPrivate}, 0},
{"1.0.0.1", 4_200_000_121, 0, []ASNProvider{ASNProviderFlowExceptPrivate}, 0},
{"1.0.0.1", 65536, 0, []ASNProvider{ASNProviderFlowExceptPrivate, ASNProviderFlow}, 65536},
{"1.0.0.1", 12322, 0, []ASNProvider{ASNProviderFlowExceptPrivate}, 12322},
{helpers.Mark(), "1.0.0.1", 12322, 0, []ASNProvider{ASNProviderFlow}, 12322},
{helpers.Mark(), "::ffff:1.0.0.1", 12322, 0, []ASNProvider{ASNProviderFlow}, 12322},
{helpers.Mark(), "1.0.0.1", 65536, 0, []ASNProvider{ASNProviderFlow}, 65536},
{helpers.Mark(), "1.0.0.1", 65536, 0, []ASNProvider{ASNProviderFlowExceptPrivate}, 0},
{helpers.Mark(), "1.0.0.1", 4_200_000_121, 0, []ASNProvider{ASNProviderFlowExceptPrivate}, 0},
{helpers.Mark(), "1.0.0.1", 65536, 0, []ASNProvider{ASNProviderFlowExceptPrivate, ASNProviderFlow}, 65536},
{helpers.Mark(), "1.0.0.1", 12322, 0, []ASNProvider{ASNProviderFlowExceptPrivate}, 12322},
// 10
{"192.0.2.2", 12322, 174, []ASNProvider{ASNProviderRouting}, 174},
{"192.0.2.129", 12322, 1299, []ASNProvider{ASNProviderRouting}, 1299},
{"192.0.2.254", 12322, 0, []ASNProvider{ASNProviderRouting}, 0},
{"1.0.0.1", 12322, 65300, []ASNProvider{ASNProviderRouting}, 65300},
{helpers.Mark(), "192.0.2.2", 12322, 174, []ASNProvider{ASNProviderRouting}, 174},
{helpers.Mark(), "192.0.2.129", 12322, 1299, []ASNProvider{ASNProviderRouting}, 1299},
{helpers.Mark(), "192.0.2.254", 12322, 0, []ASNProvider{ASNProviderRouting}, 0},
{helpers.Mark(), "1.0.0.1", 12322, 65300, []ASNProvider{ASNProviderRouting}, 65300},
}
for i, tc := range cases {
i++
t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) {
for _, tc := range cases {
t.Run(fmt.Sprintf("case %s", tc.Pos), func(t *testing.T) {
r := reporter.NewMock(t)
// We don't need all components as we won't start the component.
@@ -658,11 +658,11 @@ func TestGetASNumber(t *testing.T) {
Schema: schema.NewMock(t),
})
if err != nil {
t.Fatalf("New() error:\n%+v", err)
t.Fatalf("%sNew() error:\n%+v", tc.Pos, err)
}
got := c.getASNumber(tc.FlowAS, tc.BMPAS)
if diff := helpers.Diff(got, tc.Expected); diff != "" {
t.Fatalf("getASNumber() (-got, +want):\n%s", diff)
t.Fatalf("%sgetASNumber() (-got, +want):\n%s", tc.Pos, diff)
}
})
}
@@ -670,37 +670,36 @@ func TestGetASNumber(t *testing.T) {
func TestGetNetMask(t *testing.T) {
cases := []struct {
// Addr string
Pos helpers.Pos
FlowNetMask uint8
BMPNetMask uint8
Providers []NetProvider
Expected uint8
}{
// Flow
{0, 0, []NetProvider{NetProviderFlow}, 0},
{32, 0, []NetProvider{NetProviderFlow}, 32},
{0, 16, []NetProvider{NetProviderFlow}, 0},
{helpers.Mark(), 0, 0, []NetProvider{NetProviderFlow}, 0},
{helpers.Mark(), 32, 0, []NetProvider{NetProviderFlow}, 32},
{helpers.Mark(), 0, 16, []NetProvider{NetProviderFlow}, 0},
// BMP
{0, 0, []NetProvider{NetProviderRouting}, 0},
{32, 12, []NetProvider{NetProviderRouting}, 12},
{0, 16, []NetProvider{NetProviderRouting}, 16},
{24, 0, []NetProvider{NetProviderRouting}, 0},
{helpers.Mark(), 0, 0, []NetProvider{NetProviderRouting}, 0},
{helpers.Mark(), 32, 12, []NetProvider{NetProviderRouting}, 12},
{helpers.Mark(), 0, 16, []NetProvider{NetProviderRouting}, 16},
{helpers.Mark(), 24, 0, []NetProvider{NetProviderRouting}, 0},
// Both, the first provider with a non-default route is taken
{0, 0, []NetProvider{NetProviderRouting, NetProviderFlow}, 0},
{12, 0, []NetProvider{NetProviderRouting, NetProviderFlow}, 12},
{0, 13, []NetProvider{NetProviderRouting, NetProviderFlow}, 13},
{12, 0, []NetProvider{NetProviderRouting, NetProviderFlow}, 12},
{12, 24, []NetProvider{NetProviderRouting, NetProviderFlow}, 24},
{helpers.Mark(), 0, 0, []NetProvider{NetProviderRouting, NetProviderFlow}, 0},
{helpers.Mark(), 12, 0, []NetProvider{NetProviderRouting, NetProviderFlow}, 12},
{helpers.Mark(), 0, 13, []NetProvider{NetProviderRouting, NetProviderFlow}, 13},
{helpers.Mark(), 12, 0, []NetProvider{NetProviderRouting, NetProviderFlow}, 12},
{helpers.Mark(), 12, 24, []NetProvider{NetProviderRouting, NetProviderFlow}, 24},
{0, 0, []NetProvider{NetProviderFlow, NetProviderRouting}, 0},
{12, 0, []NetProvider{NetProviderFlow, NetProviderRouting}, 12},
{0, 13, []NetProvider{NetProviderFlow, NetProviderRouting}, 13},
{12, 0, []NetProvider{NetProviderFlow, NetProviderRouting}, 12},
{12, 24, []NetProvider{NetProviderFlow, NetProviderRouting}, 12},
{helpers.Mark(), 0, 0, []NetProvider{NetProviderFlow, NetProviderRouting}, 0},
{helpers.Mark(), 12, 0, []NetProvider{NetProviderFlow, NetProviderRouting}, 12},
{helpers.Mark(), 0, 13, []NetProvider{NetProviderFlow, NetProviderRouting}, 13},
{helpers.Mark(), 12, 0, []NetProvider{NetProviderFlow, NetProviderRouting}, 12},
{helpers.Mark(), 12, 24, []NetProvider{NetProviderFlow, NetProviderRouting}, 12},
}
for i, tc := range cases {
i++
t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) {
for _, tc := range cases {
t.Run(fmt.Sprintf("case %s", tc.Pos), func(t *testing.T) {
r := reporter.NewMock(t)
// We don't need all components as we won't start the component.
@@ -729,35 +728,35 @@ func TestGetNextHop(t *testing.T) {
nh1 := netip.MustParseAddr("2001:db8::1")
nh2 := netip.MustParseAddr("2001:db8::2")
cases := []struct {
Pos helpers.Pos
FlowNextHop netip.Addr
RoutingNextHop netip.Addr
Providers []NetProvider
Expected netip.Addr
}{
// Flow
{netip.IPv6Unspecified(), netip.IPv6Unspecified(), []NetProvider{NetProviderFlow}, netip.IPv6Unspecified()},
{nh1, netip.IPv6Unspecified(), []NetProvider{NetProviderFlow}, nh1},
{netip.IPv6Unspecified(), nh1, []NetProvider{NetProviderFlow}, netip.IPv6Unspecified()},
{helpers.Mark(), netip.IPv6Unspecified(), netip.IPv6Unspecified(), []NetProvider{NetProviderFlow}, netip.IPv6Unspecified()},
{helpers.Mark(), nh1, netip.IPv6Unspecified(), []NetProvider{NetProviderFlow}, nh1},
{helpers.Mark(), netip.IPv6Unspecified(), nh1, []NetProvider{NetProviderFlow}, netip.IPv6Unspecified()},
// Routing
{netip.IPv6Unspecified(), netip.IPv6Unspecified(), []NetProvider{NetProviderRouting}, netip.IPv6Unspecified()},
{nh1, netip.IPv6Unspecified(), []NetProvider{NetProviderRouting}, netip.IPv6Unspecified()},
{netip.IPv6Unspecified(), nh1, []NetProvider{NetProviderRouting}, nh1},
{helpers.Mark(), netip.IPv6Unspecified(), netip.IPv6Unspecified(), []NetProvider{NetProviderRouting}, netip.IPv6Unspecified()},
{helpers.Mark(), nh1, netip.IPv6Unspecified(), []NetProvider{NetProviderRouting}, netip.IPv6Unspecified()},
{helpers.Mark(), netip.IPv6Unspecified(), nh1, []NetProvider{NetProviderRouting}, nh1},
// Both
{netip.IPv6Unspecified(), netip.IPv6Unspecified(), []NetProvider{NetProviderRouting, NetProviderFlow}, netip.IPv6Unspecified()},
{nh1, netip.IPv6Unspecified(), []NetProvider{NetProviderRouting, NetProviderFlow}, nh1},
{netip.IPv6Unspecified(), nh2, []NetProvider{NetProviderRouting, NetProviderFlow}, nh2},
{nh1, netip.IPv6Unspecified(), []NetProvider{NetProviderRouting, NetProviderFlow}, nh1},
{nh1, nh2, []NetProvider{NetProviderRouting, NetProviderFlow}, nh2},
{helpers.Mark(), netip.IPv6Unspecified(), netip.IPv6Unspecified(), []NetProvider{NetProviderRouting, NetProviderFlow}, netip.IPv6Unspecified()},
{helpers.Mark(), nh1, netip.IPv6Unspecified(), []NetProvider{NetProviderRouting, NetProviderFlow}, nh1},
{helpers.Mark(), netip.IPv6Unspecified(), nh2, []NetProvider{NetProviderRouting, NetProviderFlow}, nh2},
{helpers.Mark(), nh1, netip.IPv6Unspecified(), []NetProvider{NetProviderRouting, NetProviderFlow}, nh1},
{helpers.Mark(), nh1, nh2, []NetProvider{NetProviderRouting, NetProviderFlow}, nh2},
{netip.IPv6Unspecified(), netip.IPv6Unspecified(), []NetProvider{NetProviderFlow, NetProviderRouting}, netip.IPv6Unspecified()},
{nh1, netip.IPv6Unspecified(), []NetProvider{NetProviderFlow, NetProviderRouting}, nh1},
{netip.IPv6Unspecified(), nh2, []NetProvider{NetProviderFlow, NetProviderRouting}, nh2},
{nh1, netip.IPv6Unspecified(), []NetProvider{NetProviderFlow, NetProviderRouting}, nh1},
{nh1, nh2, []NetProvider{NetProviderFlow, NetProviderRouting}, nh1},
{helpers.Mark(), netip.IPv6Unspecified(), netip.IPv6Unspecified(), []NetProvider{NetProviderFlow, NetProviderRouting}, netip.IPv6Unspecified()},
{helpers.Mark(), nh1, netip.IPv6Unspecified(), []NetProvider{NetProviderFlow, NetProviderRouting}, nh1},
{helpers.Mark(), netip.IPv6Unspecified(), nh2, []NetProvider{NetProviderFlow, NetProviderRouting}, nh2},
{helpers.Mark(), nh1, netip.IPv6Unspecified(), []NetProvider{NetProviderFlow, NetProviderRouting}, nh1},
{helpers.Mark(), nh1, nh2, []NetProvider{NetProviderFlow, NetProviderRouting}, nh1},
}
for i, tc := range cases {
i++
t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) {
for _, tc := range cases {
t.Run(fmt.Sprintf("case %s", tc.Pos), func(t *testing.T) {
r := reporter.NewMock(t)
// We don't need all components as we won't start the component.

View File

@@ -11,6 +11,8 @@ import (
"testing"
"unsafe"
"akvorado/common/helpers"
"github.com/kentik/patricia"
"github.com/osrg/gobgp/v3/pkg/packet/bgp"
)
@@ -37,108 +39,129 @@ func TestLargeCommunitiesAlign(t *testing.T) {
func TestRTAEqual(t *testing.T) {
cases := []struct {
pos helpers.Pos
rta1 routeAttributes
rta2 routeAttributes
equal bool
}{
{routeAttributes{asn: 2038}, routeAttributes{asn: 2038}, true},
{routeAttributes{asn: 2038}, routeAttributes{asn: 2039}, false},
{helpers.Mark(), routeAttributes{asn: 2038}, routeAttributes{asn: 2038}, true},
{helpers.Mark(), routeAttributes{asn: 2038}, routeAttributes{asn: 2039}, false},
{
helpers.Mark(),
routeAttributes{asn: 2038, asPath: []uint32{}},
routeAttributes{asn: 2038},
true,
},
{
helpers.Mark(),
routeAttributes{asn: 2038, asPath: []uint32{}},
routeAttributes{asn: 2039},
false,
},
{
helpers.Mark(),
routeAttributes{asn: 2038, communities: []uint32{}},
routeAttributes{asn: 2038},
true,
},
{
helpers.Mark(),
routeAttributes{asn: 2038, communities: []uint32{}},
routeAttributes{asn: 2039},
false,
},
{
helpers.Mark(),
routeAttributes{asn: 2038, largeCommunities: []bgp.LargeCommunity{}},
routeAttributes{asn: 2038},
true,
},
{
helpers.Mark(),
routeAttributes{asn: 2038, largeCommunities: []bgp.LargeCommunity{}},
routeAttributes{asn: 2039},
false,
},
{
helpers.Mark(),
routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3}},
routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3}},
true,
},
{
helpers.Mark(),
routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3}},
routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3, 4}},
false,
},
{
helpers.Mark(),
routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3}},
routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3, 0}},
false,
},
{
helpers.Mark(),
routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3}},
routeAttributes{asn: 2038, asPath: []uint32{1, 2, 4}},
false,
},
{
helpers.Mark(),
routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3, 4}},
routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3, 4}},
true,
},
{
helpers.Mark(),
routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34}},
routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34}},
true,
},
{
helpers.Mark(),
routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34}},
routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35}},
false,
},
{
helpers.Mark(),
routeAttributes{asn: 2038, communities: []uint32{100, 200, 300, 400}},
routeAttributes{asn: 2038, communities: []uint32{100, 200, 300, 400}},
true,
},
{
helpers.Mark(),
routeAttributes{asn: 2038, communities: []uint32{100, 200, 300, 400}},
routeAttributes{asn: 2038, communities: []uint32{100, 200, 300, 402}},
false,
},
{
helpers.Mark(),
routeAttributes{asn: 2038, communities: []uint32{100, 200, 300}},
routeAttributes{asn: 2038, communities: []uint32{100, 200, 300, 400}},
false,
},
{
helpers.Mark(),
routeAttributes{asn: 2038, largeCommunities: []bgp.LargeCommunity{{ASN: 1, LocalData1: 2, LocalData2: 3}, {ASN: 3, LocalData1: 4, LocalData2: 5}, {ASN: 5, LocalData1: 6, LocalData2: 7}}},
routeAttributes{asn: 2038, largeCommunities: []bgp.LargeCommunity{{ASN: 1, LocalData1: 2, LocalData2: 3}, {ASN: 3, LocalData1: 4, LocalData2: 5}, {ASN: 5, LocalData1: 6, LocalData2: 7}}},
true,
},
{
helpers.Mark(),
routeAttributes{asn: 2038, largeCommunities: []bgp.LargeCommunity{{ASN: 1, LocalData1: 2, LocalData2: 3}, {ASN: 3, LocalData1: 4, LocalData2: 5}, {ASN: 5, LocalData1: 6, LocalData2: 7}}},
routeAttributes{asn: 2038, largeCommunities: []bgp.LargeCommunity{{ASN: 1, LocalData1: 2, LocalData2: 3}, {ASN: 3, LocalData1: 4, LocalData2: 5}, {ASN: 5, LocalData1: 6, LocalData2: 8}}},
false,
},
{
helpers.Mark(),
routeAttributes{asn: 2038, largeCommunities: []bgp.LargeCommunity{{ASN: 1, LocalData1: 2, LocalData2: 3}, {ASN: 3, LocalData1: 4, LocalData2: 5}, {ASN: 5, LocalData1: 6, LocalData2: 7}}},
routeAttributes{asn: 2038, largeCommunities: []bgp.LargeCommunity{{ASN: 1, LocalData1: 2, LocalData2: 4}, {ASN: 3, LocalData1: 4, LocalData2: 5}, {ASN: 5, LocalData1: 6, LocalData2: 7}}},
false,
},
{
helpers.Mark(),
routeAttributes{asn: 2038, largeCommunities: []bgp.LargeCommunity{{ASN: 1, LocalData1: 2, LocalData2: 3}, {ASN: 3, LocalData1: 4, LocalData2: 5}}},
routeAttributes{asn: 2038, largeCommunities: []bgp.LargeCommunity{{ASN: 1, LocalData1: 2, LocalData2: 3}, {ASN: 3, LocalData1: 4, LocalData2: 5}, {ASN: 5, LocalData1: 6, LocalData2: 7}}},
false,
@@ -152,9 +175,9 @@ outer:
for _, tc := range cases {
equal := tc.rta1.Equal(tc.rta2)
if equal && !tc.equal {
t.Errorf("%+v == %+v", tc.rta1, tc.rta2)
t.Errorf("%s%+v == %+v", tc.pos, tc.rta1, tc.rta2)
} else if !equal && tc.equal {
t.Errorf("%+v != %+v", tc.rta1, tc.rta2)
t.Errorf("%s%+v != %+v", tc.pos, tc.rta1, tc.rta2)
} else {
equal := tc.rta1.Hash() == tc.rta2.Hash()
if equal && !tc.equal {
@@ -163,9 +186,9 @@ outer:
rtaHashSeed = maphash.MakeSeed()
continue outer
}
t.Errorf("%+v.hash == %+v.hash", tc.rta1, tc.rta2)
t.Errorf("%s%+v.hash == %+v.hash", tc.pos, tc.rta1, tc.rta2)
} else if !equal && tc.equal {
t.Errorf("%+v.hash != %+v.hash", tc.rta1, tc.rta2)
t.Errorf("%s%+v.hash != %+v.hash", tc.pos, tc.rta1, tc.rta2)
}
}
}

View File

@@ -204,8 +204,8 @@ func TestStartWithMissingDatabase(t *testing.T) {
Name string
Config Configuration
}{
{"Inexisting geo database", geoConfiguration},
{"Inexisting ASN database", asnConfiguration},
{"inexisting geo database", geoConfiguration},
{"inexisting ASN database", asnConfiguration},
}
for _, tc := range cases {
t.Run(tc.Name, func(t *testing.T) {