summaryrefslogtreecommitdiffhomepage
path: root/dhcpv6/ztpv6/parse_remote_id_test.go
blob: 8d17c80e69bb82049703ca794deaaaaaf0ee69d4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package ztpv6

import (
	"testing"

	"github.com/insomniacslk/dhcp/dhcpv6"
	"github.com/stretchr/testify/require"
)

func TestCircuitID(t *testing.T) {
	tt := []struct {
		name    string
		circuit string
		want    *CircuitID
		fail    bool
	}{
		{name: "Bogus string", circuit: "ope/1/2/3:ope", fail: true, want: nil},
		{name: "Bogus test", circuit: "bogusInterface", fail: true, want: nil},
		{name: "juniperQFX pattern et", circuit: "et-0/0/0:0.0", want: &CircuitID{Slot: "0", Module: "0", Port: "0", SubPort: "0"}},
		{name: "juniperQFX pattern xe", circuit: "xe-0/0/14:2", want: &CircuitID{Slot: "0", Module: "0", Port: "14", SubPort: "2"}},
		{name: "juniperPTX pattern", circuit: "et-0/0/0.0", want: &CircuitID{Slot: "0", Module: "0", Port: "0", SubPort: "0"}},
		{name: "Juniper QFX pattern", circuit: "et-1/0/61", want: &CircuitID{Slot: "1", Module: "0", Port: "61"}},
		{name: "Arista Vlan pattern 1", circuit: "Ethernet14:Vlan2001", want: &CircuitID{Port: "14", Vlan: "Vlan2001"}},
		{name: "Arista Vlan pattern 2", circuit: "Ethernet10:2020", want: &CircuitID{Port: "10", Vlan: "2020"}},
		{name: "Arista Slot Module Port Pattern", circuit: "Ethernet1/3/4", want: &CircuitID{Slot: "1", Module: "3", Port: "4"}},
		{name: "Arista Slot Module Port Pattern InterfaceID", circuit: "Ethernet1/3/4:default", want: &CircuitID{Slot: "1", Module: "3", Port: "4"}},
		{name: "Cisco pattern", circuit: "Gi1/10:2020", want: &CircuitID{Slot: "1", Port: "10", Vlan: "2020"}},
		{name: "Cisco Nexus pattern", circuit: "Ethernet1/3", want: &CircuitID{Slot: "1", Port: "3"}},
		{name: "Juniper Bundle Pattern", circuit: "ae52.0", want: &CircuitID{Port: "52", SubPort: "0"}},
		{name: "Arista Vlan pattern 1 with circuitid type and length", circuit: "\x00\x0fEthernet14:2001", want: &CircuitID{Port: "14", Vlan: "2001"}},
		{name: "juniperEX pattern", circuit: "ge-0/0/0.0:RANDOMCHAR", want: &CircuitID{Slot: "0", Module: "0", Port: "0", SubPort: "0"}},
	}
	for _, tc := range tt {
		t.Run(tc.name, func(t *testing.T) {
			circuit, err := matchCircuitId(tc.circuit)
			if err != nil && !tc.fail {
				t.Errorf("unexpected failure: %v", err)
			}
			if circuit != nil {
				require.Equal(t, *tc.want, *circuit, "comparing remoteID data")
			}
		})
	}
}

