tests: replace godebug by go-cmp for structure diffs

go-cmp is stricter and allow to catch more problems. Moreover, the
output is a bit nicer.
This commit is contained in:
Vincent Bernat
2025-08-23 08:28:38 +02:00
parent 1a09ba9e7c
commit e2f1df9add
45 changed files with 852 additions and 710 deletions

View File

@@ -158,13 +158,13 @@ module2:
if err := yaml.Unmarshal(out.Bytes(), &gotRaw); err != nil {
t.Fatalf("Unmarshal() error:\n%+v", err)
}
expectedRaw := gin.H{
"module1": gin.H{
expectedRaw := map[string]gin.H{
"module1": {
"listen": "127.0.0.1:8080",
"topic": "flows",
"workers": 100,
},
"module2": gin.H{
"module2": {
"stuff": "bye",
"details": gin.H{
"workers": 5,
@@ -356,7 +356,7 @@ invalid key "unused"`); diff != "" {
}
func TestDefaultInSlice(t *testing.T) {
try := func(t *testing.T, parse func(cmd.ConfigRelatedOptions, *bytes.Buffer) any) {
try := func(t *testing.T, parse func(cmd.ConfigRelatedOptions, *bytes.Buffer) any, expected any) {
// Configuration file
config := `---
modules:
@@ -375,60 +375,6 @@ modules:
out := bytes.NewBuffer([]byte{})
parsed := parse(c, out)
// Expected configuration
expected := map[string][]dummyConfiguration{
"Modules": {
{
Module1: dummyModule1Configuration{
Listen: "127.0.0.1:8080",
Topic: "flows1",
Workers: 100,
},
Module2: dummyModule2Configuration{
MoreDetails: MoreDetails{
Stuff: "hello",
},
Details: dummyModule2DetailsConfiguration{
Workers: 1,
IntervalValue: time.Minute,
},
Elements: []dummyModule2ElementsConfiguration{
{
Name: "el1",
Gauge: 10,
}, {
Name: "el2",
Gauge: 11,
},
},
},
}, {
Module1: dummyModule1Configuration{
Listen: "127.0.0.1:8080",
Topic: "flows2",
Workers: 100,
},
Module2: dummyModule2Configuration{
MoreDetails: MoreDetails{
Stuff: "hello",
},
Details: dummyModule2DetailsConfiguration{
Workers: 1,
IntervalValue: time.Minute,
},
Elements: []dummyModule2ElementsConfiguration{
{
Name: "el1",
Gauge: 10,
}, {
Name: "el2",
Gauge: 11,
},
},
},
},
},
}
if diff := helpers.Diff(parsed, expected); diff != "" {
t.Errorf("Parse() (-got, +want):\n%s", diff)
}
@@ -442,7 +388,64 @@ modules:
t.Fatalf("Parse() error:\n%+v", err)
}
return parsed
})
},
// Expected configuration
struct {
Modules []dummyConfiguration
}{
Modules: []dummyConfiguration{
{
Module1: dummyModule1Configuration{
Listen: "127.0.0.1:8080",
Topic: "flows1",
Workers: 100,
},
Module2: dummyModule2Configuration{
MoreDetails: MoreDetails{
Stuff: "hello",
},
Details: dummyModule2DetailsConfiguration{
Workers: 1,
IntervalValue: time.Minute,
},
Elements: []dummyModule2ElementsConfiguration{
{
Name: "el1",
Gauge: 10,
}, {
Name: "el2",
Gauge: 11,
},
},
},
},
{
Module1: dummyModule1Configuration{
Listen: "127.0.0.1:8080",
Topic: "flows2",
Workers: 100,
},
Module2: dummyModule2Configuration{
MoreDetails: MoreDetails{
Stuff: "hello",
},
Details: dummyModule2DetailsConfiguration{
Workers: 1,
IntervalValue: time.Minute,
},
Elements: []dummyModule2ElementsConfiguration{
{
Name: "el1",
Gauge: 10,
}, {
Name: "el2",
Gauge: 11,
},
},
},
},
},
})
})
t.Run("with pointer", func(t *testing.T) {
try(t, func(c cmd.ConfigRelatedOptions, out *bytes.Buffer) any {
@@ -453,7 +456,63 @@ modules:
t.Fatalf("Parse() error:\n%+v", err)
}
return parsed
})
},
struct {
Modules []*dummyConfiguration
}{
Modules: []*dummyConfiguration{
{
Module1: dummyModule1Configuration{
Listen: "127.0.0.1:8080",
Topic: "flows1",
Workers: 100,
},
Module2: dummyModule2Configuration{
MoreDetails: MoreDetails{
Stuff: "hello",
},
Details: dummyModule2DetailsConfiguration{
Workers: 1,
IntervalValue: time.Minute,
},
Elements: []dummyModule2ElementsConfiguration{
{
Name: "el1",
Gauge: 10,
}, {
Name: "el2",
Gauge: 11,
},
},
},
},
{
Module1: dummyModule1Configuration{
Listen: "127.0.0.1:8080",
Topic: "flows2",
Workers: 100,
},
Module2: dummyModule2Configuration{
MoreDetails: MoreDetails{
Stuff: "hello",
},
Details: dummyModule2DetailsConfiguration{
Workers: 1,
IntervalValue: time.Minute,
},
Elements: []dummyModule2ElementsConfiguration{
{
Name: "el1",
Gauge: 10,
}, {
Name: "el2",
Gauge: 11,
},
},
},
},
},
})
})
}

View File

