mirror of
https://github.com/akvorado/akvorado.git
synced 2025-12-11 22:14:02 +01:00
247 lines
5.9 KiB
Go
247 lines
5.9 KiB
Go
// SPDX-FileCopyrightText: 2022 Free Mobile
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
package helpers_test
|
|
|
|
import (
|
|
"net/netip"
|
|
"testing"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/mitchellh/mapstructure"
|
|
"gopkg.in/yaml.v3"
|
|
|
|
"akvorado/common/helpers"
|
|
)
|
|
|
|
func TestSubnetMapUnmarshalHook(t *testing.T) {
|
|
var nilMap map[string]string
|
|
cases := []struct {
|
|
Description string
|
|
Input interface{}
|
|
Tests map[string]string
|
|
Error bool
|
|
YAML interface{}
|
|
}{
|
|
{
|
|
Description: "nil",
|
|
Input: nilMap,
|
|
Tests: map[string]string{
|
|
"::ffff:203.0.113.1": "",
|
|
},
|
|
}, {
|
|
Description: "empty",
|
|
Input: gin.H{},
|
|
Tests: map[string]string{
|
|
"::ffff:203.0.113.1": "",
|
|
},
|
|
}, {
|
|
Description: "IPv4 subnet",
|
|
Input: gin.H{"203.0.113.0/24": "customer1"},
|
|
Tests: map[string]string{
|
|
"::ffff:203.0.113.18": "customer1",
|
|
"::ffff:203.0.113.16": "customer1",
|
|
"203.0.113.16": "",
|
|
"::ffff:203.0.1.1": "",
|
|
"203.0.1.1": "",
|
|
"2001:db8:1::12": "",
|
|
},
|
|
}, {
|
|
Description: "IPv4 IP",
|
|
Input: gin.H{"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"},
|
|
}, {
|
|
Description: "IPv6 subnet",
|
|
Input: gin.H{"2001:db8:1::/64": "customer2"},
|
|
Tests: map[string]string{
|
|
"2001:db8:1::1": "customer2",
|
|
"2001:db8:1::2": "customer2",
|
|
"2001:db8:2::2": "",
|
|
},
|
|
}, {
|
|
Description: "IPv6-mapped-IPv4 subnet",
|
|
Input: gin.H{"::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"},
|
|
}, {
|
|
Description: "IPv6 IP",
|
|
Input: gin.H{"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"},
|
|
}, {
|
|
Description: "Invalid subnet (1)",
|
|
Input: gin.H{"192.0.2.1/38": "customer"},
|
|
Error: true,
|
|
}, {
|
|
Description: "Invalid subnet (2)",
|
|
Input: gin.H{"192.0.2.1/255.0.255.0": "customer"},
|
|
Error: true,
|
|
}, {
|
|
Description: "Invalid subnet (3)",
|
|
Input: gin.H{"2001:db8::/1000": "customer"},
|
|
Error: true,
|
|
}, {
|
|
Description: "Invalid IP",
|
|
Input: gin.H{"200.33.300.1": "customer"},
|
|
Error: true,
|
|
}, {
|
|
Description: "Random key",
|
|
Input: gin.H{"kfgdjgkfj": "customer"},
|
|
Error: true,
|
|
}, {
|
|
Description: "Single value",
|
|
Input: "customer",
|
|
Tests: map[string]string{
|
|
"::ffff:203.0.113.4": "customer",
|
|
"2001:db8::1": "customer",
|
|
},
|
|
YAML: map[string]string{
|
|
"::/0": "customer",
|
|
},
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
if tc.YAML == nil {
|
|
if tc.Error {
|
|
tc.YAML = map[string]string{}
|
|
} else {
|
|
tc.YAML = tc.Input
|
|
}
|
|
}
|
|
t.Run(tc.Description, func(t *testing.T) {
|
|
var tree helpers.SubnetMap[string]
|
|
decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
|
|
Result: &tree,
|
|
ErrorUnused: true,
|
|
Metadata: nil,
|
|
DecodeHook: helpers.SubnetMapUnmarshallerHook[string](),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("NewDecoder() error:\n%+v", err)
|
|
}
|
|
err = decoder.Decode(tc.Input)
|
|
if err != nil && !tc.Error {
|
|
t.Fatalf("Decode() error:\n%+v", err)
|
|
} else if err == nil && tc.Error {
|
|
t.Fatal("Decode() did not return an error")
|
|
}
|
|
got := map[string]string{}
|
|
for k := range tc.Tests {
|
|
v, _ := tree.Lookup(netip.MustParseAddr(k))
|
|
got[k] = v
|
|
}
|
|
if diff := helpers.Diff(got, tc.Tests); diff != "" {
|
|
t.Fatalf("Decode() (-got, +want):\n%s", diff)
|
|
}
|
|
|
|
// Try to unmarshal with YAML
|
|
buf, err := yaml.Marshal(tree)
|
|
if err != nil {
|
|
t.Fatalf("yaml.Marshal() error:\n%+v", err)
|
|
}
|
|
got = map[string]string{}
|
|
if err := yaml.Unmarshal(buf, &got); err != nil {
|
|
t.Fatalf("yaml.Unmarshal() error:\n%+v", err)
|
|
}
|
|
if diff := helpers.Diff(got, tc.YAML); diff != "" {
|
|
t.Fatalf("MarshalYAML() (-got, +want):\n%s", diff)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSubnetMapUnmarshalHookWithMapValue(t *testing.T) {
|
|
type SomeStruct struct {
|
|
Blip string
|
|
Blop string
|
|
}
|
|
cases := []struct {
|
|
Description string
|
|
Input gin.H
|
|
Expected gin.H
|
|
}{
|
|
{
|
|
Description: "single value",
|
|
Input: gin.H{
|
|
"blip": "some",
|
|
"blop": "thing",
|
|
},
|
|
Expected: gin.H{
|
|
"::/0": gin.H{
|
|
"Blip": "some",
|
|
"Blop": "thing",
|
|
},
|
|
},
|
|
}, {
|
|
Description: "proper map",
|
|
Input: gin.H{
|
|
"::/0": gin.H{
|
|
"blip": "some",
|
|
"blop": "thing",
|
|
},
|
|
"203.0.113.14": gin.H{
|
|
"blip": "other",
|
|
"blop": "stuff",
|
|
},
|
|
},
|
|
Expected: gin.H{
|
|
"::/0": gin.H{
|
|
"Blip": "some",
|
|
"Blop": "thing",
|
|
},
|
|
"203.0.113.14/32": gin.H{
|
|
"Blip": "other",
|
|
"Blop": "stuff",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(tc.Description, func(t *testing.T) {
|
|
var tree helpers.SubnetMap[SomeStruct]
|
|
decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
|
|
Result: &tree,
|
|
ErrorUnused: true,
|
|
Metadata: nil,
|
|
DecodeHook: helpers.SubnetMapUnmarshallerHook[SomeStruct](),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("NewDecoder() error:\n%+v", err)
|
|
}
|
|
err = decoder.Decode(tc.Input)
|
|
if err != nil {
|
|
t.Fatalf("Decode() error:\n%+v", err)
|
|
}
|
|
if diff := helpers.Diff(tree.ToMap(), tc.Expected); diff != "" {
|
|
t.Fatalf("Decode() (-got, +want):\n%s", diff)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestToMap(t *testing.T) {
|
|
input := helpers.MustNewSubnetMap(map[string]string{
|
|
"2001:db8::/64": "hello",
|
|
"::ffff:192.0.2.0/120": "bye",
|
|
})
|
|
got := input.ToMap()
|
|
expected := map[string]string{
|
|
"2001:db8::/64": "hello",
|
|
"192.0.2.0/24": "bye",
|
|
}
|
|
if diff := helpers.Diff(got, expected); diff != "" {
|
|
t.Fatalf("ToMap() (-got, +want):\n%s", diff)
|
|
}
|
|
}
|