func TestFormatCircuitID(t *testing.T) {
	tt := []struct {
		name    string
		circuit *CircuitID
		want    string
	}{
		{name: "empty", circuit: &CircuitID{}, want: ",,,,"},
		{name: "empty", circuit: &CircuitID{}, want: ",,,,"},
		{name: "juniperQFX pattern et", circuit: &CircuitID{Slot: "0", Module: "0", Port: "0", SubPort: "0"}, want: "0,0,0,0,"},
		{name: "juniperQFX pattern xe", circuit: &CircuitID{Slot: "0", Module: "0", Port: "14", SubPort: "2"}, want: "0,0,14,2,"},
		{name: "juniperPTX pattern", circuit: &CircuitID{Slot: "0", Module: "0", Port: "0"}, want: "0,0,0,,"},
		{name: "Arista pattern", circuit: &CircuitID{Slot: "3", Module: "17", Port: "1"}, want: "3,17,1,,"},
		{name: "Juniper QFX pattern", circuit: &CircuitID{Slot: "1", Module: "0", Port: "61"}, want: "1,0,61,,"},
		{name: "Arista Vlan pattern 1", circuit: &CircuitID{Port: "14", Vlan: "Vlan2001"}, want: ",,14,,Vlan2001"},
		{name: "Arista Vlan pattern 2", circuit: &CircuitID{Port: "10", Vlan: "2020"}, want: ",,10,,2020"},
		{name: "Cisco Nexus pattern", circuit: &CircuitID{Slot: "1", Port: "3"}, want: "1,,3,,"},
		{name: "Juniper Bundle Pattern", circuit: &CircuitID{Port: "52", SubPort: "0"}, want: ",,52,0,"},
	}

	for _, tc := range tt {
		t.Run(tc.name, func(t *testing.T) {
			circuit := tc.circuit.FormatCircuitID()
			require.Equal(t, tc.want, circuit, "FormatRemoteID data")
		})
	}

}

func TestParseRemoteID(t *testing.T) {
	tt := []struct {
		name    string
		circuit []byte
		want    *CircuitID
		fail    bool
	}{
		{name: "Bogus string", circuit: []byte("ope/1/2/3:ope.1"), fail: true, want: nil},
		{name: "Bogus test", circuit: []byte("bogusInterface"), fail: true, want: nil},
		{name: "juniperQFX pattern et", circuit: []byte("et-0/0/0:0.0"), want: &CircuitID{Slot: "0", Module: "0", Port: "0", SubPort: "0"}},
		{name: "juniperQFX pattern xe", circuit: []byte("xe-0/0/14:2"), want: &CircuitID{Slot: "0", Module: "0", Port: "14", SubPort: "2"}},
		{name: "juniperPTX pattern", circuit: []byte("et-0/0/0.0"), want: &CircuitID{Slot: "0", Module: "0", Port: "0", SubPort: "0"}},
		{name: "Arista pattern", circuit: []byte("Ethernet3/17/1"), want: &CircuitID{Slot: "3", Module: "17", Port: "1"}},
		{name: "Juniper QFX pattern", circuit: []byte("et-1/0/61"), want: &CircuitID{Slot: "1", Module: "0", Port: "61"}},
		{name: "Arista Vlan pattern 1", circuit: []byte("Ethernet14:Vlan2001"), want: &CircuitID{Port: "14", Vlan: "Vlan2001"}},
		{name: "Arista Vlan pattern 2", circuit: []byte("Ethernet10:2020"), want: &CircuitID{Port: "10", Vlan: "2020"}},
		{name: "Cisco pattern", circuit: []byte("Gi1/10:2020"), want: &CircuitID{Slot: "1", Port: "10", Vlan: "2020"}},
		{name: "Cisco Nexus pattern", circuit: []byte("Ethernet1/3"), want: &CircuitID{Slot: "1", Port: "3"}},
		{name: "Juniper Bundle Pattern", circuit: []byte("ae52.0"), want: &CircuitID{Port: "52", SubPort: "0"}},
		{name: "Arista Vlan pattern 1 with circuitid type and length", circuit: []byte("\x00\x0fEthernet14:2001"), want: &CircuitID{Port: "14", Vlan: "2001"}},
		{name: "juniperEX pattern", circuit: []byte("ge-0/0/0.0:RANDOMCHAR"), want: &CircuitID{Slot: "0", Module: "0", Port: "0", SubPort: "0"}},
	}
	for _, tc := range tt {
		t.Run(tc.name, func(t *testing.T) {
			m := &dhcpv6.RelayMessage{
				MessageType: dhcpv6.MessageTypeRelayForward,
			}
			// Has to be a well-formed relay message with the OptRelayMsg.
			m.Options.Add(dhcpv6.OptRelayMessage(&dhcpv6.Message{}))
			m.Options.Add(&dhcpv6.OptRemoteID{RemoteID: tc.circuit, EnterpriseNumber: 1234})

			circuit, err := ParseRemoteID(m)
			if err != nil && !tc.fail {
				t.Errorf("unexpected failure: %v", err)
			}
			if circuit != nil {
				require.Equal(t, *tc.want, *circuit, "ZTPRemoteID data")
			} else {
				require.Equal(t, tc.want, circuit, "ZTPRemoteID data")
			}
		})
	}
}