@@ -130,8 +130,8 @@ func TestRealClickHouse(t *testing.T) {
}
expected := []struct {
N uint64
M uint64
N uint64 `ch:"n"`
M uint64 `ch:"m"`
}{
{0, 1},
{1, 2},

View File

@@ -7,6 +7,8 @@ import (
"testing"
"akvorado/common/helpers"
"github.com/google/go-cmp/cmp/cmpopts"
)
type likeInt int
@@ -72,6 +74,7 @@ func TestPutCollision(t *testing.T) {
func TestTake(t *testing.T) {
p := NewPool[likeInt]()
diffOpt := cmpopts.EquateComparable(internValue[likeInt]{})
val1 := likeInt(10)
ref1 := p.Put(val1)
@@ -91,7 +94,7 @@ func TestTake(t *testing.T) {
{value: 22, refCount: 1, previous: 2, next: 4},
{value: 32, refCount: 1, previous: 3},
}
if diff := helpers.Diff(p.values, expectedValues, helpers.DiffUnexported); diff != "" {
if diff := helpers.Diff(p.values, expectedValues, diffOpt); diff != "" {
t.Fatalf("p.values (-got, +want):\n%s", diff)
}
@@ -104,7 +107,7 @@ func TestTake(t *testing.T) {
{value: 22, refCount: 0, previous: 2, next: 4}, // free
{value: 32, refCount: 1, previous: 2},
}
if diff := helpers.Diff(p.values, expectedValues, helpers.DiffUnexported); diff != "" {
if diff := helpers.Diff(p.values, expectedValues, diffOpt); diff != "" {
t.Fatalf("p.values (-got, +want):\n%s", diff)
}
@@ -120,7 +123,7 @@ func TestTake(t *testing.T) {
{value: 42, refCount: 1, previous: 4},
{value: 32, refCount: 1, previous: 2, next: 3},
}
if diff := helpers.Diff(p.values, expectedValues, helpers.DiffUnexported); diff != "" {
if diff := helpers.Diff(p.values, expectedValues, diffOpt); diff != "" {
t.Fatalf("p.values (-got, +want):\n%s", diff)
}
@@ -133,7 +136,7 @@ func TestTake(t *testing.T) {
{value: 42, refCount: 1, previous: 4},
{value: 32, refCount: 1, next: 3},
}
if diff := helpers.Diff(p.values, expectedValues, helpers.DiffUnexported); diff != "" {
if diff := helpers.Diff(p.values, expectedValues, diffOpt); diff != "" {
t.Fatalf("p.values (-got, +want):\n%s", diff)
}
@@ -146,7 +149,7 @@ func TestTake(t *testing.T) {
{value: 42, refCount: 1},
{value: 32, refCount: 0, next: 3}, // free
}
if diff := helpers.Diff(p.values, expectedValues, helpers.DiffUnexported); diff != "" {
if diff := helpers.Diff(p.values, expectedValues, diffOpt); diff != "" {
t.Fatalf("p.values (-got, +want):\n%s", diff)
}
@@ -159,7 +162,7 @@ func TestTake(t *testing.T) {
{value: 42, refCount: 0}, // free
{value: 32, refCount: 0, next: 3}, // free
}
if diff := helpers.Diff(p.values, expectedValues, helpers.DiffUnexported); diff != "" {
if diff := helpers.Diff(p.values, expectedValues, diffOpt); diff != "" {
t.Fatalf("p.values (-got, +want):\n%s", diff)
}

View File

@@ -236,7 +236,7 @@ func TestParametrizedConfig(t *testing.T) {
Expected: OuterConfiguration{
AA: "a1",
BB: "b1",
Config: InnerConfigurationType1{
Config: &InnerConfigurationType1{
CC: "c1",
DD: "d1",
},
@@ -256,7 +256,7 @@ func TestParametrizedConfig(t *testing.T) {
Expected: OuterConfiguration{
AA: "a2",
BB: "b2",
Config: InnerConfigurationType2{
Config: &InnerConfigurationType2{
CC: "c2",
EE: "e2",
},

View File

@@ -6,6 +6,7 @@ package helpers_test
import (
"net/netip"
"slices"
"strings"
"testing"
"github.com/gin-gonic/gin"
@@ -19,6 +20,7 @@ import (
func TestSubnetMapUnmarshalHook(t *testing.T) {
var nilMap map[string]string
cases := []struct {
Pos helpers.Pos
Description string
Input any
Tests map[string]string
@@ -26,20 +28,24 @@ func TestSubnetMapUnmarshalHook(t *testing.T) {
YAML any
}{
{
Pos: helpers.Mark(),
Description: "nil",
Input: nilMap,
Tests: map[string]string{
"::ffff:203.0.113.1": "",
},
YAML: map[string]string{},
}, {
Pos: helpers.Mark(),
Description: "empty",
Input: gin.H{},
Input: map[string]string{},
Tests: map[string]string{
"::ffff:203.0.113.1": "",
},
}, {
Pos: helpers.Mark(),
Description: "IPv4 subnet",
Input: gin.H{"203.0.113.0/24": "customer1"},
Input: map[string]string{"203.0.113.0/24": "customer1"},
Tests: map[string]string{
"::ffff:203.0.113.18": "customer1",
"::ffff:203.0.113.16": "customer1",
@@ -49,59 +55,69 @@ func TestSubnetMapUnmarshalHook(t *testing.T) {
"2001:db8:1::12": "",
},
}, {
Pos: helpers.Mark(),
Description: "IPv4 IP",
Input: gin.H{"203.0.113.1": "customer1"},
Input: map[string]string{"203.0.113.1": "customer1"},
Tests: map[string]string{
"::ffff:203.0.113.1": "customer1",
"2001:db8:1::12": "",
},
YAML: gin.H{"203.0.113.1/32": "customer1"},
YAML: map[string]string{"203.0.113.1/32": "customer1"},
}, {
Pos: helpers.Mark(),
Description: "IPv6 subnet",
Input: gin.H{"2001:db8:1::/64": "customer2"},
Input: map[string]string{"2001:db8:1::/64": "customer2"},
Tests: map[string]string{
"2001:db8:1::1": "customer2",
"2001:db8:1::2": "customer2",
"2001:db8:2::2": "",
},
}, {
Pos: helpers.Mark(),
Description: "IPv6-mapped-IPv4 subnet",
Input: gin.H{"::ffff:203.0.113.0/120": "customer2"},
Input: map[string]string{"::ffff:203.0.113.0/120": "customer2"},
Tests: map[string]string{
"::ffff:203.0.113.10": "customer2",
"::ffff:203.0.112.10": "",
},
YAML: gin.H{"203.0.113.0/24": "customer2"},
YAML: map[string]string{"203.0.113.0/24": "customer2"},
}, {
Pos: helpers.Mark(),
Description: "IPv6 IP",
Input: gin.H{"2001:db8:1::1": "customer2"},
Input: map[string]string{"2001:db8:1::1": "customer2"},
Tests: map[string]string{
"2001:db8:1::1": "customer2",
"2001:db8:1::2": "",
"2001:db8:2::2": "",
},
YAML: gin.H{"2001:db8:1::1/128": "customer2"},
YAML: map[string]string{"2001:db8:1::1/128": "customer2"},
}, {
Pos: helpers.Mark(),
Description: "Invalid subnet (1)",
Input: gin.H{"192.0.2.1/38": "customer"},
Input: map[string]string{"192.0.2.1/38": "customer"},
Error: true,
}, {
Pos: helpers.Mark(),
Description: "Invalid subnet (2)",
Input: gin.H{"192.0.2.1/255.0.255.0": "customer"},
Input: map[string]string{"192.0.2.1/255.0.255.0": "customer"},
Error: true,
}, {
Pos: helpers.Mark(),
Description: "Invalid subnet (3)",
Input: gin.H{"2001:db8::/1000": "customer"},
Input: map[string]string{"2001:db8::/1000": "customer"},
Error: true,
}, {
Pos: helpers.Mark(),
Description: "Invalid IP",
Input: gin.H{"200.33.300.1": "customer"},
Input: map[string]string{"200.33.300.1": "customer"},
Error: true,
}, {
Pos: helpers.Mark(),
Description: "Random key",
Input: gin.H{"kfgdjgkfj": "customer"},
Input: map[string]string{"kfgdjgkfj": "customer"},
Error: true,
}, {
Pos: helpers.Mark(),
Description: "Single value",
Input: "customer",
Tests: map[string]string{
@@ -115,11 +131,10 @@ func TestSubnetMapUnmarshalHook(t *testing.T) {
}
for _, tc := range cases {
if tc.YAML == nil {
if tc.Error {
tc.YAML = map[string]string{}
} else {
tc.YAML = tc.Input
}
tc.YAML = tc.Input
}
if tc.Tests == nil {
tc.Tests = map[string]string{}
}
t.Run(tc.Description, func(t *testing.T) {
var tree helpers.SubnetMap[string]
@@ -134,9 +149,11 @@ func TestSubnetMapUnmarshalHook(t *testing.T) {
}
err = decoder.Decode(tc.Input)
if err != nil && !tc.Error {
t.Fatalf("Decode() error:\n%+v", err)
t.Fatalf("%sDecode() error:\n%+v", tc.Pos, err)
} else if err == nil && tc.Error {
t.Fatal("Decode() did not return an error")
t.Fatalf("%sDecode() did not return an error", tc.Pos)
} else if tc.Error {
return
}
got := map[string]string{}
for k := range tc.Tests {
@@ -144,20 +161,20 @@ func TestSubnetMapUnmarshalHook(t *testing.T) {
got[k] = v
}
if diff := helpers.Diff(got, tc.Tests); diff != "" {
t.Fatalf("Decode() (-got, +want):\n%s", diff)
t.Fatalf("%sDecode() (-got, +want):\n%s", tc.Pos, diff)
}
// Try to unmarshal with YAML
buf, err := yaml.Marshal(tree)
if err != nil {
t.Fatalf("yaml.Marshal() error:\n%+v", err)
t.Fatalf("%syaml.Marshal() error:\n%+v", tc.Pos, err)
}
got = map[string]string{}
if err := yaml.Unmarshal(buf, &got); err != nil {
t.Fatalf("yaml.Unmarshal() error:\n%+v", err)
t.Fatalf("%syaml.Unmarshal() error:\n%+v", tc.Pos, err)
}
if diff := helpers.Diff(got, tc.YAML); diff != "" {
t.Fatalf("MarshalYAML() (-got, +want):\n%s", diff)
t.Fatalf("%sMarshalYAML() (-got, +want):\n%s", tc.Pos, diff)
}
})
}
@@ -171,7 +188,7 @@ func TestSubnetMapUnmarshalHookWithMapValue(t *testing.T) {
cases := []struct {
Pos helpers.Pos
Input gin.H
Expected gin.H
Expected any
}{
{
Pos: helpers.Mark(),
@@ -179,10 +196,10 @@ func TestSubnetMapUnmarshalHookWithMapValue(t *testing.T) {
"blip": "some",
"blop": "thing",
},
Expected: gin.H{
"::/0": gin.H{
"Blip": "some",
"Blop": "thing",
Expected: map[string]SomeStruct{
"::/0": {
Blip: "some",
Blop: "thing",
},
},
}, {
@@ -197,14 +214,14 @@ func TestSubnetMapUnmarshalHookWithMapValue(t *testing.T) {
"blop": "stuff",
},
},
Expected: gin.H{
"::/0": gin.H{
"Blip": "some",
"Blop": "thing",
Expected: map[string]SomeStruct{
"::/0": {
Blip: "some",
Blop: "thing",
},
"203.0.113.14/32": gin.H{
"Blip": "other",
"Blop": "stuff",
"203.0.113.14/32": {
Blip: "other",
Blop: "stuff",
},
},
},
@@ -717,3 +734,31 @@ func TestSubnetMapAllMaybeSorted(t *testing.T) {
}
})
}
func TestSubnetmapDiff(t *testing.T) {
got := helpers.MustNewSubnetMap(map[string]string{
"2001:db8::/64": "hello",
"::ffff:192.0.2.0/120": "bye",
})
expected := helpers.MustNewSubnetMap(map[string]string{
"2001:db8::/64": "hello",
"::ffff:192.0.2.0/120": "bye",
})
if diff := helpers.Diff(got, expected); diff != "" {
t.Fatalf("Diff():\n%+v", diff)
}
got.Set(netip.MustParsePrefix("2001:db8:1::/64"), "bye")
diffGot := helpers.Diff(got, expected)
diffGot = strings.ReplaceAll(diffGot, "\u00a0", " ")
diffExpected := ` (*helpers.SubnetMap[string])(Inverse(subnetmap.Transform, map[string]string{
"192.0.2.0/24": "bye",
- "2001:db8:1::/64": "bye",
"2001:db8::/64": "hello",
}))
`
if diff := helpers.Diff(diffGot, diffExpected); diff != "" {
t.Fatalf("Diff() (-got, +want):\n%+v", diff)
}
}

View File

@@ -141,7 +141,7 @@ func Mark() Pos {
// 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 fmt.Sprintf("%s:%d: ", p.file, p.line)
}
return ""
}

View File

@@ -10,6 +10,7 @@ import (
"testing"
"github.com/go-viper/mapstructure/v2"
"github.com/google/go-cmp/cmp"
"akvorado/common/helpers/yaml"
)
@@ -28,7 +29,7 @@ type ConfigurationDecodeCases []struct {
}
// TestConfigurationDecode helps decoding configuration. It also test decoding from YAML.
func TestConfigurationDecode(t *testing.T, cases ConfigurationDecodeCases, options ...DiffOption) {
func TestConfigurationDecode(t *testing.T, cases ConfigurationDecodeCases, options ...cmp.Option) {
t.Helper()
for _, tc := range cases {
for _, fromYAML := range []bool{false, true} {

View File

@@ -6,85 +6,28 @@
package helpers
import (
"fmt"
"net"
"net/netip"
"reflect"
"time"
"github.com/kylelemons/godebug/pretty"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
)
var prettyC = pretty.Config{
Diffable: true,
PrintStringers: false,
SkipZeroFields: true,
IncludeUnexported: false,
}
var diffCmpOptions cmp.Options
func formatByte(v any) string {
return fmt.Sprintf("0x%x", v)
}
func defaultPrettyFormatters() map[reflect.Type]any {
result := map[reflect.Type]any{
reflect.TypeOf(net.IP{}): fmt.Sprint,
reflect.TypeOf(netip.Addr{}): fmt.Sprint,
reflect.TypeOf(netip.Prefix{}): fmt.Sprint,
reflect.TypeOf(time.Time{}): fmt.Sprint,
reflect.TypeOf(SubnetMap[string]{}): fmt.Sprint,
reflect.TypeOf(SubnetMap[uint]{}): fmt.Sprint,
reflect.TypeOf(SubnetMap[uint16]{}): fmt.Sprint,
reflect.TypeOf(byte(0)): formatByte,
}
for t, fn := range nonDefaultPrettyFormatters {
result[t] = fn
}
return result
}
var nonDefaultPrettyFormatters = map[reflect.Type]any{}
// AddPrettyFormatter add a global pretty formatter. We cannot put everything in
// the default map due to cycles.
func AddPrettyFormatter(t reflect.Type, fn any) {
nonDefaultPrettyFormatters[t] = fn
}
// DiffOption changes the behavior of the Diff function.
type DiffOption struct {
kind int
// When this is a formatter
t reflect.Type
fn any
// RegisterCmpOption adds an option that will be used in all call to Diff().
func RegisterCmpOption(option cmp.Option) {
diffCmpOptions = append(diffCmpOptions, option)
}
// Diff return a diff of two objects. If no diff, an empty string is
// returned.
func Diff(a, b any, options ...DiffOption) string {
prettyC := prettyC
prettyC.Formatter = defaultPrettyFormatters()
for _, option := range options {
switch option.kind {
case DiffUnexported.kind:
prettyC.IncludeUnexported = true
case DiffZero.kind:
prettyC.SkipZeroFields = false
case DiffFormatter(nil, nil).kind:
prettyC.Formatter[option.t] = option.fn
}
}
return prettyC.Compare(a, b)
func Diff(a, b any, options ...cmp.Option) string {
options = append(options, diffCmpOptions...)
return cmp.Diff(a, b, options...)
}
var (
// DiffUnexported will display diff of unexported fields too.
DiffUnexported = DiffOption{kind: 1}
// DiffZero will include zero-field in diff
DiffZero = DiffOption{kind: 2}
)
// DiffFormatter adds a new formatter
func DiffFormatter(t reflect.Type, fn any) DiffOption {
return DiffOption{kind: 3, t: t, fn: fn}
func init() {
RegisterCmpOption(cmpopts.EquateComparable(netip.Addr{}))
RegisterCmpOption(cmpopts.EquateComparable(netip.Prefix{}))
RegisterCmpOption(cmpopts.EquateErrors())
}

View File

@@ -24,12 +24,12 @@ type HTTPEndpointCases []struct {
Method string
URL string
Header http.Header
JSONInput any
JSONInput gin.H
ContentType string
StatusCode int
FirstLines []string
JSONOutput any
JSONOutput gin.H
}
// TestHTTPEndpoints test a few HTTP endpoints
@@ -108,6 +108,9 @@ func TestHTTPEndpoints(t *testing.T, serverAddr net.Addr, cases HTTPEndpointCase
for reader.Scan() && len(got) < len(tc.FirstLines) {
got = append(got, reader.Text())
}
if tc.FirstLines == nil {
tc.FirstLines = []string{}
}
if diff := Diff(got, tc.FirstLines); diff != "" {
t.Errorf("%s%s %s (-got, +want):\n%s", tc.Pos, tc.Method, tc.URL, diff)
}
@@ -117,7 +120,18 @@ func TestHTTPEndpoints(t *testing.T, serverAddr net.Addr, cases HTTPEndpointCase
if err := decoder.Decode(&got); err != nil {
t.Fatalf("%s%s %s:\n%+v", tc.Pos, tc.Method, tc.URL, err)
}
if diff := Diff(got, tc.JSONOutput); diff != "" {
// Encode/decode expected to compare JSON stuff
var expected gin.H
expectedBytes, err := json.Marshal(tc.JSONOutput)
if err != nil {
t.Fatalf("json.Marshal() error:\n%+v", err)
}
if err := json.Unmarshal(expectedBytes, &expected); err != nil {
t.Fatalf("json.Unmarshal() error:\n%+v", err)
}
if diff := Diff(got, expected); diff != "" {
t.Fatalf("%s%s %s (-got, +want):\n%s", tc.Pos, tc.Method, tc.URL, diff)
}
}

View File

@@ -0,0 +1,23 @@
// SPDX-FileCopyrightText: 2022 Free Mobile
// SPDX-License-Identifier: AGPL-3.0-only
//go:build !release
package helpers
import "github.com/google/go-cmp/cmp"
// RegisterSubnetMapCmp register a subnetmap to work with cmp.Equal()/cmp.Diff()
func RegisterSubnetMapCmp[T any]() {
RegisterCmpOption(
cmp.Transformer("subnetmap.Transform",
func(sm *SubnetMap[T]) map[string]T {
return sm.ToMap()
}))
}
func init() {
RegisterSubnetMapCmp[uint16]()
RegisterSubnetMapCmp[uint]()
RegisterSubnetMapCmp[string]()
}

View File

@@ -9,8 +9,6 @@ import (
"akvorado/common/helpers"
"akvorado/common/helpers/yaml"
"github.com/gin-gonic/gin"
)
func TestUnmarshalWithIn(t *testing.T) {
@@ -19,14 +17,14 @@ func TestUnmarshalWithIn(t *testing.T) {
if err := yaml.UnmarshalWithInclude(fsys, "base.yaml", &got); err != nil {
t.Fatalf("UnmarshalWithInclude() error:\n%+v", err)
}
expected := gin.H{
"file1": gin.H{"name": "1.yaml"},
"file2": gin.H{"name": "2.yaml"},
"nested": gin.H{
"file1": gin.H{"name": "1.yaml"},
expected := map[string]any{
"file1": map[string]any{"name": "1.yaml"},
"file2": map[string]any{"name": "2.yaml"},
"nested": map[string]any{
"file1": map[string]any{"name": "1.yaml"},
},
"list1": []string{"el1", "el2", "el3"},
"list2": []any{gin.H{
"list1": []any{"el1", "el2", "el3"},
"list2": []any{map[string]any{
"protocol": "tcp",
"size": 1300,
}, "el2", "el3"},

View File

@@ -3,15 +3,14 @@
//go:build !release
package clickhouse
package pb
import (
"fmt"
"reflect"
"akvorado/common/helpers"
"github.com/google/go-cmp/cmp/cmpopts"
)
func init() {
helpers.AddPrettyFormatter(reflect.TypeOf(helpers.SubnetMap[NetworkAttributes]{}), fmt.Sprint)
helpers.RegisterCmpOption(cmpopts.IgnoreUnexported(RawFlow{}))
}

View File

@@ -4,8 +4,6 @@
package remotedatasource
import (
"fmt"
"reflect"
"testing"
"time"
@@ -100,5 +98,5 @@ func TestSourceDecode(t *testing.T) {
},
Error: true,
},
}, helpers.DiffFormatter(reflect.TypeOf(TransformQuery{}), fmt.Sprint), helpers.DiffZero)
})
}

View File

@@ -136,7 +136,7 @@ func TestSource(t *testing.T) {
handler := remoteDataHandler{
data: []remoteData{},
}
var expected []remoteData
expected := []remoteData{}
handler.fetcher, _ = New[remoteData](r, handler.UpdateData, "test", config)
handler.fetcher.Start()

View File

@@ -139,12 +139,12 @@ func TestHealthcheckHTTPHandler(t *testing.T) {
}
expected := gin.H{
"status": "error",
"details": gin.H{
"hc1": map[string]string{
"details": map[string]any{
"hc1": map[string]any{
"status": "ok",
"reason": "all well",
},
"hc2": map[string]string{
"hc2": map[string]any{
"status": "error",
"reason": "trying to be better",
},

View File

@@ -161,19 +161,23 @@ func (bf *FlowMessage) AppendUint(columnKey ColumnKey, value uint64) {
switch col := col.(type) {
case *proto.ColUInt64:
col.Append(value)
bf.appendDebug(columnKey, value)
case *proto.ColUInt32:
col.Append(uint32(value))
bf.appendDebug(columnKey, uint32(value))
case *proto.ColUInt16:
col.Append(uint16(value))
bf.appendDebug(columnKey, uint16(value))
case *proto.ColUInt8:
col.Append(uint8(value))
bf.appendDebug(columnKey, uint8(value))
case *proto.ColEnum8:
col.Append(proto.Enum8(value))
bf.appendDebug(columnKey, uint8(value))
default:
panic(fmt.Sprintf("unhandled uint type %q", col.Type()))
}
bf.batch.columnSet.Set(uint(columnKey))
bf.appendDebug(columnKey, value)
}
// AppendString adds a String value to the provided column

View File

@@ -6,11 +6,13 @@ package schema
import (
"net/netip"
"slices"
"strings"
"testing"
"akvorado/common/helpers"
"github.com/ClickHouse/ch-go/proto"
"github.com/google/go-cmp/cmp"
)
func TestAppendDefault(t *testing.T) {
@@ -50,10 +52,10 @@ func TestAppendBasics(t *testing.T) {
bf.AppendUint(ColumnPackets, 200)
expected := map[ColumnKey]any{
ColumnTimeReceived: 1000,
ColumnSamplingRate: 20000,
ColumnDstAS: 65000,
ColumnPackets: 100,
ColumnTimeReceived: uint32(1000),
ColumnSamplingRate: uint64(20000),
ColumnDstAS: uint32(65000),
ColumnPackets: uint64(100),
}
got := bf.OtherColumns
if diff := helpers.Diff(got, expected); diff != "" {
@@ -94,7 +96,7 @@ func TestAppendArrayUInt32Columns(t *testing.T) {
Offsets: proto.ColUInt64{3, 6},
Data: &proto.ColUInt32{65400, 65500, 65001, 65403, 65503, 65003},
}
if diff := helpers.Diff(got, expected); diff != "" {
if diff := helpers.Diff(got, &expected); diff != "" {
t.Errorf("AppendArrayUInt32 (-got, +want):\n%s", diff)
}
}
@@ -122,7 +124,7 @@ func TestAppendArrayUInt128Columns(t *testing.T) {
{High: (65401 << 32) + 100, Low: 201},
},
}
if diff := helpers.Diff(got, expected); diff != "" {
if diff := helpers.Diff(got, &expected); diff != "" {
t.Errorf("AppendArrayUInt128 (-got, +want):\n%s", diff)
}
}
@@ -142,10 +144,10 @@ func TestUndoUInt64(t *testing.T) {
expectedBytes := proto.ColUInt64{100}
expectedPackets := proto.ColUInt64{200}
if diff := helpers.Diff(bytesCol, expectedBytes); diff != "" {
if diff := helpers.Diff(bytesCol, &expectedBytes); diff != "" {
t.Errorf("Initial bytes column state (-got, +want):\n%s", diff)
}
if diff := helpers.Diff(packetsCol, expectedPackets); diff != "" {
if diff := helpers.Diff(packetsCol, &expectedPackets); diff != "" {
t.Errorf("Initial packets column state (-got, +want):\n%s", diff)
}
@@ -155,10 +157,10 @@ func TestUndoUInt64(t *testing.T) {
expectedBytesAfter := proto.ColUInt64{}
expectedPacketsAfter := proto.ColUInt64{}
if diff := helpers.Diff(bytesCol, expectedBytesAfter); diff != "" {
if diff := helpers.Diff(bytesCol, &expectedBytesAfter); diff != "" {
t.Errorf("Bytes column after undo (-got, +want):\n%s", diff)
}
if diff := helpers.Diff(packetsCol, expectedPacketsAfter); diff != "" {
if diff := helpers.Diff(packetsCol, &expectedPacketsAfter); diff != "" {
t.Errorf("Packets column after undo (-got, +want):\n%s", diff)
}
}
@@ -178,10 +180,10 @@ func TestUndoUInt32(t *testing.T) {
expectedSrc := proto.ColUInt32{65001}
expectedDst := proto.ColUInt32{65002}
if diff := helpers.Diff(srcCol, expectedSrc); diff != "" {
if diff := helpers.Diff(srcCol, &expectedSrc); diff != "" {
t.Errorf("Initial SrcAS column state (-got, +want):\n%s", diff)
}
if diff := helpers.Diff(dstCol, expectedDst); diff != "" {
if diff := helpers.Diff(dstCol, &expectedDst); diff != "" {
t.Errorf("Initial DstAS column state (-got, +want):\n%s", diff)
}
@@ -191,10 +193,10 @@ func TestUndoUInt32(t *testing.T) {
expectedSrcAfter := proto.ColUInt32{}
expectedDstAfter := proto.ColUInt32{}
if diff := helpers.Diff(srcCol, expectedSrcAfter); diff != "" {
if diff := helpers.Diff(srcCol, &expectedSrcAfter); diff != "" {
t.Errorf("SrcAS column after undo (-got, +want):\n%s", diff)
}
if diff := helpers.Diff(dstCol, expectedDstAfter); diff != "" {
if diff := helpers.Diff(dstCol, &expectedDstAfter); diff != "" {
t.Errorf("DstAS column after undo (-got, +want):\n%s", diff)
}
}
@@ -214,10 +216,10 @@ func TestUndoUInt16(t *testing.T) {
expectedSrc := proto.ColUInt16{80}
expectedDst := proto.ColUInt16{443}
if diff := helpers.Diff(srcCol, expectedSrc); diff != "" {
if diff := helpers.Diff(srcCol, &expectedSrc); diff != "" {
t.Errorf("Initial SrcPort column state (-got, +want):\n%s", diff)
}
if diff := helpers.Diff(dstCol, expectedDst); diff != "" {
if diff := helpers.Diff(dstCol, &expectedDst); diff != "" {
t.Errorf("Initial DstPort column state (-got, +want):\n%s", diff)
}
@@ -227,10 +229,10 @@ func TestUndoUInt16(t *testing.T) {
expectedSrcAfter := proto.ColUInt16{}
expectedDstAfter := proto.ColUInt16{}
if diff := helpers.Diff(srcCol, expectedSrcAfter); diff != "" {
if diff := helpers.Diff(srcCol, &expectedSrcAfter); diff != "" {
t.Errorf("SrcPort column after undo (-got, +want):\n%s", diff)
}
if diff := helpers.Diff(dstCol, expectedDstAfter); diff != "" {
if diff := helpers.Diff(dstCol, &expectedDstAfter); diff != "" {
t.Errorf("DstPort column after undo (-got, +want):\n%s", diff)
}
}
@@ -246,7 +248,7 @@ func TestUndoUInt8(t *testing.T) {
col := bf.batch.columns[ColumnSrcNetMask].(*proto.ColUInt8)
expected := proto.ColUInt8{6}
if diff := helpers.Diff(col, expected); diff != "" {
if diff := helpers.Diff(col, &expected); diff != "" {
t.Errorf("Initial Proto column state (-got, +want):\n%s", diff)
}
@@ -255,7 +257,7 @@ func TestUndoUInt8(t *testing.T) {
expectedAfter := proto.ColUInt8{}
if diff := helpers.Diff(col, expectedAfter); diff != "" {
if diff := helpers.Diff(col, &expectedAfter); diff != "" {
t.Errorf("Proto column after undo (-got, +want):\n%s", diff)
}
}
@@ -278,10 +280,10 @@ func TestUndoIPv6(t *testing.T) {
expectedSrc := proto.ColIPv6{srcAddr.As16()}
expectedDst := proto.ColIPv6{dstAddr.As16()}
if diff := helpers.Diff(srcCol, expectedSrc); diff != "" {
if diff := helpers.Diff(srcCol, &expectedSrc); diff != "" {
t.Errorf("Initial SrcAddr column state (-got, +want):\n%s", diff)
}
if diff := helpers.Diff(dstCol, expectedDst); diff != "" {
if diff := helpers.Diff(dstCol, &expectedDst); diff != "" {
t.Errorf("Initial DstAddr column state (-got, +want):\n%s", diff)
}
@@ -291,10 +293,10 @@ func TestUndoIPv6(t *testing.T) {
expectedSrcAfter := proto.ColIPv6{}
expectedDstAfter := proto.ColIPv6{}
if diff := helpers.Diff(srcCol, expectedSrcAfter); diff != "" {
if diff := helpers.Diff(srcCol, &expectedSrcAfter); diff != "" {
t.Errorf("SrcAddr column after undo (-got, +want):\n%s", diff)
}
if diff := helpers.Diff(dstCol, expectedDstAfter); diff != "" {
if diff := helpers.Diff(dstCol, &expectedDstAfter); diff != "" {
t.Errorf("DstAddr column after undo (-got, +want):\n%s", diff)
}
}
@@ -310,7 +312,7 @@ func TestUndoDateTime(t *testing.T) {
col := bf.batch.columns[ColumnTimeReceived].(*proto.ColDateTime)
expected := proto.ColDateTime{Data: []proto.DateTime{1000}}
if diff := helpers.Diff(col, expected); diff != "" {
if diff := helpers.Diff(col, &expected); diff != "" {
t.Errorf("Initial TimeReceived column state (-got, +want):\n%s", diff)
}
@@ -319,7 +321,7 @@ func TestUndoDateTime(t *testing.T) {
expectedAfter := proto.ColDateTime{Data: []proto.DateTime{}}
if diff := helpers.Diff(col, expectedAfter); diff != "" {
if diff := helpers.Diff(col, &expectedAfter); diff != "" {
t.Errorf("TimeReceived column after undo (-got, +want):\n%s", diff)
}
}
@@ -335,7 +337,7 @@ func TestUndoEnum8(t *testing.T) {
col := bf.batch.columns[ColumnInIfBoundary].(*proto.ColEnum8)
expected := proto.ColEnum8{proto.Enum8(InterfaceBoundaryExternal)}
if diff := helpers.Diff(col, expected); diff != "" {
if diff := helpers.Diff(col, &expected); diff != "" {
t.Errorf("Initial InIfBoundary column state (-got, +want):\n%s", diff)
}
@@ -344,7 +346,7 @@ func TestUndoEnum8(t *testing.T) {
expectedAfter := proto.ColEnum8{}
if diff := helpers.Diff(col, expectedAfter); diff != "" {
if diff := helpers.Diff(col, &expectedAfter); diff != "" {
t.Errorf("InIfBoundary column after undo (-got, +want):\n%s", diff)
}
}
@@ -364,10 +366,14 @@ func TestUndoLowCardinalityString(t *testing.T) {
expectedName := proto.ColLowCardinality[string]{Values: []string{"router1"}}
expectedRole := proto.ColLowCardinality[string]{Values: []string{"edge"}}
if diff := helpers.Diff(nameCol, expectedName); diff != "" {
diffOpt := cmp.Comparer(func(x, y proto.ColLowCardinality[string]) bool {
return slices.Compare(x.Values, y.Values) == 0
})
if diff := helpers.Diff(nameCol, &expectedName, diffOpt); diff != "" {
t.Errorf("Initial ExporterName column state (-got, +want):\n%s", diff)
}
if diff := helpers.Diff(roleCol, expectedRole); diff != "" {
if diff := helpers.Diff(roleCol, &expectedRole, diffOpt); diff != "" {
t.Errorf("Initial ExporterRole column state (-got, +want):\n%s", diff)
}
@@ -377,10 +383,10 @@ func TestUndoLowCardinalityString(t *testing.T) {
expectedNameAfter := proto.ColLowCardinality[string]{Values: []string{}}
expectedRoleAfter := proto.ColLowCardinality[string]{Values: []string{}}
if diff := helpers.Diff(nameCol, expectedNameAfter); diff != "" {
if diff := helpers.Diff(nameCol, &expectedNameAfter, diffOpt); diff != "" {
t.Errorf("ExporterName column after undo (-got, +want):\n%s", diff)
}
if diff := helpers.Diff(roleCol, expectedRoleAfter); diff != "" {
if diff := helpers.Diff(roleCol, &expectedRoleAfter, diffOpt); diff != "" {
t.Errorf("ExporterRole column after undo (-got, +want):\n%s", diff)
}
}
@@ -393,11 +399,17 @@ func TestUndoLowCardinalityIPv6(t *testing.T) {
addr := netip.MustParseAddr("2001:db8::1")
bf.AppendIPv6(ColumnExporterAddress, addr)
diffOpt := cmp.Comparer(func(x, y proto.ColLowCardinality[proto.IPv6]) bool {
return slices.CompareFunc(x.Values, y.Values, func(a, b proto.IPv6) int {
return strings.Compare(a.String(), b.String())
}) == 0
})
// Check we have the expected initial state
col := bf.batch.columns[ColumnExporterAddress].(*proto.ColLowCardinality[proto.IPv6])
expected := proto.ColLowCardinality[proto.IPv6]{Values: []proto.IPv6{addr.As16()}}
if diff := helpers.Diff(col, expected); diff != "" {
if diff := helpers.Diff(col, &expected, diffOpt); diff != "" {
t.Errorf("Initial ExporterAddress column state (-got, +want):\n%s", diff)
}
@@ -406,7 +418,7 @@ func TestUndoLowCardinalityIPv6(t *testing.T) {
expectedAfter := proto.ColLowCardinality[proto.IPv6]{Values: []proto.IPv6{}}
if diff := helpers.Diff(col, expectedAfter); diff != "" {
if diff := helpers.Diff(col, &expectedAfter, diffOpt); diff != "" {
t.Errorf("ExporterAddress column after undo (-got, +want):\n%s", diff)
}
}
@@ -593,11 +605,11 @@ func TestBuildProtoInput(t *testing.T) {
// Let's compare a subset
expected := proto.Input{
{Name: "TimeReceived", Data: proto.ColDateTime{Data: []proto.DateTime{1002, 1003}}},
{Name: "SrcAS", Data: proto.ColUInt32{65000, 65001}},
{Name: "DstAS", Data: proto.ColUInt32{0, 0}},
{Name: "Bytes", Data: proto.ColUInt64{2000, 202}},
{Name: "Packets", Data: proto.ColUInt64{30, 3}},
{Name: "TimeReceived", Data: &proto.ColDateTime{Data: []proto.DateTime{1002, 1003}}},
{Name: "SrcAS", Data: &proto.ColUInt32{65000, 65001}},
{Name: "DstAS", Data: &proto.ColUInt32{0, 0}},
{Name: "Bytes", Data: &proto.ColUInt64{2000, 202}},
{Name: "Packets", Data: &proto.ColUInt64{30, 3}},
}
got = slices.DeleteFunc(got, func(col proto.InputColumn) bool {
return !slices.Contains([]string{"TimeReceived", "SrcAS", "DstAS", "Packets", "Bytes"}, col.Name)

View File

@@ -7,6 +7,9 @@ import (
"testing"
"akvorado/common/helpers"
"github.com/bits-and-blooms/bitset"
"github.com/google/go-cmp/cmp"
)
func TestFlowsClickHouse(t *testing.T) {
@@ -35,7 +38,11 @@ func TestFinalizeTwice(t *testing.T) {
c := NewMock(t)
oldSchema := c.Schema
newSchema := c.finalize()
if diff := helpers.Diff(oldSchema, newSchema, helpers.DiffUnexported); diff != "" {
if diff := helpers.Diff(oldSchema, newSchema,
cmp.AllowUnexported(Schema{}),
cmp.Comparer(func(x, y bitset.BitSet) bool {
return x.Equal(&y)
})); diff != "" {
t.Fatalf("finalize() (-old, +new):\n%s", diff)
}
}

View File

@@ -160,29 +160,29 @@ func TestInsertMemory(t *testing.T) {
"SamplingRate": "20000",
"ExporterAddress": "::ffff:203.0.113.14",
"ExporterName": "router1.example.net",
"SrcAS": 65000,
"DstAS": 12322,
"SrcAS": float64(65000),
"DstAS": float64(12322),
"Bytes": "20",
"Packets": "3",
"InIfBoundary": "internal",
"OutIfBoundary": "external",
"InIfSpeed": 10000,
"EType": helpers.ETypeIPv4,
"InIfSpeed": float64(10000),
"EType": float64(helpers.ETypeIPv4),
}, {
"TimeReceived": "1970-01-01 00:16:41",
"SamplingRate": "20000",
"ExporterAddress": "::ffff:203.0.113.14",
"ExporterName": "router1.example.net",
"SrcAS": 12322,
"DstAS": 65000,
"SrcAS": float64(12322),
"DstAS": float64(65000),
"Bytes": "200",
"Packets": "3",
"InIfBoundary": "external",
"OutIfBoundary": "undefined",
"OutIfSpeed": 10000,
"EType": helpers.ETypeIPv4,
"DstASPath": []uint32{65400, 65500, 65001},
"DstLargeCommunities": []string{
"OutIfSpeed": float64(10000),
"EType": float64(helpers.ETypeIPv4),
"DstASPath": []any{float64(65400), float64(65500), float64(65001)},
"DstLargeCommunities": []any{
"1206435509165107881967816", // 65401:100:200
"1206435509165107881967817", // 65401:100:201
},

View File

@@ -6,11 +6,11 @@
package schema
import (
"fmt"
"reflect"
"testing"
"akvorado/common/helpers"
"github.com/google/go-cmp/cmp/cmpopts"
)
var debug = true
@@ -44,5 +44,5 @@ func (c *Component) EnableAllColumns() *Component {
}
func init() {
helpers.AddPrettyFormatter(reflect.TypeOf(ColumnBytes), fmt.Sprint)
helpers.RegisterCmpOption(cmpopts.IgnoreUnexported(FlowMessage{}))
}

View File

@@ -351,7 +351,6 @@ output provider */ = 'telia'`,
s = s.EnableAllColumns()
for _, tc := range cases {
tc.MetaIn.Schema = s
tc.MetaOut.Schema = tc.MetaIn.Schema
got, err := Parse("", []byte(tc.Input), GlobalStore("meta", &tc.MetaIn))
if err != nil {
t.Errorf("Parse(%q) error:\n%+v", tc.Input, err)
@@ -397,7 +396,6 @@ func TestValidMaterializedFilter(t *testing.T) {
cs.ClickHouseMaterialized = true
tc.MetaIn.Schema = s
tc.MetaOut.Schema = tc.MetaIn.Schema
got, err := Parse("", []byte(tc.Input), GlobalStore("meta", &tc.MetaIn))
if err != nil {
t.Errorf("Parse(%q) error:\n%+v", tc.Input, err)

16
console/filter/tests.go Normal file
View File

@@ -0,0 +1,16 @@
// SPDX-FileCopyrightText: 2025 Free Mobile
// SPDX-License-Identifier: AGPL-3.0-only
//go:build !release
package filter
import (
"akvorado/common/helpers"
"github.com/google/go-cmp/cmp/cmpopts"
)
func init() {
helpers.RegisterCmpOption(cmpopts.IgnoreFields(Meta{}, "Schema"))
}

View File

@@ -46,6 +46,8 @@ func TestGraphLineInputReverseDirection(t *testing.T) {
},
Points: 100,
}
input.Filter.Validate(input.schema)
expected.Filter.Validate(input.schema)
query.Columns(input.Dimensions).Validate(input.schema)
query.Columns(expected.Dimensions).Validate(input.schema)
got := input.reverseDirection()

View File

@@ -39,6 +39,11 @@ func (qc Column) String() string {
return qc.name
}
// Equal returns true iff two columns have the same name.
func (qc Column) Equal(oqc Column) bool {
return qc.name == oqc.name
}
// MarshalText turns a column into a string.
func (qc Column) MarshalText() ([]byte, error) {
return []byte(qc.name), nil

View File

@@ -4,8 +4,6 @@
package query_test
import (
"fmt"
"reflect"
"testing"
"akvorado/common/helpers"
@@ -38,7 +36,7 @@ func TestUnmarshalQueryColumn(t *testing.T) {
if err != nil {
continue
}
if diff := helpers.Diff(qc.Key(), tc.Expected, helpers.DiffFormatter(reflect.TypeOf(schema.ColumnBytes), fmt.Sprint)); diff != "" {
if diff := helpers.Diff(qc.Key(), tc.Expected); diff != "" {
t.Fatalf("UnmarshalText(%q) (-got, +want):\n%s", tc.Input, diff)
}
}
@@ -145,7 +143,7 @@ func TestReverseDirection(t *testing.T) {
query.NewColumn("ExporterName"),
query.NewColumn("OutIfProvider"),
}
if diff := helpers.Diff(columns, expected, helpers.DiffFormatter(reflect.TypeOf(query.Column{}), fmt.Sprint)); diff != "" {
if diff := helpers.Diff(columns, expected); diff != "" {
t.Fatalf("Reverse() (-got, +want):\n%s", diff)
}
}

View File

@@ -34,6 +34,11 @@ func (qf Filter) String() string {
return qf.filter
}
// Equal tells if two filters are equal.
func (qf Filter) Equal(oqf Filter) bool {
return qf.filter == oqf.filter
}
// MarshalText turns a filter into a string.
func (qf Filter) MarshalText() ([]byte, error) {
return []byte(qf.filter), nil

View File

@@ -9,6 +9,8 @@ import (
"testing"
"github.com/benbjohnson/clock"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"akvorado/common/clickhousedb"
"akvorado/common/clickhousedb/mocks"
@@ -43,3 +45,8 @@ func NewMock(t *testing.T, config Configuration) (*Component, *httpserver.Compon
helpers.StartStop(t, c)
return c, h, mockConn, mockClock
}
func init() {
helpers.RegisterCmpOption(cmpopts.IgnoreUnexported(graphCommonHandlerInput{}))
helpers.RegisterCmpOption(cmp.AllowUnexported(graphLineHandlerInput{}))
}

View File

@@ -129,13 +129,13 @@ func TestGetNetFlowData(t *testing.T) {
SrcNetMask: 24,
DstNetMask: 23,
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 1500,
schema.ColumnPackets: 1,
schema.ColumnEType: helpers.ETypeIPv4,
schema.ColumnProto: 6,
schema.ColumnSrcPort: 443,
schema.ColumnDstPort: 34974,
schema.ColumnForwardingStatus: 64,
schema.ColumnBytes: uint64(1500),
schema.ColumnPackets: uint64(1),
schema.ColumnEType: uint32(helpers.ETypeIPv4),
schema.ColumnProto: uint32(6),
schema.ColumnSrcPort: uint16(443),
schema.ColumnDstPort: uint16(34974),
schema.ColumnForwardingStatus: uint32(64),
},
},
{
@@ -150,13 +150,13 @@ func TestGetNetFlowData(t *testing.T) {
SrcNetMask: 24,
DstNetMask: 24,
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 1339,
schema.ColumnPackets: 1,
schema.ColumnEType: helpers.ETypeIPv4,
schema.ColumnProto: 6,
schema.ColumnSrcPort: 443,
schema.ColumnDstPort: 33199,
schema.ColumnForwardingStatus: 64,
schema.ColumnBytes: uint64(1339),
schema.ColumnPackets: uint64(1),
schema.ColumnEType: uint32(helpers.ETypeIPv4),
schema.ColumnProto: uint32(6),
schema.ColumnSrcPort: uint16(443),
schema.ColumnDstPort: uint16(33199),
schema.ColumnForwardingStatus: uint32(64),
},
},
{
@@ -171,13 +171,13 @@ func TestGetNetFlowData(t *testing.T) {
SrcNetMask: 48,
DstNetMask: 48,
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 1300,
schema.ColumnPackets: 1,
schema.ColumnEType: helpers.ETypeIPv6,
schema.ColumnProto: 6,
schema.ColumnSrcPort: 33179,
schema.ColumnDstPort: 443,
schema.ColumnForwardingStatus: 64,
schema.ColumnBytes: uint64(1300),
schema.ColumnPackets: uint64(1),
schema.ColumnEType: uint32(helpers.ETypeIPv6),
schema.ColumnProto: uint32(6),
schema.ColumnSrcPort: uint16(33179),
schema.ColumnDstPort: uint16(443),
schema.ColumnForwardingStatus: uint32(64),
},
},
}

View File

@@ -70,11 +70,11 @@ func TestSNMPServer(t *testing.T) {
Type: gosnmp.OctetString,
}, {
Name: ".1.3.6.1.2.1.31.1.1.1.15.1",
Value: 10000,
Value: uint(10000),
Type: gosnmp.Gauge32,
}, {
Name: ".1.3.6.1.2.1.31.1.1.1.15.2",
Value: 10000,
Value: uint(10000),
Type: gosnmp.Gauge32,
}, {
Name: ".1.3.6.1.2.1.31.1.1.1.18.1",

3
go.mod
View File

@@ -22,12 +22,12 @@ require (
github.com/go-playground/validator/v10 v10.20.0
github.com/go-redis/redis/v8 v8.11.5
github.com/go-viper/mapstructure/v2 v2.4.0
github.com/google/go-cmp v0.7.0
github.com/google/gopacket v1.1.19
github.com/gosnmp/gosnmp v1.42.1
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0
github.com/hashicorp/go-version v1.7.0
github.com/itchyny/gojq v0.12.17
github.com/kylelemons/godebug v1.1.0
github.com/mattn/go-isatty v0.0.20
github.com/netsampler/goflow2/v2 v2.2.3
github.com/openconfig/gnmi v0.14.0
@@ -111,7 +111,6 @@ require (
github.com/goccy/go-json v0.10.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/licensecheck v0.3.1 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.6.0 // indirect

View File

@@ -22,7 +22,7 @@ func TestFileInput(t *testing.T) {
configuration.Paths = []string{path.Join("testdata", "file1.txt"), path.Join("testdata", "file2.txt")}
done := make(chan bool)
expected := []pb.RawFlow{
expected := []*pb.RawFlow{
{
Payload: []byte("hello world!\n"),
SourceAddress: net.ParseIP("127.0.0.1").To16(),

View File

@@ -4,8 +4,6 @@
package clickhouse
import (
"fmt"
"reflect"
"testing"
"github.com/gin-gonic/gin"
@@ -16,46 +14,53 @@ import (
func TestNetworkNamesUnmarshalHook(t *testing.T) {
helpers.TestConfigurationDecode(t, helpers.ConfigurationDecodeCases{
{
Pos: helpers.Mark(),
Description: "nil",
Initial: func() any { return helpers.SubnetMap[NetworkAttributes]{} },
Initial: func() any { return &helpers.SubnetMap[NetworkAttributes]{} },
Configuration: func() any { return nil },
Expected: helpers.SubnetMap[NetworkAttributes]{},
Expected: &helpers.SubnetMap[NetworkAttributes]{},
}, {
Pos: helpers.Mark(),
Description: "empty",
Initial: func() any { return helpers.SubnetMap[NetworkAttributes]{} },
Initial: func() any { return &helpers.SubnetMap[NetworkAttributes]{} },
Configuration: func() any { return gin.H{} },
Expected: helpers.SubnetMap[NetworkAttributes]{},
Expected: &helpers.SubnetMap[NetworkAttributes]{},
}, {
Pos: helpers.Mark(),
Description: "IPv4",
Initial: func() any { return helpers.SubnetMap[NetworkAttributes]{} },
Initial: func() any { return &helpers.SubnetMap[NetworkAttributes]{} },
Configuration: func() any { return gin.H{"203.0.113.0/24": gin.H{"name": "customer"}} },
Expected: helpers.MustNewSubnetMap(map[string]NetworkAttributes{
"::ffff:203.0.113.0/120": {Name: "customer"},
}),
}, {
Pos: helpers.Mark(),
Description: "IPv6",
Initial: func() any { return helpers.SubnetMap[NetworkAttributes]{} },
Initial: func() any { return &helpers.SubnetMap[NetworkAttributes]{} },
Configuration: func() any { return gin.H{"2001:db8:1::/64": gin.H{"name": "customer"}} },
Expected: helpers.MustNewSubnetMap(map[string]NetworkAttributes{
"2001:db8:1::/64": {Name: "customer"},
}),
}, {
Pos: helpers.Mark(),
Description: "IPv4 subnet (compatibility)",
Initial: func() any { return helpers.SubnetMap[NetworkAttributes]{} },
Initial: func() any { return &helpers.SubnetMap[NetworkAttributes]{} },
Configuration: func() any { return gin.H{"203.0.113.0/24": "customer"} },
Expected: helpers.MustNewSubnetMap(map[string]NetworkAttributes{
"::ffff:203.0.113.0/120": {Name: "customer"},
}),
}, {
Pos: helpers.Mark(),
Description: "IPv6 subnet (compatibility)",
Initial: func() any { return helpers.SubnetMap[NetworkAttributes]{} },
Initial: func() any { return &helpers.SubnetMap[NetworkAttributes]{} },
Configuration: func() any { return gin.H{"2001:db8:1::/64": "customer"} },
Expected: helpers.MustNewSubnetMap(map[string]NetworkAttributes{
"2001:db8:1::/64": {Name: "customer"},
}),
}, {
Pos: helpers.Mark(),
Description: "all attributes",
Initial: func() any { return helpers.SubnetMap[NetworkAttributes]{} },
Initial: func() any { return &helpers.SubnetMap[NetworkAttributes]{} },
Configuration: func() any {
return gin.H{"203.0.113.0/24": gin.H{
"name": "customer1",
@@ -73,17 +78,19 @@ func TestNetworkNamesUnmarshalHook(t *testing.T) {
Tenant: "mobile",
}}),
}, {
Pos: helpers.Mark(),
Description: "Invalid subnet (1)",
Initial: func() any { return helpers.SubnetMap[NetworkAttributes]{} },
Initial: func() any { return &helpers.SubnetMap[NetworkAttributes]{} },
Configuration: func() any { return gin.H{"192.0.2.1/38": "customer"} },
Error: true,
}, {
Pos: helpers.Mark(),
Description: "Invalid subnet (2)",
Initial: func() any { return helpers.SubnetMap[NetworkAttributes]{} },
Initial: func() any { return &helpers.SubnetMap[NetworkAttributes]{} },
Configuration: func() any { return gin.H{"192.0.2.1/255.0.255.0": "customer"} },
Error: true,
},
}, helpers.DiffFormatter(reflect.TypeOf(helpers.SubnetMap[NetworkAttributes]{}), fmt.Sprint))
})
}
func TestDefaultConfiguration(t *testing.T) {
@@ -92,3 +99,7 @@ func TestDefaultConfiguration(t *testing.T) {
t.Fatalf("validate.Struct() error:\n%+v", err)
}
}
func init() {
helpers.RegisterSubnetMapCmp[NetworkAttributes]()
}

View File

@@ -23,9 +23,9 @@ type Configuration struct {
// ClassifierCacheDuration defines the default TTL for classifier cache
ClassifierCacheDuration time.Duration `validate:"min=1s"`
// DefaultSamplingRate defines the default sampling rate to use when the information is missing
DefaultSamplingRate helpers.SubnetMap[uint]
DefaultSamplingRate *helpers.SubnetMap[uint]
// OverrideSamplingRate defines a sampling rate to use instead of the received on
OverrideSamplingRate helpers.SubnetMap[uint]
OverrideSamplingRate *helpers.SubnetMap[uint]
// ASNProviders defines the source used to get AS numbers
ASNProviders []ASNProvider `validate:"dive"`
// NetProviders defines the source used to get Prefix/Network Information

View File

@@ -58,8 +58,8 @@ func TestEnrich(t *testing.T) {
schema.ColumnOutIfName: "Gi0/0/200",
schema.ColumnInIfDescription: "Interface 100",
schema.ColumnOutIfDescription: "Interface 200",
schema.ColumnInIfSpeed: 1000,
schema.ColumnOutIfSpeed: 1000,
schema.ColumnInIfSpeed: uint32(1000),
schema.ColumnOutIfSpeed: uint32(1000),
},
},
},
@@ -89,8 +89,8 @@ func TestEnrich(t *testing.T) {
schema.ColumnOutIfName: "Gi0/0/200",
schema.ColumnInIfDescription: "Interface 100",
schema.ColumnOutIfDescription: "Interface 200",
schema.ColumnInIfSpeed: 1000,
schema.ColumnOutIfSpeed: 1000,
schema.ColumnInIfSpeed: uint32(1000),
schema.ColumnOutIfSpeed: uint32(1000),
},
},
},
@@ -115,8 +115,8 @@ func TestEnrich(t *testing.T) {
schema.ColumnOutIfName: "Gi0/0/200",
schema.ColumnInIfDescription: "Interface 100",
schema.ColumnOutIfDescription: "Interface 200",
schema.ColumnInIfSpeed: 1000,
schema.ColumnOutIfSpeed: 1000,
schema.ColumnInIfSpeed: uint32(1000),
schema.ColumnOutIfSpeed: uint32(1000),
},
},
},
@@ -145,8 +145,8 @@ func TestEnrich(t *testing.T) {
schema.ColumnOutIfName: "Gi0/0/200",
schema.ColumnInIfDescription: "Interface 100",
schema.ColumnOutIfDescription: "Interface 200",
schema.ColumnInIfSpeed: 1000,
schema.ColumnOutIfSpeed: 1000,
schema.ColumnInIfSpeed: uint32(1000),
schema.ColumnOutIfSpeed: uint32(1000),
},
},
},
@@ -181,8 +181,8 @@ func TestEnrich(t *testing.T) {
schema.ColumnOutIfName: "Gi0/0/200",
schema.ColumnInIfDescription: "Interface 100",
schema.ColumnOutIfDescription: "Interface 200",
schema.ColumnInIfSpeed: 1000,
schema.ColumnOutIfSpeed: 1000,
schema.ColumnInIfSpeed: uint32(1000),
schema.ColumnOutIfSpeed: uint32(1000),
},
},
},
@@ -214,8 +214,8 @@ func TestEnrich(t *testing.T) {
schema.ColumnOutIfName: "Gi0/0/200",
schema.ColumnInIfDescription: "Interface 100",
schema.ColumnOutIfDescription: "Interface 200",
schema.ColumnInIfSpeed: 1000,
schema.ColumnOutIfSpeed: 1000,
schema.ColumnInIfSpeed: uint32(1000),
schema.ColumnOutIfSpeed: uint32(1000),
},
},
},
@@ -282,8 +282,8 @@ func TestEnrich(t *testing.T) {
schema.ColumnOutIfName: "Gi0/0/200",
schema.ColumnInIfDescription: "Interface 100",
schema.ColumnOutIfDescription: "Interface 200",
schema.ColumnInIfSpeed: 1000,
schema.ColumnOutIfSpeed: 1000,
schema.ColumnInIfSpeed: uint32(1000),
schema.ColumnOutIfSpeed: uint32(1000),
},
},
},
@@ -314,8 +314,8 @@ func TestEnrich(t *testing.T) {
schema.ColumnOutIfName: "Gi0/0/200",
schema.ColumnInIfDescription: "Interface 100",
schema.ColumnOutIfDescription: "Super Speed",
schema.ColumnInIfSpeed: 1000,
schema.ColumnOutIfSpeed: 1000,
schema.ColumnInIfSpeed: uint32(1000),
schema.ColumnOutIfSpeed: uint32(1000),
},
},
},
@@ -349,8 +349,8 @@ func TestEnrich(t *testing.T) {
schema.ColumnOutIfName: "Gi0/0/200.300",
schema.ColumnInIfDescription: "Interface 100",
schema.ColumnOutIfDescription: "Interface 200",
schema.ColumnInIfSpeed: 1000,
schema.ColumnOutIfSpeed: 1000,
schema.ColumnInIfSpeed: uint32(1000),
schema.ColumnOutIfSpeed: uint32(1000),
},
},
},
@@ -385,10 +385,10 @@ ClassifyProviderRegex(Interface.Description, "^Transit: ([^ ]+)", "$1")`,
schema.ColumnOutIfName: "Gi0/0/200",
schema.ColumnInIfDescription: "Interface 100",
schema.ColumnOutIfDescription: "Interface 200",
schema.ColumnInIfSpeed: 1000,
schema.ColumnOutIfSpeed: 1000,
schema.ColumnInIfBoundary: schema.InterfaceBoundaryInternal,
schema.ColumnOutIfBoundary: schema.InterfaceBoundaryInternal,
schema.ColumnInIfSpeed: uint32(1000),
schema.ColumnOutIfSpeed: uint32(1000),
schema.ColumnInIfBoundary: uint8(schema.InterfaceBoundaryInternal),
schema.ColumnOutIfBoundary: uint8(schema.InterfaceBoundaryInternal),
},
},
},
@@ -419,10 +419,10 @@ ClassifyProviderRegex(Interface.Description, "^Transit: ([^ ]+)", "$1")`,
schema.ColumnOutIfName: "Gi0/0/200",
schema.ColumnInIfDescription: "Interface 100",
schema.ColumnOutIfDescription: "Interface 200",
schema.ColumnInIfSpeed: 1000,
schema.ColumnOutIfSpeed: 1000,
schema.ColumnInIfBoundary: 2, // Internal
schema.ColumnOutIfBoundary: 2,
schema.ColumnInIfSpeed: uint32(1000),
schema.ColumnOutIfSpeed: uint32(1000),
schema.ColumnInIfBoundary: uint8(2), // Internal
schema.ColumnOutIfBoundary: uint8(2),
},
},
},
@@ -453,8 +453,8 @@ ClassifyProviderRegex(Interface.Description, "^Transit: ([^ ]+)", "$1")`,
schema.ColumnOutIfName: "Gi0/0/200",
schema.ColumnInIfDescription: "Interface 100",
schema.ColumnOutIfDescription: "Interface 200",
schema.ColumnInIfSpeed: 1000,
schema.ColumnOutIfSpeed: 1000,
schema.ColumnInIfSpeed: uint32(1000),
schema.ColumnOutIfSpeed: uint32(1000),
schema.ColumnInIfProvider: "telia",
schema.ColumnOutIfProvider: "telia",
},
@@ -488,14 +488,14 @@ ClassifyProviderRegex(Interface.Description, "^Transit: ([^ ]+)", "$1")`,
schema.ColumnOutIfName: "Gi0/0/200",
schema.ColumnInIfDescription: "Interface 100",
schema.ColumnOutIfDescription: "Interface 200",
schema.ColumnInIfSpeed: 1000,
schema.ColumnOutIfSpeed: 1000,
schema.ColumnInIfSpeed: uint32(1000),
schema.ColumnOutIfSpeed: uint32(1000),
schema.ColumnInIfConnectivity: "p100",
schema.ColumnOutIfConnectivity: "core",
schema.ColumnInIfProvider: "othello",
schema.ColumnOutIfProvider: "othello",
schema.ColumnInIfBoundary: 1, // external
schema.ColumnOutIfBoundary: 2, // internal
schema.ColumnInIfBoundary: uint8(1), // external
schema.ColumnOutIfBoundary: uint8(2), // internal
},
},
},
@@ -532,14 +532,14 @@ ClassifyProviderRegex(Interface.Description, "^Transit: ([^ ]+)", "$1")`,
schema.ColumnOutIfName: "Gi0/0/2010",
schema.ColumnInIfDescription: "Interface 1010",
schema.ColumnOutIfDescription: "Interface 2010",
schema.ColumnInIfSpeed: 1000,
schema.ColumnOutIfSpeed: 1000,
schema.ColumnInIfSpeed: uint32(1000),
schema.ColumnOutIfSpeed: uint32(1000),
schema.ColumnInIfConnectivity: "p1010",
schema.ColumnOutIfConnectivity: "metadata connectivity",
schema.ColumnInIfProvider: "othello",
schema.ColumnOutIfProvider: "metadata provider",
schema.ColumnInIfBoundary: schema.InterfaceBoundaryExternal,
schema.ColumnOutIfBoundary: schema.InterfaceBoundaryExternal,
schema.ColumnInIfBoundary: uint8(schema.InterfaceBoundaryExternal),
schema.ColumnOutIfBoundary: uint8(schema.InterfaceBoundaryExternal),
},
},
},
@@ -573,8 +573,8 @@ ClassifyProviderRegex(Interface.Description, "^Transit: ([^ ]+)", "$1")`,
schema.ColumnOutIfName: "Gi0/0/200",
schema.ColumnInIfDescription: "Interface 100",
schema.ColumnOutIfDescription: "Interface 200",
schema.ColumnInIfSpeed: 1000,
schema.ColumnOutIfSpeed: 1000,
schema.ColumnInIfSpeed: uint32(1000),
schema.ColumnOutIfSpeed: uint32(1000),
schema.ColumnDstASPath: []uint32{64200, 1299, 174},
schema.ColumnDstCommunities: []uint32{100, 200, 400},
schema.ColumnDstLargeCommunities: []schema.UInt128{

View File

@@ -83,12 +83,12 @@ func TestCore(t *testing.T) {
SrcAddr: netip.MustParseAddr("::ffff:67.43.156.77"),
DstAddr: netip.MustParseAddr("::ffff:2.125.160.216"),
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 6765,
schema.ColumnPackets: 4,
schema.ColumnEType: 0x800,
schema.ColumnProto: 6,
schema.ColumnSrcPort: 8534,
schema.ColumnDstPort: 80,
schema.ColumnBytes: uint64(6765),
schema.ColumnPackets: uint64(4),
schema.ColumnEType: uint32(0x800),
schema.ColumnProto: uint32(6),
schema.ColumnSrcPort: uint16(8534),
schema.ColumnDstPort: uint16(80),
},
}
return msg
@@ -102,8 +102,8 @@ func TestCore(t *testing.T) {
expected.OtherColumns[schema.ColumnOutIfName] = fmt.Sprintf("Gi0/0/%d", out)
expected.OtherColumns[schema.ColumnInIfDescription] = fmt.Sprintf("Interface %d", in)
expected.OtherColumns[schema.ColumnOutIfDescription] = fmt.Sprintf("Interface %d", out)
expected.OtherColumns[schema.ColumnInIfSpeed] = 1000
expected.OtherColumns[schema.ColumnOutIfSpeed] = 1000
expected.OtherColumns[schema.ColumnInIfSpeed] = uint32(1000)
expected.OtherColumns[schema.ColumnOutIfSpeed] = uint32(1000)
expected.OtherColumns[schema.ColumnExporterName] = strings.ReplaceAll(exporter, ".", "_")
return expected
}
@@ -259,34 +259,34 @@ func TestCore(t *testing.T) {
t.Fatalf("GET /api/v0/outlet/flows error while reading body:\n%+v", err)
}
expected := gin.H{
"TimeReceived": 200,
"SamplingRate": 1000,
"TimeReceived": float64(200),
"SamplingRate": float64(1000),
"ExporterAddress": "::ffff:192.0.2.142",
"SrcAddr": "::ffff:67.43.156.77",
"DstAddr": "::ffff:2.125.160.216",
"SrcAS": 0, // no geoip enrich anymore
"InIf": 434,
"OutIf": 677,
"SrcAS": float64(0), // no geoip enrich anymore
"InIf": float64(434),
"OutIf": float64(677),
"NextHop": "",
"SrcNetMask": 0,
"DstNetMask": 0,
"SrcVlan": 0,
"DstVlan": 0,
"DstAS": 0,
"OtherColumns": gin.H{
"SrcNetMask": float64(0),
"DstNetMask": float64(0),
"SrcVlan": float64(0),
"DstVlan": float64(0),
"DstAS": float64(0),
"OtherColumns": map[string]any{
"ExporterName": "192_0_2_142",
"InIfName": "Gi0/0/434",
"OutIfName": "Gi0/0/677",
"InIfDescription": "Interface 434",
"OutIfDescription": "Interface 677",
"InIfSpeed": 1000,
"OutIfSpeed": 1000,
"Bytes": 6765,
"Packets": 4,
"SrcPort": 8534,
"DstPort": 80,
"EType": 2048,
"Proto": 6,
"InIfSpeed": float64(1000),
"OutIfSpeed": float64(1000),
"Bytes": float64(6765),
"Packets": float64(4),
"SrcPort": float64(8534),
"DstPort": float64(80),
"EType": float64(2048),
"Proto": float64(6),
},
}
if diff := helpers.Diff(got, expected); diff != "" {

View File

@@ -43,10 +43,10 @@ func TestGobDecoder(t *testing.T) {
DstAddr: netip.MustParseAddr("::ffff:192.0.2.200"),
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: uint64(1024),
schema.ColumnPackets: 10,
schema.ColumnInIfBoundary: schema.InterfaceBoundaryExternal,
schema.ColumnPackets: uint64(10),
schema.ColumnInIfBoundary: uint8(schema.InterfaceBoundaryExternal),
schema.ColumnExporterName: "hello",
schema.ColumnDstNetMask: uint32(8),
schema.ColumnDstNetMask: uint8(8),
schema.ColumnDstPort: uint16(80),
schema.ColumnDstASPath: []uint32{65000, 65001, 65002},
},

View File

@@ -20,21 +20,21 @@ func TestDecodeMPLSAndIPv4(t *testing.T) {
if l != 40 {
t.Errorf("ParseEthernet() returned %d, expected 40", l)
}
expected := schema.FlowMessage{
expected := &schema.FlowMessage{
SrcAddr: netip.MustParseAddr("::ffff:10.31.0.1"),
DstAddr: netip.MustParseAddr("::ffff:10.34.0.1"),
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnEType: helpers.ETypeIPv4,
schema.ColumnProto: 6,
schema.ColumnSrcPort: 11001,
schema.ColumnDstPort: 23,
schema.ColumnTCPFlags: 16,
schema.ColumnMPLSLabels: []uint64{18, 16},
schema.ColumnIPTTL: 255,
schema.ColumnIPTos: 0xb0,
schema.ColumnIPFragmentID: 8,
schema.ColumnSrcMAC: 0x003096052838,
schema.ColumnDstMAC: 0x003096e6fc39,
schema.ColumnEType: uint32(helpers.ETypeIPv4),
schema.ColumnProto: uint32(6),
schema.ColumnSrcPort: uint16(11001),
schema.ColumnDstPort: uint16(23),
schema.ColumnTCPFlags: uint16(16),
schema.ColumnMPLSLabels: []uint32{18, 16},
schema.ColumnIPTTL: uint8(255),
schema.ColumnIPTos: uint8(0xb0),
schema.ColumnIPFragmentID: uint32(8),
schema.ColumnSrcMAC: uint64(0x003096052838),
schema.ColumnDstMAC: uint64(0x003096e6fc39),
},
}
if diff := helpers.Diff(bf, expected); diff != "" {
@@ -50,16 +50,16 @@ func TestDecodeVLANAndIPv6(t *testing.T) {
if l != 179 {
t.Errorf("ParseEthernet() returned %d, expected 179", l)
}
expected := schema.FlowMessage{
expected := &schema.FlowMessage{
SrcVlan: 100,
SrcAddr: netip.MustParseAddr("2402:f000:1:8e01::5555"),
DstAddr: netip.MustParseAddr("2607:fcd0:100:2300::b108:2a6b"),
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnEType: helpers.ETypeIPv6,
schema.ColumnProto: 4,
schema.ColumnIPTTL: 246,
schema.ColumnSrcMAC: 0x00121ef2613d,
schema.ColumnDstMAC: 0xc500000082c4,
schema.ColumnEType: uint32(helpers.ETypeIPv6),
schema.ColumnProto: uint32(4),
schema.ColumnIPTTL: uint8(246),
schema.ColumnSrcMAC: uint64(0x00121ef2613d),
schema.ColumnDstMAC: uint64(0xc500000082c4),
},
}
if diff := helpers.Diff(bf, expected); diff != "" {

View File

@@ -138,14 +138,14 @@ func TestDecode(t *testing.T) {
SrcNetMask: 24,
DstNetMask: 14,
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 1500,
schema.ColumnPackets: 1,
schema.ColumnEType: helpers.ETypeIPv4,
schema.ColumnProto: 6,
schema.ColumnSrcPort: 443,
schema.ColumnDstPort: 19624,
schema.ColumnForwardingStatus: 64,
schema.ColumnTCPFlags: 16,
schema.ColumnBytes: uint64(1500),
schema.ColumnPackets: uint64(1),
schema.ColumnEType: uint32(helpers.ETypeIPv4),
schema.ColumnProto: uint32(6),
schema.ColumnSrcPort: uint16(443),
schema.ColumnDstPort: uint16(19624),
schema.ColumnForwardingStatus: uint32(64),
schema.ColumnTCPFlags: uint16(16),
},
}, {
SamplingRate: 30000,
@@ -158,14 +158,14 @@ func TestDecode(t *testing.T) {
SrcNetMask: 24,
DstNetMask: 14,
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 1500,
schema.ColumnPackets: 1,
schema.ColumnEType: helpers.ETypeIPv4,
schema.ColumnProto: 6,
schema.ColumnSrcPort: 443,
schema.ColumnDstPort: 2444,
schema.ColumnForwardingStatus: 64,
schema.ColumnTCPFlags: 16,
schema.ColumnBytes: uint64(1500),
schema.ColumnPackets: uint64(1),
schema.ColumnEType: uint32(helpers.ETypeIPv4),
schema.ColumnProto: uint32(6),
schema.ColumnSrcPort: uint16(443),
schema.ColumnDstPort: uint16(2444),
schema.ColumnForwardingStatus: uint32(64),
schema.ColumnTCPFlags: uint16(16),
},
}, {
SamplingRate: 30000,
@@ -178,14 +178,14 @@ func TestDecode(t *testing.T) {
SrcNetMask: 20,
DstNetMask: 18,
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 1400,
schema.ColumnPackets: 1,
schema.ColumnEType: helpers.ETypeIPv4,
schema.ColumnProto: 6,
schema.ColumnSrcPort: 443,
schema.ColumnDstPort: 53697,
schema.ColumnForwardingStatus: 64,
schema.ColumnTCPFlags: 16,
schema.ColumnBytes: uint64(1400),
schema.ColumnPackets: uint64(1),
schema.ColumnEType: uint32(helpers.ETypeIPv4),
schema.ColumnProto: uint32(6),
schema.ColumnSrcPort: uint16(443),
schema.ColumnDstPort: uint16(53697),
schema.ColumnForwardingStatus: uint32(64),
schema.ColumnTCPFlags: uint16(16),
},
}, {
SamplingRate: 30000,
@@ -198,19 +198,19 @@ func TestDecode(t *testing.T) {
SrcNetMask: 16,
DstNetMask: 14,
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 1448,
schema.ColumnPackets: 1,
schema.ColumnEType: helpers.ETypeIPv4,
schema.ColumnProto: 6,
schema.ColumnSrcPort: 443,
schema.ColumnDstPort: 52300,
schema.ColumnForwardingStatus: 64,
schema.ColumnTCPFlags: 16,
schema.ColumnBytes: uint64(1448),
schema.ColumnPackets: uint64(1),
schema.ColumnEType: uint32(helpers.ETypeIPv4),
schema.ColumnProto: uint32(6),
schema.ColumnSrcPort: uint16(443),
schema.ColumnDstPort: uint16(52300),
schema.ColumnForwardingStatus: uint32(64),
schema.ColumnTCPFlags: uint16(16),
},
},
}
if diff := helpers.Diff(got, expectedFlows); diff != "" {
if diff := helpers.Diff(got, &expectedFlows); diff != "" {
t.Fatalf("Decode() (-got, +want):\n%s", diff)
}
gotMetrics = r.GetMetrics(
@@ -293,12 +293,12 @@ func TestDecodeSamplingRate(t *testing.T) {
SrcVlan: 701,
NextHop: netip.MustParseAddr("::ffff:0.0.0.0"),
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnPackets: 1,
schema.ColumnBytes: 160,
schema.ColumnProto: 6,
schema.ColumnSrcPort: 13245,
schema.ColumnDstPort: 10907,
schema.ColumnEType: helpers.ETypeIPv4,
schema.ColumnPackets: uint64(1),
schema.ColumnBytes: uint64(160),
schema.ColumnProto: uint32(6),
schema.ColumnSrcPort: uint16(13245),
schema.ColumnDstPort: uint16(10907),
schema.ColumnEType: uint32(helpers.ETypeIPv4),
},
},
}
@@ -353,17 +353,17 @@ func TestDecodeMultipleSamplingRates(t *testing.T) {
InIf: 97,
OutIf: 6,
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnPackets: 18,
schema.ColumnBytes: 1348,
schema.ColumnProto: 6,
schema.ColumnSrcPort: 443,
schema.ColumnDstPort: 52616,
schema.ColumnForwardingStatus: 64,
schema.ColumnIPTTL: 127,
schema.ColumnIPTos: 64,
schema.ColumnIPv6FlowLabel: 252813,
schema.ColumnTCPFlags: 16,
schema.ColumnEType: helpers.ETypeIPv6,
schema.ColumnPackets: uint64(18),
schema.ColumnBytes: uint64(1348),
schema.ColumnProto: uint32(6),
schema.ColumnSrcPort: uint16(443),
schema.ColumnDstPort: uint16(52616),
schema.ColumnForwardingStatus: uint32(64),
schema.ColumnIPTTL: uint8(127),
schema.ColumnIPTos: uint8(64),
schema.ColumnIPv6FlowLabel: uint32(252813),
schema.ColumnTCPFlags: uint16(16),
schema.ColumnEType: uint32(helpers.ETypeIPv6),
},
},
{
@@ -377,16 +377,16 @@ func TestDecodeMultipleSamplingRates(t *testing.T) {
InIf: 103,
OutIf: 6,
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnPackets: 4,
schema.ColumnBytes: 579,
schema.ColumnProto: 17,
schema.ColumnSrcPort: 2121,
schema.ColumnDstPort: 2121,
schema.ColumnForwardingStatus: 64,
schema.ColumnIPTTL: 57,
schema.ColumnIPTos: 40,
schema.ColumnIPv6FlowLabel: 570164,
schema.ColumnEType: helpers.ETypeIPv6,
schema.ColumnPackets: uint64(4),
schema.ColumnBytes: uint64(579),
schema.ColumnProto: uint32(17),
schema.ColumnSrcPort: uint16(2121),
schema.ColumnDstPort: uint16(2121),
schema.ColumnForwardingStatus: uint32(64),
schema.ColumnIPTTL: uint8(57),
schema.ColumnIPTos: uint8(40),
schema.ColumnIPv6FlowLabel: uint32(570164),
schema.ColumnEType: uint32(helpers.ETypeIPv6),
},
},
}
@@ -421,12 +421,12 @@ func TestDecodeICMP(t *testing.T) {
SrcAddr: netip.MustParseAddr("2001:db8::"),
DstAddr: netip.MustParseAddr("2001:db8::1"),
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 104,
schema.ColumnDstPort: 32768,
schema.ColumnEType: 34525,
schema.ColumnICMPv6Type: 128, // Code: 0
schema.ColumnPackets: 1,
schema.ColumnProto: 58,
schema.ColumnBytes: uint64(104),
schema.ColumnDstPort: uint16(32768),
schema.ColumnEType: uint32(34525),
schema.ColumnICMPv6Type: uint8(128), // Code: 0
schema.ColumnPackets: uint64(1),
schema.ColumnProto: uint32(58),
},
},
{
@@ -434,12 +434,12 @@ func TestDecodeICMP(t *testing.T) {
SrcAddr: netip.MustParseAddr("2001:db8::1"),
DstAddr: netip.MustParseAddr("2001:db8::"),
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 104,
schema.ColumnDstPort: 33024,
schema.ColumnEType: 34525,
schema.ColumnICMPv6Type: 129, // Code: 0
schema.ColumnPackets: 1,
schema.ColumnProto: 58,
schema.ColumnBytes: uint64(104),
schema.ColumnDstPort: uint16(33024),
schema.ColumnEType: uint32(34525),
schema.ColumnICMPv6Type: uint8(129), // Code: 0
schema.ColumnPackets: uint64(1),
schema.ColumnProto: uint32(58),
},
},
{
@@ -447,12 +447,12 @@ func TestDecodeICMP(t *testing.T) {
SrcAddr: netip.MustParseAddr("::ffff:203.0.113.4"),
DstAddr: netip.MustParseAddr("::ffff:203.0.113.5"),
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 84,
schema.ColumnDstPort: 2048,
schema.ColumnEType: 2048,
schema.ColumnICMPv4Type: 8, // Code: 0
schema.ColumnPackets: 1,
schema.ColumnProto: 1,
schema.ColumnBytes: uint64(84),
schema.ColumnDstPort: uint16(2048),
schema.ColumnEType: uint32(2048),
schema.ColumnICMPv4Type: uint8(8), // Code: 0
schema.ColumnPackets: uint64(1),
schema.ColumnProto: uint32(1),
},
},
{
@@ -460,16 +460,16 @@ func TestDecodeICMP(t *testing.T) {
SrcAddr: netip.MustParseAddr("::ffff:203.0.113.5"),
DstAddr: netip.MustParseAddr("::ffff:203.0.113.4"),
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 84,
schema.ColumnEType: 2048,
schema.ColumnPackets: 1,
schema.ColumnProto: 1,
schema.ColumnBytes: uint64(84),
schema.ColumnEType: uint32(2048),
schema.ColumnPackets: uint64(1),
schema.ColumnProto: uint32(1),
// Type/Code = 0
},
},
}
if diff := helpers.Diff(got, expectedFlows); diff != "" {
if diff := helpers.Diff(got, &expectedFlows); diff != "" {
t.Fatalf("Decode() (-got, +want):\n%s", diff)
}
}
@@ -502,21 +502,21 @@ func TestDecodeDataLink(t *testing.T) {
InIf: 582,
OutIf: 0,
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 96,
schema.ColumnSrcPort: 55501,
schema.ColumnDstPort: 11777,
schema.ColumnEType: helpers.ETypeIPv4,
schema.ColumnPackets: 1,
schema.ColumnProto: 17,
schema.ColumnSrcMAC: 0xb402165592f4,
schema.ColumnDstMAC: 0x182ad36e503f,
schema.ColumnIPFragmentID: 0x8f00,
schema.ColumnIPTTL: 119,
schema.ColumnBytes: uint64(96),
schema.ColumnSrcPort: uint16(55501),
schema.ColumnDstPort: uint16(11777),
schema.ColumnEType: uint32(helpers.ETypeIPv4),
schema.ColumnPackets: uint64(1),
schema.ColumnProto: uint32(17),
schema.ColumnSrcMAC: uint64(0xb402165592f4),
schema.ColumnDstMAC: uint64(0x182ad36e503f),
schema.ColumnIPFragmentID: uint32(0x8f00),
schema.ColumnIPTTL: uint8(119),
},
},
}
if diff := helpers.Diff(got, expectedFlows); diff != "" {
if diff := helpers.Diff(got, &expectedFlows); diff != "" {
t.Fatalf("Decode() (-got, +want):\n%s", diff)
}
}
@@ -534,7 +534,7 @@ func TestDecodeWithoutTemplate(t *testing.T) {
}
expectedFlows := []*schema.FlowMessage{}
if diff := helpers.Diff(got, expectedFlows); diff != "" {
if diff := helpers.Diff(got, &expectedFlows); diff != "" {
t.Fatalf("Decode() (-got, +want):\n%s", diff)
}
}
@@ -560,14 +560,14 @@ func TestDecodeMPLS(t *testing.T) {
SamplingRate: 10,
OutIf: 16,
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 89,
schema.ColumnPackets: 1,
schema.ColumnEType: helpers.ETypeIPv6,
schema.ColumnForwardingStatus: 66,
schema.ColumnIPTTL: 255,
schema.ColumnProto: 17,
schema.ColumnSrcPort: 49153,
schema.ColumnDstPort: 862,
schema.ColumnBytes: uint64(89),
schema.ColumnPackets: uint64(1),
schema.ColumnEType: uint32(helpers.ETypeIPv6),
schema.ColumnForwardingStatus: uint32(66),
schema.ColumnIPTTL: uint8(255),
schema.ColumnProto: uint32(17),
schema.ColumnSrcPort: uint16(49153),
schema.ColumnDstPort: uint16(862),
schema.ColumnMPLSLabels: []uint32{20005, 524250},
},
}, {
@@ -578,20 +578,20 @@ func TestDecodeMPLS(t *testing.T) {
SamplingRate: 10,
OutIf: 17,
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 890,
schema.ColumnPackets: 10,
schema.ColumnEType: helpers.ETypeIPv6,
schema.ColumnForwardingStatus: 66,
schema.ColumnIPTTL: 255,
schema.ColumnProto: 17,
schema.ColumnSrcPort: 49153,
schema.ColumnDstPort: 862,
schema.ColumnBytes: uint64(890),
schema.ColumnPackets: uint64(10),
schema.ColumnEType: uint32(helpers.ETypeIPv6),
schema.ColumnForwardingStatus: uint32(66),
schema.ColumnIPTTL: uint8(255),
schema.ColumnProto: uint32(17),
schema.ColumnSrcPort: uint16(49153),
schema.ColumnDstPort: uint16(862),
schema.ColumnMPLSLabels: []uint32{20006, 524275},
},
},
}
if diff := helpers.Diff(got, expectedFlows); diff != "" {
if diff := helpers.Diff(got, &expectedFlows); diff != "" {
t.Fatalf("Decode() (-got, +want):\n%s", diff)
}
}
@@ -633,13 +633,13 @@ func TestDecodeNFv5(t *testing.T) {
SrcNetMask: 19,
DstNetMask: 24,
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 133,
schema.ColumnPackets: 1,
schema.ColumnEType: helpers.ETypeIPv4,
schema.ColumnProto: 6,
schema.ColumnSrcPort: 30104,
schema.ColumnDstPort: 11963,
schema.ColumnTCPFlags: 0x18,
schema.ColumnBytes: uint64(133),
schema.ColumnPackets: uint64(1),
schema.ColumnEType: uint32(helpers.ETypeIPv4),
schema.ColumnProto: uint32(6),
schema.ColumnSrcPort: uint16(30104),
schema.ColumnDstPort: uint16(11963),
schema.ColumnTCPFlags: uint16(0x18),
},
},
}
@@ -742,14 +742,14 @@ func TestDecodeNAT(t *testing.T) {
SrcAddr: netip.MustParseAddr("::ffff:172.16.100.198"),
DstAddr: netip.MustParseAddr("::ffff:10.89.87.1"),
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnSrcPort: 35303,
schema.ColumnDstPort: 53,
schema.ColumnSrcPort: uint16(35303),
schema.ColumnDstPort: uint16(53),
schema.ColumnSrcAddrNAT: netip.MustParseAddr("::ffff:10.143.52.29"),
schema.ColumnDstAddrNAT: netip.MustParseAddr("::ffff:10.89.87.1"),
schema.ColumnSrcPortNAT: 35303,
schema.ColumnDstPortNAT: 53,
schema.ColumnEType: helpers.ETypeIPv4,
schema.ColumnProto: 17,
schema.ColumnSrcPortNAT: uint16(35303),
schema.ColumnDstPortNAT: uint16(53),
schema.ColumnEType: uint32(helpers.ETypeIPv4),
schema.ColumnProto: uint32(17),
},
},
}
@@ -785,15 +785,15 @@ func TestDecodePhysicalInterfaces(t *testing.T) {
DstAddr: netip.MustParseAddr("::ffff:212.82.101.24"),
NextHop: netip.MustParseAddr("::"),
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnSrcMAC: 0xc014fef6c365,
schema.ColumnDstMAC: 0xe8b6c24ae34c,
schema.ColumnPackets: 3,
schema.ColumnBytes: 4506,
schema.ColumnSrcPort: 55629,
schema.ColumnDstPort: 993,
schema.ColumnTCPFlags: 0x10,
schema.ColumnEType: helpers.ETypeIPv4,
schema.ColumnProto: 6,
schema.ColumnSrcMAC: uint64(0xc014fef6c365),
schema.ColumnDstMAC: uint64(0xe8b6c24ae34c),
schema.ColumnPackets: uint64(3),
schema.ColumnBytes: uint64(4506),
schema.ColumnSrcPort: uint16(55629),
schema.ColumnDstPort: uint16(993),
schema.ColumnTCPFlags: uint16(0x10),
schema.ColumnEType: uint32(helpers.ETypeIPv4),
schema.ColumnProto: uint32(6),
},
},
}

View File

@@ -51,18 +51,18 @@ func TestDecode(t *testing.T) {
DstAddr: netip.MustParseAddr("2a0c:8880:2:0:185:21:130:39"),
ExporterAddress: netip.MustParseAddr("::ffff:172.16.0.3"),
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 1500,
schema.ColumnPackets: 1,
schema.ColumnEType: helpers.ETypeIPv6,
schema.ColumnProto: 6,
schema.ColumnSrcPort: 46026,
schema.ColumnDstPort: 22,
schema.ColumnSrcMAC: 40057391053392,
schema.ColumnDstMAC: 40057381862408,
schema.ColumnIPTTL: 64,
schema.ColumnIPTos: 0x8,
schema.ColumnIPv6FlowLabel: 0x68094,
schema.ColumnTCPFlags: 0x10,
schema.ColumnBytes: uint64(1500),
schema.ColumnPackets: uint64(1),
schema.ColumnEType: uint32(helpers.ETypeIPv6),
schema.ColumnProto: uint32(6),
schema.ColumnSrcPort: uint16(46026),
schema.ColumnDstPort: uint16(22),
schema.ColumnSrcMAC: uint64(40057391053392),
schema.ColumnDstMAC: uint64(40057381862408),
schema.ColumnIPTTL: uint8(64),
schema.ColumnIPTos: uint8(0x8),
schema.ColumnIPv6FlowLabel: uint32(0x68094),
schema.ColumnTCPFlags: uint16(0x10),
},
}, {
SamplingRate: 1024,
@@ -78,17 +78,17 @@ func TestDecode(t *testing.T) {
SrcNetMask: 20,
DstNetMask: 27,
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 421,
schema.ColumnPackets: 1,
schema.ColumnEType: helpers.ETypeIPv4,
schema.ColumnProto: 6,
schema.ColumnSrcPort: 443,
schema.ColumnDstPort: 56876,
schema.ColumnSrcMAC: 216372595274807,
schema.ColumnDstMAC: 191421060163210,
schema.ColumnIPFragmentID: 0xa572,
schema.ColumnIPTTL: 59,
schema.ColumnTCPFlags: 0x18,
schema.ColumnBytes: uint64(421),
schema.ColumnPackets: uint64(1),
schema.ColumnEType: uint32(helpers.ETypeIPv4),
schema.ColumnProto: uint32(6),
schema.ColumnSrcPort: uint16(443),
schema.ColumnDstPort: uint16(56876),
schema.ColumnSrcMAC: uint64(216372595274807),
schema.ColumnDstMAC: uint64(191421060163210),
schema.ColumnIPFragmentID: uint32(0xa572),
schema.ColumnIPTTL: uint8(59),
schema.ColumnTCPFlags: uint16(0x18),
},
}, {
SamplingRate: 1024,
@@ -100,18 +100,18 @@ func TestDecode(t *testing.T) {
SrcVlan: 100,
DstVlan: 100,
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 1500,
schema.ColumnPackets: 1,
schema.ColumnEType: helpers.ETypeIPv6,
schema.ColumnProto: 6,
schema.ColumnSrcPort: 46026,
schema.ColumnDstPort: 22,
schema.ColumnSrcMAC: 40057391053392,
schema.ColumnDstMAC: 40057381862408,
schema.ColumnIPTTL: 64,
schema.ColumnIPTos: 0x8,
schema.ColumnIPv6FlowLabel: 0x68094,
schema.ColumnTCPFlags: 0x10,
schema.ColumnBytes: uint64(1500),
schema.ColumnPackets: uint64(1),
schema.ColumnEType: uint32(helpers.ETypeIPv6),
schema.ColumnProto: uint32(6),
schema.ColumnSrcPort: uint16(46026),
schema.ColumnDstPort: uint16(22),
schema.ColumnSrcMAC: uint64(40057391053392),
schema.ColumnDstMAC: uint64(40057381862408),
schema.ColumnIPTTL: uint8(64),
schema.ColumnIPTos: uint8(0x8),
schema.ColumnIPv6FlowLabel: uint32(0x68094),
schema.ColumnTCPFlags: uint16(0x10),
},
}, {
SamplingRate: 1024,
@@ -127,19 +127,19 @@ func TestDecode(t *testing.T) {
SrcNetMask: 27,
DstNetMask: 17,
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 40,
schema.ColumnPackets: 1,
schema.ColumnEType: helpers.ETypeIPv4,
schema.ColumnProto: 6,
schema.ColumnSrcPort: 55658,
schema.ColumnDstPort: 5555,
schema.ColumnSrcMAC: 138617863011056,
schema.ColumnDstMAC: 216372595274807,
schema.ColumnBytes: uint64(40),
schema.ColumnPackets: uint64(1),
schema.ColumnEType: uint32(helpers.ETypeIPv4),
schema.ColumnProto: uint32(6),
schema.ColumnSrcPort: uint16(55658),
schema.ColumnDstPort: uint16(5555),
schema.ColumnSrcMAC: uint64(138617863011056),
schema.ColumnDstMAC: uint64(216372595274807),
schema.ColumnDstASPath: []uint32{203698, 6762, 26615},
schema.ColumnDstCommunities: []uint64{2583495656, 2583495657, 4259880000, 4259880001, 4259900001},
schema.ColumnIPFragmentID: 0xd431,
schema.ColumnIPTTL: 255,
schema.ColumnTCPFlags: 0x2,
schema.ColumnDstCommunities: []uint32{2583495656, 2583495657, 4259880000, 4259880001, 4259900001},
schema.ColumnIPFragmentID: uint32(0xd431),
schema.ColumnIPTTL: uint8(255),
schema.ColumnTCPFlags: uint16(0x2),
},
}, {
SamplingRate: 1024,
@@ -151,18 +151,18 @@ func TestDecode(t *testing.T) {
SrcVlan: 100,
DstVlan: 100,
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 1500,
schema.ColumnPackets: 1,
schema.ColumnEType: helpers.ETypeIPv6,
schema.ColumnProto: 6,
schema.ColumnSrcPort: 46026,
schema.ColumnDstPort: 22,
schema.ColumnSrcMAC: 40057391053392,
schema.ColumnDstMAC: 40057381862408,
schema.ColumnIPTTL: 64,
schema.ColumnIPTos: 0x8,
schema.ColumnIPv6FlowLabel: 0x68094,
schema.ColumnTCPFlags: 0x10,
schema.ColumnBytes: uint64(1500),
schema.ColumnPackets: uint64(1),
schema.ColumnEType: uint32(helpers.ETypeIPv6),
schema.ColumnProto: uint32(6),
schema.ColumnSrcPort: uint16(46026),
schema.ColumnDstPort: uint16(22),
schema.ColumnSrcMAC: uint64(40057391053392),
schema.ColumnDstMAC: uint64(40057381862408),
schema.ColumnIPTTL: uint8(64),
schema.ColumnIPTos: uint8(0x8),
schema.ColumnIPv6FlowLabel: uint32(0x68094),
schema.ColumnTCPFlags: uint16(0x10),
},
},
}
@@ -205,18 +205,18 @@ func TestDecode(t *testing.T) {
SrcVlan: 100,
DstVlan: 100,
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 1500,
schema.ColumnPackets: 1,
schema.ColumnEType: helpers.ETypeIPv6,
schema.ColumnProto: 6,
schema.ColumnSrcPort: 46026,
schema.ColumnDstPort: 22,
schema.ColumnSrcMAC: 40057391053392,
schema.ColumnDstMAC: 40057381862408,
schema.ColumnTCPFlags: 16,
schema.ColumnIPv6FlowLabel: 426132,
schema.ColumnIPTTL: 64,
schema.ColumnIPTos: 8,
schema.ColumnBytes: uint64(1500),
schema.ColumnPackets: uint64(1),
schema.ColumnEType: uint32(helpers.ETypeIPv6),
schema.ColumnProto: uint32(6),
schema.ColumnSrcPort: uint16(46026),
schema.ColumnDstPort: uint16(22),
schema.ColumnSrcMAC: uint64(40057391053392),
schema.ColumnDstMAC: uint64(40057381862408),
schema.ColumnTCPFlags: uint16(16),
schema.ColumnIPv6FlowLabel: uint32(426132),
schema.ColumnIPTTL: uint8(64),
schema.ColumnIPTos: uint8(8),
},
},
}
@@ -246,19 +246,19 @@ func TestDecode(t *testing.T) {
SrcVlan: 100,
DstVlan: 100,
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 1500,
schema.ColumnPackets: 1,
schema.ColumnEType: helpers.ETypeIPv6,
schema.ColumnProto: 6,
schema.ColumnSrcPort: 46026,
schema.ColumnDstPort: 22,
schema.ColumnForwardingStatus: 128,
schema.ColumnSrcMAC: 40057391053392,
schema.ColumnDstMAC: 40057381862408,
schema.ColumnTCPFlags: 16,
schema.ColumnIPv6FlowLabel: 426132,
schema.ColumnIPTTL: 64,
schema.ColumnIPTos: 8,
schema.ColumnBytes: uint64(1500),
schema.ColumnPackets: uint64(1),
schema.ColumnEType: uint32(helpers.ETypeIPv6),
schema.ColumnProto: uint32(6),
schema.ColumnSrcPort: uint16(46026),
schema.ColumnDstPort: uint16(22),
schema.ColumnForwardingStatus: uint32(128),
schema.ColumnSrcMAC: uint64(40057391053392),
schema.ColumnDstMAC: uint64(40057381862408),
schema.ColumnTCPFlags: uint16(16),
schema.ColumnIPv6FlowLabel: uint32(426132),
schema.ColumnIPTTL: uint8(64),
schema.ColumnIPTos: uint8(8),
},
},
}
@@ -288,18 +288,18 @@ func TestDecode(t *testing.T) {
SrcVlan: 100,
DstVlan: 100,
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 1500,
schema.ColumnPackets: 1,
schema.ColumnEType: helpers.ETypeIPv6,
schema.ColumnProto: 6,
schema.ColumnSrcPort: 46026,
schema.ColumnDstPort: 22,
schema.ColumnSrcMAC: 40057391053392,
schema.ColumnDstMAC: 40057381862408,
schema.ColumnTCPFlags: 16,
schema.ColumnIPv6FlowLabel: 426132,
schema.ColumnIPTTL: 64,
schema.ColumnIPTos: 8,
schema.ColumnBytes: uint64(1500),
schema.ColumnPackets: uint64(1),
schema.ColumnEType: uint32(helpers.ETypeIPv6),
schema.ColumnProto: uint32(6),
schema.ColumnSrcPort: uint16(46026),
schema.ColumnDstPort: uint16(22),
schema.ColumnSrcMAC: uint64(40057391053392),
schema.ColumnDstMAC: uint64(40057381862408),
schema.ColumnTCPFlags: uint16(16),
schema.ColumnIPv6FlowLabel: uint32(426132),
schema.ColumnIPTTL: uint8(64),
schema.ColumnIPTos: uint8(8),
},
},
}
@@ -333,20 +333,20 @@ func TestDecode(t *testing.T) {
SrcNetMask: 32,
DstNetMask: 22,
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 104,
schema.ColumnPackets: 1,
schema.ColumnEType: helpers.ETypeIPv4,
schema.ColumnProto: 6,
schema.ColumnSrcPort: 22,
schema.ColumnDstPort: 52237,
schema.ColumnBytes: uint64(104),
schema.ColumnPackets: uint64(1),
schema.ColumnEType: uint32(helpers.ETypeIPv4),
schema.ColumnProto: uint32(6),
schema.ColumnSrcPort: uint16(22),
schema.ColumnDstPort: uint16(52237),
schema.ColumnDstASPath: []uint32{8218, 29605, 203361},
schema.ColumnDstCommunities: []uint64{538574949, 1911619684, 1911669584, 1911671290},
schema.ColumnTCPFlags: 0x18,
schema.ColumnIPFragmentID: 0xab4e,
schema.ColumnIPTTL: 61,
schema.ColumnIPTos: 0x8,
schema.ColumnSrcMAC: 0x948ed30a713b,
schema.ColumnDstMAC: 0x22421f4a9fcd,
schema.ColumnDstCommunities: []uint32{538574949, 1911619684, 1911669584, 1911671290},
schema.ColumnTCPFlags: uint16(0x18),
schema.ColumnIPFragmentID: uint32(0xab4e),
schema.ColumnIPTTL: uint8(61),
schema.ColumnIPTos: uint8(0x8),
schema.ColumnSrcMAC: uint64(0x948ed30a713b),
schema.ColumnDstMAC: uint64(0x22421f4a9fcd),
},
},
}
@@ -375,16 +375,16 @@ func TestDecode(t *testing.T) {
DstAddr: netip.MustParseAddr("::ffff:51.51.51.51"),
ExporterAddress: netip.MustParseAddr("::ffff:49.49.49.49"),
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 1344,
schema.ColumnPackets: 1,
schema.ColumnEType: helpers.ETypeIPv4,
schema.ColumnProto: 17,
schema.ColumnSrcPort: 46622,
schema.ColumnDstPort: 58631,
schema.ColumnSrcMAC: 1094287164743,
schema.ColumnDstMAC: 1101091482116,
schema.ColumnIPFragmentID: 41647,
schema.ColumnIPTTL: 64,
schema.ColumnBytes: uint64(1344),
schema.ColumnPackets: uint64(1),
schema.ColumnEType: uint32(helpers.ETypeIPv4),
schema.ColumnProto: uint32(17),
schema.ColumnSrcPort: uint16(46622),
schema.ColumnDstPort: uint16(58631),
schema.ColumnSrcMAC: uint64(1094287164743),
schema.ColumnDstMAC: uint64(1101091482116),
schema.ColumnIPFragmentID: uint32(41647),
schema.ColumnIPTTL: uint8(64),
},
},
}
@@ -412,13 +412,13 @@ func TestDecode(t *testing.T) {
DstAddr: netip.MustParseAddr("::ffff:92.222.186.1"),
ExporterAddress: netip.MustParseAddr("::ffff:172.19.64.116"),
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 32,
schema.ColumnPackets: 1,
schema.ColumnEType: helpers.ETypeIPv4,
schema.ColumnProto: 1,
schema.ColumnIPFragmentID: 4329,
schema.ColumnIPTTL: 64,
schema.ColumnIPTos: 8,
schema.ColumnBytes: uint64(32),
schema.ColumnPackets: uint64(1),
schema.ColumnEType: uint32(helpers.ETypeIPv4),
schema.ColumnProto: uint32(1),
schema.ColumnIPFragmentID: uint32(4329),
schema.ColumnIPTTL: uint8(64),
schema.ColumnIPTos: uint8(8),
},
}, {
SamplingRate: 1,
@@ -428,13 +428,13 @@ func TestDecode(t *testing.T) {
DstAddr: netip.MustParseAddr("::ffff:92.222.184.1"),
ExporterAddress: netip.MustParseAddr("::ffff:172.19.64.116"),
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 32,
schema.ColumnPackets: 1,
schema.ColumnEType: helpers.ETypeIPv4,
schema.ColumnProto: 1,
schema.ColumnIPFragmentID: 62945,
schema.ColumnIPTTL: 64,
schema.ColumnIPTos: 8,
schema.ColumnBytes: uint64(32),
schema.ColumnPackets: uint64(1),
schema.ColumnEType: uint32(helpers.ETypeIPv4),
schema.ColumnProto: uint32(1),
schema.ColumnIPFragmentID: uint32(62945),
schema.ColumnIPTTL: uint8(64),
schema.ColumnIPTos: uint8(8),
},
},
}
@@ -460,16 +460,16 @@ func TestDecode(t *testing.T) {
DstAddr: netip.MustParseAddr("::ffff:203.0.113.5"),
ExporterAddress: netip.MustParseAddr("::ffff:127.0.0.1"),
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 84,
schema.ColumnPackets: 1,
schema.ColumnEType: helpers.ETypeIPv4,
schema.ColumnProto: 1,
schema.ColumnDstMAC: 0xd25b45ee5ecf,
schema.ColumnSrcMAC: 0xe2efc68f8cd4,
schema.ColumnICMPv4Type: 8,
schema.ColumnBytes: uint64(84),
schema.ColumnPackets: uint64(1),
schema.ColumnEType: uint32(helpers.ETypeIPv4),
schema.ColumnProto: uint32(1),
schema.ColumnDstMAC: uint64(0xd25b45ee5ecf),
schema.ColumnSrcMAC: uint64(0xe2efc68f8cd4),
schema.ColumnICMPv4Type: uint8(8),
// schema.ColumnICMPv4Code: 0,
schema.ColumnIPTTL: 64,
schema.ColumnIPFragmentID: 0x90c5,
schema.ColumnIPTTL: uint8(64),
schema.ColumnIPFragmentID: uint32(0x90c5),
},
},
}
@@ -495,14 +495,14 @@ func TestDecode(t *testing.T) {
DstAddr: netip.MustParseAddr("2001:db8::"),
ExporterAddress: netip.MustParseAddr("::ffff:127.0.0.1"),
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 72,
schema.ColumnPackets: 1,
schema.ColumnEType: helpers.ETypeIPv6,
schema.ColumnProto: 58,
schema.ColumnSrcMAC: 0xd25b45ee5ecf,
schema.ColumnDstMAC: 0xe2efc68f8cd4,
schema.ColumnIPTTL: 255,
schema.ColumnICMPv6Type: 135,
schema.ColumnBytes: uint64(72),
schema.ColumnPackets: uint64(1),
schema.ColumnEType: uint32(helpers.ETypeIPv6),
schema.ColumnProto: uint32(58),
schema.ColumnSrcMAC: uint64(0xd25b45ee5ecf),
schema.ColumnDstMAC: uint64(0xe2efc68f8cd4),
schema.ColumnIPTTL: uint8(255),
schema.ColumnICMPv6Type: uint8(135),
// schema.ColumnICMPv6Code: 0,
},
},
@@ -532,17 +532,17 @@ func TestDecode(t *testing.T) {
DstAddr: netip.MustParseAddr("::ffff:49.49.49.109"),
ExporterAddress: netip.MustParseAddr("::ffff:172.17.128.58"),
OtherColumns: map[schema.ColumnKey]any{
schema.ColumnBytes: 80,
schema.ColumnPackets: 1,
schema.ColumnEType: helpers.ETypeIPv4,
schema.ColumnProto: 6,
schema.ColumnSrcMAC: 0x4caea3520ff6,
schema.ColumnDstMAC: 0x000110621493,
schema.ColumnIPTTL: 62,
schema.ColumnIPFragmentID: 56159,
schema.ColumnTCPFlags: 16,
schema.ColumnSrcPort: 32017,
schema.ColumnDstPort: 443,
schema.ColumnBytes: uint64(80),
schema.ColumnPackets: uint64(1),
schema.ColumnEType: uint32(helpers.ETypeIPv4),
schema.ColumnProto: uint32(6),
schema.ColumnSrcMAC: uint64(0x4caea3520ff6),
schema.ColumnDstMAC: uint64(0x000110621493),
schema.ColumnIPTTL: uint8(62),
schema.ColumnIPFragmentID: uint32(56159),
schema.ColumnTCPFlags: uint16(16),
schema.ColumnSrcPort: uint16(32017),
schema.ColumnDstPort: uint16(443),
},
},
}

View File

@@ -289,31 +289,31 @@ func TestNeedUpdates(t *testing.T) {
cases := []struct {
Minutes time.Duration
Expected map[string][]uint
Expected map[netip.Addr][]uint
}{
{9, map[string][]uint{
"::ffff:127.0.0.1": {
{9, map[netip.Addr][]uint{
netip.MustParseAddr("::ffff:127.0.0.1"): {
676,
678,
},
"::ffff:127.0.0.2": {
netip.MustParseAddr("::ffff:127.0.0.2"): {
678,
},
}},
{19, map[string][]uint{
"::ffff:127.0.0.1": {
{19, map[netip.Addr][]uint{
netip.MustParseAddr("::ffff:127.0.0.1"): {
678,
},
"::ffff:127.0.0.2": {
netip.MustParseAddr("::ffff:127.0.0.2"): {
678,
},
}},
{29, map[string][]uint{
"::ffff:127.0.0.1": {
{29, map[netip.Addr][]uint{
netip.MustParseAddr("::ffff:127.0.0.1"): {
678,
},
}},
{39, map[string][]uint{}},
{39, map[netip.Addr][]uint{}},
}
for _, tc := range cases {
t.Run(fmt.Sprintf("%d minutes", tc.Minutes), func(t *testing.T) {

View File

@@ -8,6 +8,8 @@ import (
"akvorado/common/helpers"
"akvorado/outlet/metadata/provider"
"github.com/google/go-cmp/cmp/cmpopts"
)
func TestStateUpdate(t *testing.T) {
@@ -28,7 +30,7 @@ func TestStateUpdate(t *testing.T) {
Name: "",
Interfaces: map[uint]provider.Interface{},
}
if diff := helpers.Diff(state, expected); diff != "" {
if diff := helpers.Diff(state, expected, cmpopts.IgnoreUnexported(state)); diff != "" {
t.Fatalf("udpate() (-got, +want):\n%s", diff)
}
@@ -90,7 +92,7 @@ func TestStateUpdate(t *testing.T) {
},
},
}
if diff := helpers.Diff(state, expected); diff != "" {
if diff := helpers.Diff(state, expected, cmpopts.IgnoreUnexported(state)); diff != "" {
t.Fatalf("udpate() (-got, +want):\n%s", diff)
}
}

View File

@@ -6,12 +6,9 @@
package snmp
import (
"fmt"
"reflect"
"akvorado/common/helpers"
)
func init() {
helpers.AddPrettyFormatter(reflect.TypeOf(helpers.SubnetMap[Credentials]{}), fmt.Sprint)
helpers.RegisterSubnetMapCmp[Credentials]()
}

View File

@@ -6,12 +6,9 @@
package static
import (
"fmt"
"reflect"
"akvorado/common/helpers"
)
func init() {
helpers.AddPrettyFormatter(reflect.TypeOf(helpers.SubnetMap[ExporterConfiguration]{}), fmt.Sprint)
helpers.RegisterSubnetMapCmp[ExporterConfiguration]()
}

View File

@@ -206,7 +206,7 @@ func TestRemoveRoutes(t *testing.T) {
if count != 1 {
t.Error("removeRoutes() should have removed 1 route")
}
if diff := helpers.Diff(r.routes, map[prefixIndex]route{}); diff != "" {
if diff := helpers.Diff(r.routes, map[routeKey]route{}); diff != "" {
t.Errorf("removeRoutes() (-got, +want):\n%s", diff)
}
})

View File

@@ -6,10 +6,8 @@
package bmp
import (
"fmt"
"net"
"net/netip"
"reflect"
"testing"
"akvorado/common/daemon"
@@ -18,6 +16,7 @@ import (
"akvorado/outlet/routing/provider"
"github.com/benbjohnson/clock"
"github.com/google/go-cmp/cmp"
"github.com/osrg/gobgp/v3/pkg/packet/bgp"
"github.com/osrg/gobgp/v3/pkg/packet/bmp"
)
@@ -149,5 +148,5 @@ func MustParseRD(input string) RD {
}
func init() {
helpers.AddPrettyFormatter(reflect.TypeOf(route{}), fmt.Sprint)
helpers.RegisterCmpOption(cmp.AllowUnexported(route{}))
}