mirror of
https://github.com/akvorado/akvorado.git
synced 2025-12-11 22:14:02 +01:00
tests: introduce helpers.Pos/helpers.Mark
This helps locating the position of a test.
This commit is contained in:
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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 ""
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user