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) { func TestTransformQueryOnCluster(t *testing.T) {
cases := []struct { cases := []struct {
Pos helpers.Pos
Input string Input string
Expected string Expected string
}{ }{
{"SYSTEM RELOAD DICTIONARIES", "SYSTEM RELOAD DICTIONARIES ON CLUSTER akvorado"}, {helpers.Mark(), "SYSTEM RELOAD DICTIONARIES", "SYSTEM RELOAD DICTIONARIES ON CLUSTER akvorado"},
{"system reload dictionaries", "system reload dictionaries ON CLUSTER akvorado"}, {helpers.Mark(), "system reload dictionaries", "system reload dictionaries ON CLUSTER akvorado"},
{" system reload dictionaries ", "system reload dictionaries ON CLUSTER akvorado"}, {helpers.Mark(), " 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(), "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 (n int, PRIMARY KEY n) ENGINE=ReplicatedMergeTree",
"CREATE TABLE test_01148_atomic.rmt2 ON CLUSTER akvorado (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 NO DELAY",
"DROP TABLE IF EXISTS test_repl ON CLUSTER akvorado 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 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", "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 `CREATE DICTIONARY default.asns
( (
asn UInt32 INJECTIVE, 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)`, `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 ( CREATE TABLE queue (
timestamp UInt64, 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')`, `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 CREATE MATERIALIZED VIEW consumer TO daily
AS SELECT toDate(toDateTime(timestamp)) AS day, level, count() as total 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`, `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 // Not modified
{"SELECT 1", "SELECT 1"}, {helpers.Mark(), "SELECT 1", "SELECT 1"},
} }
for _, tc := range cases { for _, tc := range cases {
got := TransformQueryOnCluster(tc.Input, "akvorado") got := TransformQueryOnCluster(tc.Input, "akvorado")
if diff := helpers.Diff(got, tc.Expected); diff != "" { 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) { func TestMapStructureMatchName(t *testing.T) {
cases := []struct { cases := []struct {
pos Pos
mapKey string mapKey string
fieldName string fieldName string
expected bool expected bool
}{ }{
{"one", "one", true}, {Mark(), "one", "one", true},
{"one", "One", true}, {Mark(), "one", "One", true},
{"one-two", "OneTwo", true}, {Mark(), "one-two", "OneTwo", true},
{"onetwo", "OneTwo", true}, {Mark(), "onetwo", "OneTwo", true},
{"One-Two", "OneTwo", true}, {Mark(), "One-Two", "OneTwo", true},
{"two", "one", false}, {Mark(), "two", "one", false},
} }
for _, tc := range cases { for _, tc := range cases {
got := MapStructureMatchName(tc.mapKey, tc.fieldName) got := MapStructureMatchName(tc.mapKey, tc.fieldName)
if got && !tc.expected { 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 { } 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 Blop string
} }
cases := []struct { cases := []struct {
Description string Pos helpers.Pos
Input gin.H Input gin.H
Expected gin.H Expected gin.H
}{ }{
{ {
Description: "single value", Pos: helpers.Mark(),
Input: gin.H{ Input: gin.H{
"blip": "some", "blip": "some",
"blop": "thing", "blop": "thing",
@@ -185,7 +185,7 @@ func TestSubnetMapUnmarshalHookWithMapValue(t *testing.T) {
}, },
}, },
}, { }, {
Description: "proper map", Pos: helpers.Mark(),
Input: gin.H{ Input: gin.H{
"::/0": gin.H{ "::/0": gin.H{
"blip": "some", "blip": "some",
@@ -209,7 +209,7 @@ func TestSubnetMapUnmarshalHookWithMapValue(t *testing.T) {
}, },
} }
for _, tc := range cases { for _, tc := range cases {
t.Run(tc.Description, func(t *testing.T) { t.Run("sub", func(t *testing.T) {
var tree helpers.SubnetMap[SomeStruct] var tree helpers.SubnetMap[SomeStruct]
decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
Result: &tree, Result: &tree,
@@ -218,14 +218,14 @@ func TestSubnetMapUnmarshalHookWithMapValue(t *testing.T) {
DecodeHook: helpers.SubnetMapUnmarshallerHook[SomeStruct](), DecodeHook: helpers.SubnetMapUnmarshallerHook[SomeStruct](),
}) })
if err != nil { if err != nil {
t.Fatalf("NewDecoder() error:\n%+v", err) t.Fatalf("%sNewDecoder() error:\n%+v", tc.Pos, err)
} }
err = decoder.Decode(tc.Input) err = decoder.Decode(tc.Input)
if err != nil { 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 != "" { 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 ( import (
"context" "context"
"errors" "errors"
"fmt"
"net" "net"
"os" "os"
"path/filepath"
"runtime"
"testing" "testing"
"time" "time"
) )
@@ -98,3 +101,23 @@ type starter interface {
type stopper interface { type stopper interface {
Stop() error 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. // may mutate the configuration.
type ConfigurationDecodeCases []struct { type ConfigurationDecodeCases []struct {
Description string Description string
Pos Pos
Initial func() interface{} // initial value for configuration Initial func() interface{} // initial value for configuration
Configuration func() interface{} // configuration to decode Configuration func() interface{} // configuration to decode
Expected interface{} Expected interface{}
@@ -45,10 +46,10 @@ func TestConfigurationDecode(t *testing.T, cases ConfigurationDecodeCases, optio
// Encode and decode with YAML // Encode and decode with YAML
out, err := yaml.Marshal(tc.Configuration()) out, err := yaml.Marshal(tc.Configuration())
if err != nil { 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 { 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 { } else {
// Just use as is // Just use as is
@@ -58,11 +59,11 @@ func TestConfigurationDecode(t *testing.T, cases ConfigurationDecodeCases, optio
decoder, err := mapstructure.NewDecoder(GetMapStructureDecoderConfig(&got)) decoder, err := mapstructure.NewDecoder(GetMapStructureDecoderConfig(&got))
if err != nil { if err != nil {
t.Fatalf("NewDecoder() error:\n%+v", err) t.Fatalf("%sNewDecoder() error:\n%+v", tc.Pos, err)
} }
err = decoder.Decode(configuration) err = decoder.Decode(configuration)
if err != nil && !tc.Error { 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 { } else if tc.Error && err != nil {
return return
} }
@@ -70,21 +71,21 @@ func TestConfigurationDecode(t *testing.T, cases ConfigurationDecodeCases, optio
if !tc.SkipValidation { if !tc.SkipValidation {
err = Validate.Struct(got) err = Validate.Struct(got)
if err != nil && !tc.Error { 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 { } else if tc.Error && err != nil {
return return
} }
if tc.Error { if tc.Error {
t.Errorf("Decode() and Validate() did not error") t.Errorf("%sDecode() and Validate() did not error", tc.Pos)
} }
} else { } else {
if tc.Error { 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 { 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 // HTTPEndpointCases describes case for TestHTTPEndpoints
type HTTPEndpointCases []struct { type HTTPEndpointCases []struct {
Pos Pos
Description string Description string
Method string Method string
URL 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.Run(desc, func(t *testing.T) {
t.Helper() t.Helper()
if tc.FirstLines != nil && tc.JSONOutput != nil { 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 resp *http.Response
var err error var err error
@@ -62,13 +63,13 @@ func TestHTTPEndpoints(t *testing.T, serverAddr net.Addr, cases HTTPEndpointCase
} }
resp, err = http.DefaultClient.Do(req) resp, err = http.DefaultClient.Do(req)
if err != nil { 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 { } else {
payload := new(bytes.Buffer) payload := new(bytes.Buffer)
err = json.NewEncoder(payload).Encode(tc.JSONInput) err = json.NewEncoder(payload).Encode(tc.JSONInput)
if err != nil { if err != nil {
t.Fatalf("Encode() error:\n%+v", err) t.Fatalf("%sEncode() error:\n%+v", tc.Pos, err)
} }
req, _ := http.NewRequest(tc.Method, req, _ := http.NewRequest(tc.Method,
fmt.Sprintf("http://%s%s", serverAddr, tc.URL), 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") req.Header.Add("Content-Type", "application/json")
resp, err = http.DefaultClient.Do(req) resp, err = http.DefaultClient.Do(req)
if err != nil { 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 tc.StatusCode = 200
} }
if resp.StatusCode != tc.StatusCode { 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) tc.Method, resp.StatusCode, tc.StatusCode)
} }
if tc.JSONOutput != nil { if tc.JSONOutput != nil {
@@ -96,7 +98,8 @@ func TestHTTPEndpoints(t *testing.T, serverAddr net.Addr, cases HTTPEndpointCase
} }
gotContentType := resp.Header.Get("Content-Type") gotContentType := resp.Header.Get("Content-Type")
if gotContentType != tc.ContentType { 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) tc.Method, tc.URL, gotContentType, tc.ContentType)
} }
if tc.JSONOutput == nil { if tc.JSONOutput == nil {
@@ -106,16 +109,16 @@ func TestHTTPEndpoints(t *testing.T, serverAddr net.Addr, cases HTTPEndpointCase
got = append(got, reader.Text()) got = append(got, reader.Text())
} }
if diff := Diff(got, tc.FirstLines); diff != "" { 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 { } else {
decoder := json.NewDecoder(resp.Body) decoder := json.NewDecoder(resp.Body)
var got gin.H var got gin.H
if err := decoder.Decode(&got); err != nil { 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 != "" { 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"` Listen string `validate:"listen"`
}{} }{}
cases := []struct { cases := []struct {
Pos helpers.Pos
Listen string Listen string
Err bool Err bool
}{ }{
{"127.0.0.1:161", false}, {helpers.Mark(), "127.0.0.1:161", false},
{"localhost:161", false}, {helpers.Mark(), "localhost:161", false},
{"0.0.0.0:161", false}, {helpers.Mark(), "0.0.0.0:161", false},
{"0.0.0.0:0", false}, {helpers.Mark(), "0.0.0.0:0", false},
{":161", false}, {helpers.Mark(), ":161", false},
{":0", false}, {helpers.Mark(), ":0", false},
{"127.0.0.1:0", false}, {helpers.Mark(), "127.0.0.1:0", false},
{"localhost", true}, {helpers.Mark(), "localhost", true},
{"127.0.0.1", true}, {helpers.Mark(), "127.0.0.1", true},
{"127.0.0.1:what", true}, {helpers.Mark(), "127.0.0.1:what", true},
{"127.0.0.1:100000", true}, {helpers.Mark(), "127.0.0.1:100000", true},
} }
for _, tc := range cases { for _, tc := range cases {
s.Listen = tc.Listen s.Listen = tc.Listen
err := helpers.Validate.Struct(s) err := helpers.Validate.Struct(s)
if err == nil && tc.Err { 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 { } 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"` Set2 []string `validate:"ninterfield=Set1"`
}{} }{}
cases := []struct { cases := []struct {
Pos helpers.Pos
Set1 []string Set1 []string
Set2 []string Set2 []string
Err bool Err bool
}{ }{
{nil, nil, false}, {helpers.Mark(), nil, nil, false},
{nil, []string{"aaa"}, false}, {helpers.Mark(), nil, []string{"aaa"}, false},
{[]string{}, []string{"bbb"}, false}, {helpers.Mark(), []string{}, []string{"bbb"}, false},
{[]string{}, []string{"bbb"}, false}, {helpers.Mark(), []string{}, []string{"bbb"}, false},
{[]string{"bbb"}, nil, false}, {helpers.Mark(), []string{"bbb"}, nil, false},
{[]string{"aaa"}, []string{"bbb"}, false}, {helpers.Mark(), []string{"aaa"}, []string{"bbb"}, false},
{[]string{"aaa", "ccc"}, []string{"bbb"}, false}, {helpers.Mark(), []string{"aaa", "ccc"}, []string{"bbb"}, false},
{[]string{"aaa"}, []string{"aaa"}, true}, {helpers.Mark(), []string{"aaa"}, []string{"aaa"}, true},
{[]string{"aaa", "ccc"}, []string{"bbb", "ddd"}, false}, {helpers.Mark(), []string{"aaa", "ccc"}, []string{"bbb", "ddd"}, false},
{[]string{"aaa", "ccc"}, []string{"bbb", "ccc"}, true}, {helpers.Mark(), []string{"aaa", "ccc"}, []string{"bbb", "ccc"}, true},
{[]string{"aaa", "ccc"}, []string{"ccc", "bbb"}, true}, {helpers.Mark(), []string{"aaa", "ccc"}, []string{"ccc", "bbb"}, true},
} }
for _, tc := range cases { for _, tc := range cases {
s.Set1 = tc.Set1 s.Set1 = tc.Set1

View File

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

View File

@@ -6,39 +6,41 @@ package console
import ( import (
"testing" "testing"
"akvorado/common/helpers"
"akvorado/common/schema" "akvorado/common/schema"
"akvorado/console/query" "akvorado/console/query"
) )
func TestRequireMainTable(t *testing.T) { func TestRequireMainTable(t *testing.T) {
cases := []struct { cases := []struct {
Pos helpers.Pos
Columns []query.Column Columns []query.Column
Filter query.Filter Filter query.Filter
Expected bool Expected bool
}{ }{
{[]query.Column{}, query.NewFilter(""), false}, {helpers.Mark(), []query.Column{}, query.NewFilter(""), false},
{[]query.Column{query.NewColumn("SrcAS")}, query.NewFilter(""), false}, {helpers.Mark(), []query.Column{query.NewColumn("SrcAS")}, query.NewFilter(""), false},
{[]query.Column{query.NewColumn("ExporterAddress")}, query.NewFilter(""), false}, {helpers.Mark(), []query.Column{query.NewColumn("ExporterAddress")}, query.NewFilter(""), false},
{[]query.Column{query.NewColumn("SrcPort")}, query.NewFilter(""), true}, {helpers.Mark(), []query.Column{query.NewColumn("SrcPort")}, query.NewFilter(""), true},
{[]query.Column{query.NewColumn("SrcAddr")}, query.NewFilter(""), true}, {helpers.Mark(), []query.Column{query.NewColumn("SrcAddr")}, query.NewFilter(""), true},
{[]query.Column{query.NewColumn("DstPort")}, query.NewFilter(""), true}, {helpers.Mark(), []query.Column{query.NewColumn("DstPort")}, query.NewFilter(""), true},
{[]query.Column{query.NewColumn("DstAddr")}, query.NewFilter(""), true}, {helpers.Mark(), []query.Column{query.NewColumn("DstAddr")}, query.NewFilter(""), true},
{[]query.Column{query.NewColumn("SrcAS"), query.NewColumn("DstAddr")}, query.NewFilter(""), true}, {helpers.Mark(), []query.Column{query.NewColumn("SrcAS"), query.NewColumn("DstAddr")}, query.NewFilter(""), true},
{[]query.Column{query.NewColumn("DstAddr"), query.NewColumn("SrcAS")}, query.NewFilter(""), true}, {helpers.Mark(), []query.Column{query.NewColumn("DstAddr"), query.NewColumn("SrcAS")}, query.NewFilter(""), true},
{[]query.Column{query.NewColumn("DstNetPrefix")}, query.NewFilter(""), true}, {helpers.Mark(), []query.Column{query.NewColumn("DstNetPrefix")}, query.NewFilter(""), true},
{[]query.Column{}, query.NewFilter("SrcAddr = 203.0.113.15"), true}, {helpers.Mark(), []query.Column{}, query.NewFilter("SrcAddr = 203.0.113.15"), true},
} }
sch := schema.NewMock(t) sch := schema.NewMock(t)
for idx, tc := range cases { for idx, tc := range cases {
if err := query.Columns(tc.Columns).Validate(sch); err != nil { 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 { 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) got := requireMainTable(sch, tc.Columns, tc.Filter)
if got != tc.Expected { 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) { func TestSankeyQuerySQL(t *testing.T) {
cases := []struct { cases := []struct {
Description string Description string
Pos helpers.Pos
Input graphSankeyHandlerInput Input graphSankeyHandlerInput
Expected string Expected string
}{ }{
{ {
Description: "two dimensions, no filters, l3 bps", Description: "two dimensions, no filters, l3 bps",
Pos: helpers.Mark(),
Input: graphSankeyHandlerInput{ Input: graphSankeyHandlerInput{
graphCommonHandlerInput{ graphCommonHandlerInput{
Start: time.Date(2022, 4, 10, 15, 45, 10, 0, time.UTC), Start: time.Date(2022, 4, 10, 15, 45, 10, 0, time.UTC),
@@ -54,6 +56,7 @@ ORDER BY xps DESC
{{ end }}`, {{ end }}`,
}, { }, {
Description: "two dimensions, no filters, l2 bps", Description: "two dimensions, no filters, l2 bps",
Pos: helpers.Mark(),
Input: graphSankeyHandlerInput{ Input: graphSankeyHandlerInput{
graphCommonHandlerInput{ graphCommonHandlerInput{
Start: time.Date(2022, 4, 10, 15, 45, 10, 0, time.UTC), 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", Description: "two dimensions, no filters, pps",
Pos: helpers.Mark(),
Input: graphSankeyHandlerInput{ Input: graphSankeyHandlerInput{
graphCommonHandlerInput{ graphCommonHandlerInput{
Start: time.Date(2022, 4, 10, 15, 45, 10, 0, time.UTC), Start: time.Date(2022, 4, 10, 15, 45, 10, 0, time.UTC),
@@ -115,6 +119,7 @@ ORDER BY xps DESC
{{ end }}`, {{ end }}`,
}, { }, {
Description: "two dimensions, with filter", Description: "two dimensions, with filter",
Pos: helpers.Mark(),
Input: graphSankeyHandlerInput{ Input: graphSankeyHandlerInput{
graphCommonHandlerInput{ graphCommonHandlerInput{
Start: time.Date(2022, 4, 10, 15, 45, 10, 0, time.UTC), Start: time.Date(2022, 4, 10, 15, 45, 10, 0, time.UTC),
@@ -148,17 +153,17 @@ ORDER BY xps DESC
for _, tc := range cases { for _, tc := range cases {
tc.Input.schema = schema.NewMock(t) tc.Input.schema = schema.NewMock(t)
if err := query.Columns(tc.Input.Dimensions).Validate(tc.Input.schema); err != nil { 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 { 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, "@@", "`") tc.Expected = strings.ReplaceAll(tc.Expected, "@@", "`")
t.Run(tc.Description, func(t *testing.T) { t.Run(tc.Description, func(t *testing.T) {
got, _ := tc.Input.toSQL() got, _ := tc.Input.toSQL()
if diff := helpers.Diff(strings.Split(strings.TrimSpace(got), "\n"), if diff := helpers.Diff(strings.Split(strings.TrimSpace(got), "\n"),
strings.Split(strings.TrimSpace(tc.Expected), "\n")); diff != "" { 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) { func TestPeakHourDistance(t *testing.T) {
cases := []struct { cases := []struct {
Pos helpers.Pos
Peak time.Duration Peak time.Duration
Now time.Duration Now time.Duration
Expected float64 Expected float64
}{ }{
{6 * time.Hour, 6 * time.Hour, 1}, {helpers.Mark(), 6 * time.Hour, 6 * time.Hour, 1},
{6 * time.Hour, 0, 0.5}, {helpers.Mark(), 6 * time.Hour, 0, 0.5},
{6 * time.Hour, 18 * time.Hour, 0}, {helpers.Mark(), 6 * time.Hour, 18 * time.Hour, 0},
{12 * time.Hour, 13 * time.Hour, 11. / 12}, {helpers.Mark(), 12 * time.Hour, 13 * time.Hour, 11. / 12},
{12 * time.Hour, 11 * time.Hour, 11. / 12}, {helpers.Mark(), 12 * time.Hour, 11 * time.Hour, 11. / 12},
{12 * time.Hour, 14 * time.Hour, 10. / 12}, {helpers.Mark(), 12 * time.Hour, 14 * time.Hour, 10. / 12},
{12 * time.Hour, 15 * time.Hour, 9. / 12}, {helpers.Mark(), 12 * time.Hour, 15 * time.Hour, 9. / 12},
{12 * time.Hour, 16 * time.Hour, 8. / 12}, {helpers.Mark(), 12 * time.Hour, 16 * time.Hour, 8. / 12},
{12 * time.Hour, 17 * time.Hour, 7. / 12}, {helpers.Mark(), 12 * time.Hour, 17 * time.Hour, 7. / 12},
{12 * time.Hour, 18 * time.Hour, 6. / 12}, {helpers.Mark(), 12 * time.Hour, 18 * time.Hour, 6. / 12},
{12 * time.Hour, 19 * time.Hour, 5. / 12}, {helpers.Mark(), 12 * time.Hour, 19 * time.Hour, 5. / 12},
} }
for _, tc := range cases { for _, tc := range cases {
got := peakHourDistance(tc.Now, tc.Peak) got := peakHourDistance(tc.Now, tc.Peak)
if math.Abs(got-tc.Expected) > tc.Expected*0.01 { if math.Abs(got-tc.Expected) > tc.Expected*0.01 {
t.Errorf("peakHourDistance(%s, %s) == %f, expected %f", t.Errorf("%speakHourDistance(%s, %s) == %f, expected %f",
tc.Peak, tc.Now, got, tc.Expected) tc.Pos, tc.Peak, tc.Now, got, tc.Expected)
} }
} }
} }
@@ -129,10 +130,12 @@ func TestChooseRandom(t *testing.T) {
func TestGenerateFlows(t *testing.T) { func TestGenerateFlows(t *testing.T) {
cases := []struct { cases := []struct {
Pos helpers.Pos
FlowConfiguration FlowConfiguration
Expected []generatedFlow Expected []generatedFlow
}{ }{
{ {
Pos: helpers.Mark(),
FlowConfiguration: FlowConfiguration{ FlowConfiguration: FlowConfiguration{
PerSecond: 1, PerSecond: 1,
InIfIndex: []int{10}, InIfIndex: []int{10},
@@ -187,6 +190,7 @@ func TestGenerateFlows(t *testing.T) {
}, },
}, },
}, { }, {
Pos: helpers.Mark(),
FlowConfiguration: FlowConfiguration{ FlowConfiguration: FlowConfiguration{
PerSecond: 1, PerSecond: 1,
InIfIndex: []int{20}, InIfIndex: []int{20},
@@ -223,6 +227,7 @@ func TestGenerateFlows(t *testing.T) {
}, },
}, },
}, { }, {
Pos: helpers.Mark(),
FlowConfiguration: FlowConfiguration{ FlowConfiguration: FlowConfiguration{
PerSecond: 1, PerSecond: 1,
InIfIndex: []int{20}, InIfIndex: []int{20},
@@ -280,11 +285,11 @@ func TestGenerateFlows(t *testing.T) {
}, },
} }
now := time.Date(2022, 3, 18, 15, 0, 0, 0, time.UTC) now := time.Date(2022, 3, 18, 15, 0, 0, 0, time.UTC)
for i, tc := range cases { for _, tc := range cases {
t.Run(fmt.Sprintf("case %d", i+1), func(t *testing.T) { t.Run(fmt.Sprintf("case %s", tc.Pos), func(t *testing.T) {
got := generateFlows([]FlowConfiguration{tc.FlowConfiguration}, 0, now) got := generateFlows([]FlowConfiguration{tc.FlowConfiguration}, 0, now)
if diff := helpers.Diff(got, tc.Expected); diff != "" { 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) { func TestGetASNumber(t *testing.T) {
cases := []struct { cases := []struct {
Pos helpers.Pos
Addr string Addr string
FlowAS uint32 FlowAS uint32
BMPAS uint32 BMPAS uint32
@@ -628,22 +629,21 @@ func TestGetASNumber(t *testing.T) {
Expected uint32 Expected uint32
}{ }{
// 1 // 1
{"1.0.0.1", 12322, 0, []ASNProvider{ASNProviderFlow}, 12322}, {helpers.Mark(), "1.0.0.1", 12322, 0, []ASNProvider{ASNProviderFlow}, 12322},
{"::ffff:1.0.0.1", 12322, 0, []ASNProvider{ASNProviderFlow}, 12322}, {helpers.Mark(), "::ffff:1.0.0.1", 12322, 0, []ASNProvider{ASNProviderFlow}, 12322},
{"1.0.0.1", 65536, 0, []ASNProvider{ASNProviderFlow}, 65536}, {helpers.Mark(), "1.0.0.1", 65536, 0, []ASNProvider{ASNProviderFlow}, 65536},
{"1.0.0.1", 65536, 0, []ASNProvider{ASNProviderFlowExceptPrivate}, 0}, {helpers.Mark(), "1.0.0.1", 65536, 0, []ASNProvider{ASNProviderFlowExceptPrivate}, 0},
{"1.0.0.1", 4_200_000_121, 0, []ASNProvider{ASNProviderFlowExceptPrivate}, 0}, {helpers.Mark(), "1.0.0.1", 4_200_000_121, 0, []ASNProvider{ASNProviderFlowExceptPrivate}, 0},
{"1.0.0.1", 65536, 0, []ASNProvider{ASNProviderFlowExceptPrivate, ASNProviderFlow}, 65536}, {helpers.Mark(), "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{ASNProviderFlowExceptPrivate}, 12322},
// 10 // 10
{"192.0.2.2", 12322, 174, []ASNProvider{ASNProviderRouting}, 174}, {helpers.Mark(), "192.0.2.2", 12322, 174, []ASNProvider{ASNProviderRouting}, 174},
{"192.0.2.129", 12322, 1299, []ASNProvider{ASNProviderRouting}, 1299}, {helpers.Mark(), "192.0.2.129", 12322, 1299, []ASNProvider{ASNProviderRouting}, 1299},
{"192.0.2.254", 12322, 0, []ASNProvider{ASNProviderRouting}, 0}, {helpers.Mark(), "192.0.2.254", 12322, 0, []ASNProvider{ASNProviderRouting}, 0},
{"1.0.0.1", 12322, 65300, []ASNProvider{ASNProviderRouting}, 65300}, {helpers.Mark(), "1.0.0.1", 12322, 65300, []ASNProvider{ASNProviderRouting}, 65300},
} }
for i, tc := range cases { for _, tc := range cases {
i++ t.Run(fmt.Sprintf("case %s", tc.Pos), func(t *testing.T) {
t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) {
r := reporter.NewMock(t) r := reporter.NewMock(t)
// We don't need all components as we won't start the component. // 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), Schema: schema.NewMock(t),
}) })
if err != nil { 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) got := c.getASNumber(tc.FlowAS, tc.BMPAS)
if diff := helpers.Diff(got, tc.Expected); diff != "" { 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) { func TestGetNetMask(t *testing.T) {
cases := []struct { cases := []struct {
// Addr string Pos helpers.Pos
FlowNetMask uint8 FlowNetMask uint8
BMPNetMask uint8 BMPNetMask uint8
Providers []NetProvider Providers []NetProvider
Expected uint8 Expected uint8
}{ }{
// Flow // Flow
{0, 0, []NetProvider{NetProviderFlow}, 0}, {helpers.Mark(), 0, 0, []NetProvider{NetProviderFlow}, 0},
{32, 0, []NetProvider{NetProviderFlow}, 32}, {helpers.Mark(), 32, 0, []NetProvider{NetProviderFlow}, 32},
{0, 16, []NetProvider{NetProviderFlow}, 0}, {helpers.Mark(), 0, 16, []NetProvider{NetProviderFlow}, 0},
// BMP // BMP
{0, 0, []NetProvider{NetProviderRouting}, 0}, {helpers.Mark(), 0, 0, []NetProvider{NetProviderRouting}, 0},
{32, 12, []NetProvider{NetProviderRouting}, 12}, {helpers.Mark(), 32, 12, []NetProvider{NetProviderRouting}, 12},
{0, 16, []NetProvider{NetProviderRouting}, 16}, {helpers.Mark(), 0, 16, []NetProvider{NetProviderRouting}, 16},
{24, 0, []NetProvider{NetProviderRouting}, 0}, {helpers.Mark(), 24, 0, []NetProvider{NetProviderRouting}, 0},
// Both, the first provider with a non-default route is taken // Both, the first provider with a non-default route is taken
{0, 0, []NetProvider{NetProviderRouting, NetProviderFlow}, 0}, {helpers.Mark(), 0, 0, []NetProvider{NetProviderRouting, NetProviderFlow}, 0},
{12, 0, []NetProvider{NetProviderRouting, NetProviderFlow}, 12}, {helpers.Mark(), 12, 0, []NetProvider{NetProviderRouting, NetProviderFlow}, 12},
{0, 13, []NetProvider{NetProviderRouting, NetProviderFlow}, 13}, {helpers.Mark(), 0, 13, []NetProvider{NetProviderRouting, NetProviderFlow}, 13},
{12, 0, []NetProvider{NetProviderRouting, NetProviderFlow}, 12}, {helpers.Mark(), 12, 0, []NetProvider{NetProviderRouting, NetProviderFlow}, 12},
{12, 24, []NetProvider{NetProviderRouting, NetProviderFlow}, 24}, {helpers.Mark(), 12, 24, []NetProvider{NetProviderRouting, NetProviderFlow}, 24},
{0, 0, []NetProvider{NetProviderFlow, NetProviderRouting}, 0}, {helpers.Mark(), 0, 0, []NetProvider{NetProviderFlow, NetProviderRouting}, 0},
{12, 0, []NetProvider{NetProviderFlow, NetProviderRouting}, 12}, {helpers.Mark(), 12, 0, []NetProvider{NetProviderFlow, NetProviderRouting}, 12},
{0, 13, []NetProvider{NetProviderFlow, NetProviderRouting}, 13}, {helpers.Mark(), 0, 13, []NetProvider{NetProviderFlow, NetProviderRouting}, 13},
{12, 0, []NetProvider{NetProviderFlow, NetProviderRouting}, 12}, {helpers.Mark(), 12, 0, []NetProvider{NetProviderFlow, NetProviderRouting}, 12},
{12, 24, []NetProvider{NetProviderFlow, NetProviderRouting}, 12}, {helpers.Mark(), 12, 24, []NetProvider{NetProviderFlow, NetProviderRouting}, 12},
} }
for i, tc := range cases { for _, tc := range cases {
i++ t.Run(fmt.Sprintf("case %s", tc.Pos), func(t *testing.T) {
t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) {
r := reporter.NewMock(t) r := reporter.NewMock(t)
// We don't need all components as we won't start the component. // 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") nh1 := netip.MustParseAddr("2001:db8::1")
nh2 := netip.MustParseAddr("2001:db8::2") nh2 := netip.MustParseAddr("2001:db8::2")
cases := []struct { cases := []struct {
Pos helpers.Pos
FlowNextHop netip.Addr FlowNextHop netip.Addr
RoutingNextHop netip.Addr RoutingNextHop netip.Addr
Providers []NetProvider Providers []NetProvider
Expected netip.Addr Expected netip.Addr
}{ }{
// Flow // Flow
{netip.IPv6Unspecified(), netip.IPv6Unspecified(), []NetProvider{NetProviderFlow}, netip.IPv6Unspecified()}, {helpers.Mark(), netip.IPv6Unspecified(), netip.IPv6Unspecified(), []NetProvider{NetProviderFlow}, netip.IPv6Unspecified()},
{nh1, netip.IPv6Unspecified(), []NetProvider{NetProviderFlow}, nh1}, {helpers.Mark(), nh1, netip.IPv6Unspecified(), []NetProvider{NetProviderFlow}, nh1},
{netip.IPv6Unspecified(), nh1, []NetProvider{NetProviderFlow}, netip.IPv6Unspecified()}, {helpers.Mark(), netip.IPv6Unspecified(), nh1, []NetProvider{NetProviderFlow}, netip.IPv6Unspecified()},
// Routing // Routing
{netip.IPv6Unspecified(), netip.IPv6Unspecified(), []NetProvider{NetProviderRouting}, netip.IPv6Unspecified()}, {helpers.Mark(), netip.IPv6Unspecified(), netip.IPv6Unspecified(), []NetProvider{NetProviderRouting}, netip.IPv6Unspecified()},
{nh1, netip.IPv6Unspecified(), []NetProvider{NetProviderRouting}, netip.IPv6Unspecified()}, {helpers.Mark(), nh1, netip.IPv6Unspecified(), []NetProvider{NetProviderRouting}, netip.IPv6Unspecified()},
{netip.IPv6Unspecified(), nh1, []NetProvider{NetProviderRouting}, nh1}, {helpers.Mark(), netip.IPv6Unspecified(), nh1, []NetProvider{NetProviderRouting}, nh1},
// Both // Both
{netip.IPv6Unspecified(), netip.IPv6Unspecified(), []NetProvider{NetProviderRouting, NetProviderFlow}, netip.IPv6Unspecified()}, {helpers.Mark(), netip.IPv6Unspecified(), netip.IPv6Unspecified(), []NetProvider{NetProviderRouting, NetProviderFlow}, netip.IPv6Unspecified()},
{nh1, netip.IPv6Unspecified(), []NetProvider{NetProviderRouting, NetProviderFlow}, nh1}, {helpers.Mark(), nh1, netip.IPv6Unspecified(), []NetProvider{NetProviderRouting, NetProviderFlow}, nh1},
{netip.IPv6Unspecified(), nh2, []NetProvider{NetProviderRouting, NetProviderFlow}, nh2}, {helpers.Mark(), netip.IPv6Unspecified(), nh2, []NetProvider{NetProviderRouting, NetProviderFlow}, nh2},
{nh1, netip.IPv6Unspecified(), []NetProvider{NetProviderRouting, NetProviderFlow}, nh1}, {helpers.Mark(), nh1, netip.IPv6Unspecified(), []NetProvider{NetProviderRouting, NetProviderFlow}, nh1},
{nh1, nh2, []NetProvider{NetProviderRouting, NetProviderFlow}, nh2}, {helpers.Mark(), nh1, nh2, []NetProvider{NetProviderRouting, NetProviderFlow}, nh2},
{netip.IPv6Unspecified(), netip.IPv6Unspecified(), []NetProvider{NetProviderFlow, NetProviderRouting}, netip.IPv6Unspecified()}, {helpers.Mark(), netip.IPv6Unspecified(), netip.IPv6Unspecified(), []NetProvider{NetProviderFlow, NetProviderRouting}, netip.IPv6Unspecified()},
{nh1, netip.IPv6Unspecified(), []NetProvider{NetProviderFlow, NetProviderRouting}, nh1}, {helpers.Mark(), nh1, netip.IPv6Unspecified(), []NetProvider{NetProviderFlow, NetProviderRouting}, nh1},
{netip.IPv6Unspecified(), nh2, []NetProvider{NetProviderFlow, NetProviderRouting}, nh2}, {helpers.Mark(), netip.IPv6Unspecified(), nh2, []NetProvider{NetProviderFlow, NetProviderRouting}, nh2},
{nh1, netip.IPv6Unspecified(), []NetProvider{NetProviderFlow, NetProviderRouting}, nh1}, {helpers.Mark(), nh1, netip.IPv6Unspecified(), []NetProvider{NetProviderFlow, NetProviderRouting}, nh1},
{nh1, nh2, []NetProvider{NetProviderFlow, NetProviderRouting}, nh1}, {helpers.Mark(), nh1, nh2, []NetProvider{NetProviderFlow, NetProviderRouting}, nh1},
} }
for i, tc := range cases { for _, tc := range cases {
i++ t.Run(fmt.Sprintf("case %s", tc.Pos), func(t *testing.T) {
t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) {
r := reporter.NewMock(t) r := reporter.NewMock(t)
// We don't need all components as we won't start the component. // We don't need all components as we won't start the component.

View File

@@ -11,6 +11,8 @@ import (
"testing" "testing"
"unsafe" "unsafe"
"akvorado/common/helpers"
"github.com/kentik/patricia" "github.com/kentik/patricia"
"github.com/osrg/gobgp/v3/pkg/packet/bgp" "github.com/osrg/gobgp/v3/pkg/packet/bgp"
) )
@@ -37,108 +39,129 @@ func TestLargeCommunitiesAlign(t *testing.T) {
func TestRTAEqual(t *testing.T) { func TestRTAEqual(t *testing.T) {
cases := []struct { cases := []struct {
pos helpers.Pos
rta1 routeAttributes rta1 routeAttributes
rta2 routeAttributes rta2 routeAttributes
equal bool equal bool
}{ }{
{routeAttributes{asn: 2038}, routeAttributes{asn: 2038}, true}, {helpers.Mark(), routeAttributes{asn: 2038}, routeAttributes{asn: 2038}, true},
{routeAttributes{asn: 2038}, routeAttributes{asn: 2039}, false}, {helpers.Mark(), routeAttributes{asn: 2038}, routeAttributes{asn: 2039}, false},
{ {
helpers.Mark(),
routeAttributes{asn: 2038, asPath: []uint32{}}, routeAttributes{asn: 2038, asPath: []uint32{}},
routeAttributes{asn: 2038}, routeAttributes{asn: 2038},
true, true,
}, },
{ {
helpers.Mark(),
routeAttributes{asn: 2038, asPath: []uint32{}}, routeAttributes{asn: 2038, asPath: []uint32{}},
routeAttributes{asn: 2039}, routeAttributes{asn: 2039},
false, false,
}, },
{ {
helpers.Mark(),
routeAttributes{asn: 2038, communities: []uint32{}}, routeAttributes{asn: 2038, communities: []uint32{}},
routeAttributes{asn: 2038}, routeAttributes{asn: 2038},
true, true,
}, },
{ {
helpers.Mark(),
routeAttributes{asn: 2038, communities: []uint32{}}, routeAttributes{asn: 2038, communities: []uint32{}},
routeAttributes{asn: 2039}, routeAttributes{asn: 2039},
false, false,
}, },
{ {
helpers.Mark(),
routeAttributes{asn: 2038, largeCommunities: []bgp.LargeCommunity{}}, routeAttributes{asn: 2038, largeCommunities: []bgp.LargeCommunity{}},
routeAttributes{asn: 2038}, routeAttributes{asn: 2038},
true, true,
}, },
{ {
helpers.Mark(),
routeAttributes{asn: 2038, largeCommunities: []bgp.LargeCommunity{}}, routeAttributes{asn: 2038, largeCommunities: []bgp.LargeCommunity{}},
routeAttributes{asn: 2039}, routeAttributes{asn: 2039},
false, false,
}, },
{ {
helpers.Mark(),
routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3}}, routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3}},
routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3}}, routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3}},
true, true,
}, },
{ {
helpers.Mark(),
routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3}}, routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3}},
routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3, 4}}, routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3, 4}},
false, false,
}, },
{ {
helpers.Mark(),
routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3}}, routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3}},
routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3, 0}}, routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3, 0}},
false, false,
}, },
{ {
helpers.Mark(),
routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3}}, routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3}},
routeAttributes{asn: 2038, asPath: []uint32{1, 2, 4}}, routeAttributes{asn: 2038, asPath: []uint32{1, 2, 4}},
false, false,
}, },
{ {
helpers.Mark(),
routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3, 4}}, routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3, 4}},
routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3, 4}}, routeAttributes{asn: 2038, asPath: []uint32{1, 2, 3, 4}},
true, 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}},
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, 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}},
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}}, 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, false,
}, },
{ {
helpers.Mark(),
routeAttributes{asn: 2038, communities: []uint32{100, 200, 300, 400}}, routeAttributes{asn: 2038, communities: []uint32{100, 200, 300, 400}},
routeAttributes{asn: 2038, communities: []uint32{100, 200, 300, 400}}, routeAttributes{asn: 2038, communities: []uint32{100, 200, 300, 400}},
true, true,
}, },
{ {
helpers.Mark(),
routeAttributes{asn: 2038, communities: []uint32{100, 200, 300, 400}}, routeAttributes{asn: 2038, communities: []uint32{100, 200, 300, 400}},
routeAttributes{asn: 2038, communities: []uint32{100, 200, 300, 402}}, routeAttributes{asn: 2038, communities: []uint32{100, 200, 300, 402}},
false, false,
}, },
{ {
helpers.Mark(),
routeAttributes{asn: 2038, communities: []uint32{100, 200, 300}}, routeAttributes{asn: 2038, communities: []uint32{100, 200, 300}},
routeAttributes{asn: 2038, communities: []uint32{100, 200, 300, 400}}, routeAttributes{asn: 2038, communities: []uint32{100, 200, 300, 400}},
false, 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}}},
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, 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: 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}}}, 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, 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}}},
routeAttributes{asn: 2038, largeCommunities: []bgp.LargeCommunity{{ASN: 1, LocalData1: 2, LocalData2: 4}, {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, 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}}},
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}}},
false, false,
@@ -152,9 +175,9 @@ outer:
for _, tc := range cases { for _, tc := range cases {
equal := tc.rta1.Equal(tc.rta2) equal := tc.rta1.Equal(tc.rta2)
if equal && !tc.equal { 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 { } 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 { } else {
equal := tc.rta1.Hash() == tc.rta2.Hash() equal := tc.rta1.Hash() == tc.rta2.Hash()
if equal && !tc.equal { if equal && !tc.equal {
@@ -163,9 +186,9 @@ outer:
rtaHashSeed = maphash.MakeSeed() rtaHashSeed = maphash.MakeSeed()
continue outer 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 { } 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 Name string
Config Configuration Config Configuration
}{ }{
{"Inexisting geo database", geoConfiguration}, {"inexisting geo database", geoConfiguration},
{"Inexisting ASN database", asnConfiguration}, {"inexisting ASN database", asnConfiguration},
} }
for _, tc := range cases { for _, tc := range cases {
t.Run(tc.Name, func(t *testing.T) { t.Run(tc.Name, func(t *testing.T) {