func TestParseRemoteIDWithInterfaceID(t *testing.T) {
	tt := []struct {
		name    string
		circuit []byte
		want    *CircuitID
		fail    bool
	}{
		{name: "Bogus string", circuit: []byte("ope/1/2/3:ope.1"), fail: true, want: nil},
		{name: "Bogus test", circuit: []byte("bogusInterface"), fail: true, want: nil},
		{name: "juniperQFX pattern et", circuit: []byte("et-0/0/0:0.0"), want: &CircuitID{Slot: "0", Module: "0", Port: "0", SubPort: "0"}},
		{name: "juniperQFX pattern xe", circuit: []byte("xe-0/0/14:2"), want: &CircuitID{Slot: "0", Module: "0", Port: "14", SubPort: "2"}},
		{name: "juniperPTX pattern", circuit: []byte("et-0/0/0.0"), want: &CircuitID{Slot: "0", Module: "0", Port: "0", SubPort: "0"}},
		{name: "Arista pattern", circuit: []byte("Ethernet3/17/1"), want: &CircuitID{Slot: "3", Module: "17", Port: "1"}},
		{name: "Juniper QFX pattern", circuit: []byte("et-1/0/61"), want: &CircuitID{Slot: "1", Module: "0", Port: "61"}},
		{name: "Arista Vlan pattern 1", circuit: []byte("Ethernet14:Vlan2001"), want: &CircuitID{Port: "14", Vlan: "Vlan2001"}},
		{name: "Arista Vlan pattern 2", circuit: []byte("Ethernet10:2020"), want: &CircuitID{Port: "10", Vlan: "2020"}},
		{name: "Cisco pattern", circuit: []byte("Gi1/10:2020"), want: &CircuitID{Slot: "1", Port: "10", Vlan: "2020"}},
		{name: "Cisco Nexus pattern", circuit: []byte("Ethernet1/3"), want: &CircuitID{Slot: "1", Port: "3"}},
		{name: "Juniper Bundle Pattern", circuit: []byte("ae52.0"), want: &CircuitID{Port: "52", SubPort: "0"}},
		{name: "Arista Vlan pattern 1 with circuitid type and length", circuit: []byte("\x00\x0fEthernet14:2001"), want: &CircuitID{Port: "14", Vlan: "2001"}},
		{name: "juniperEX pattern", circuit: []byte("ge-0/0/0.0:RANDOMCHAR"), want: &CircuitID{Slot: "0", Module: "0", Port: "0", SubPort: "0"}},
		{name: "Arista Slot Module Port Pattern", circuit: []byte("Ethernet1/3/4:default"), want: &CircuitID{Slot: "1", Module: "3", Port: "4"}},
	}
	for _, tc := range tt {
		t.Run(tc.name, func(t *testing.T) {
			m := &dhcpv6.RelayMessage{
				MessageType: dhcpv6.MessageTypeRelayForward,
			}
			// Has to be a well-formed relay message with the OptRelayMsg.
			m.Options.Add(dhcpv6.OptRelayMessage(&dhcpv6.Message{}))
			m.Options.Add(dhcpv6.OptInterfaceID(tc.circuit))
			circuit, err := ParseRemoteID(m)
			if err != nil && !tc.fail {
				t.Errorf("unexpected failure: %v", err)
			}
			if circuit != nil {
				require.Equal(t, *tc.want, *circuit, "ZTPRemoteID data")
			} else {
				require.Equal(t, tc.want, circuit, "ZTPRemoteID data")
			}
		})
	}
}