Source file
src/net/netip/netip_pkg_test.go
1
2
3
4
5 package netip
6
7 import (
8 "bytes"
9 "encoding"
10 "encoding/json"
11 "strings"
12 "testing"
13 )
14
15 var (
16 mustPrefix = MustParsePrefix
17 mustIP = MustParseAddr
18 )
19
20 func TestPrefixValid(t *testing.T) {
21 v4 := MustParseAddr("1.2.3.4")
22 v6 := MustParseAddr("::1")
23 tests := []struct {
24 ipp Prefix
25 want bool
26 }{
27 {Prefix{v4, -2}, false},
28 {Prefix{v4, -1}, false},
29 {Prefix{v4, 0}, true},
30 {Prefix{v4, 32}, true},
31 {Prefix{v4, 33}, false},
32
33 {Prefix{v6, -2}, false},
34 {Prefix{v6, -1}, false},
35 {Prefix{v6, 0}, true},
36 {Prefix{v6, 32}, true},
37 {Prefix{v6, 128}, true},
38 {Prefix{v6, 129}, false},
39
40 {Prefix{Addr{}, -2}, false},
41 {Prefix{Addr{}, -1}, false},
42 {Prefix{Addr{}, 0}, false},
43 {Prefix{Addr{}, 32}, false},
44 {Prefix{Addr{}, 128}, false},
45 }
46 for _, tt := range tests {
47 got := tt.ipp.IsValid()
48 if got != tt.want {
49 t.Errorf("(%v).IsValid() = %v want %v", tt.ipp, got, tt.want)
50 }
51 }
52 }
53
54 var nextPrevTests = []struct {
55 ip Addr
56 next Addr
57 prev Addr
58 }{
59 {mustIP("10.0.0.1"), mustIP("10.0.0.2"), mustIP("10.0.0.0")},
60 {mustIP("10.0.0.255"), mustIP("10.0.1.0"), mustIP("10.0.0.254")},
61 {mustIP("127.0.0.1"), mustIP("127.0.0.2"), mustIP("127.0.0.0")},
62 {mustIP("254.255.255.255"), mustIP("255.0.0.0"), mustIP("254.255.255.254")},
63 {mustIP("255.255.255.255"), Addr{}, mustIP("255.255.255.254")},
64 {mustIP("0.0.0.0"), mustIP("0.0.0.1"), Addr{}},
65 {mustIP("::"), mustIP("::1"), Addr{}},
66 {mustIP("::%x"), mustIP("::1%x"), Addr{}},
67 {mustIP("::1"), mustIP("::2"), mustIP("::")},
68 {mustIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"), Addr{}, mustIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe")},
69 }
70
71 func TestIPNextPrev(t *testing.T) {
72 doNextPrev(t)
73
74 for _, ip := range []Addr{
75 mustIP("0.0.0.0"),
76 mustIP("::"),
77 } {
78 got := ip.Prev()
79 if !got.isZero() {
80 t.Errorf("IP(%v).Prev = %v; want zero", ip, got)
81 }
82 }
83
84 var allFF [16]byte
85 for i := range allFF {
86 allFF[i] = 0xff
87 }
88
89 for _, ip := range []Addr{
90 mustIP("255.255.255.255"),
91 AddrFrom16(allFF),
92 } {
93 got := ip.Next()
94 if !got.isZero() {
95 t.Errorf("IP(%v).Next = %v; want zero", ip, got)
96 }
97 }
98 }
99
100 func BenchmarkIPNextPrev(b *testing.B) {
101 for i := 0; i < b.N; i++ {
102 doNextPrev(b)
103 }
104 }
105
106 func doNextPrev(t testing.TB) {
107 for _, tt := range nextPrevTests {
108 gnext, gprev := tt.ip.Next(), tt.ip.Prev()
109 if gnext != tt.next {
110 t.Errorf("IP(%v).Next = %v; want %v", tt.ip, gnext, tt.next)
111 }
112 if gprev != tt.prev {
113 t.Errorf("IP(%v).Prev = %v; want %v", tt.ip, gprev, tt.prev)
114 }
115 if !tt.ip.Next().isZero() && tt.ip.Next().Prev() != tt.ip {
116 t.Errorf("IP(%v).Next.Prev = %v; want %v", tt.ip, tt.ip.Next().Prev(), tt.ip)
117 }
118 if !tt.ip.Prev().isZero() && tt.ip.Prev().Next() != tt.ip {
119 t.Errorf("IP(%v).Prev.Next = %v; want %v", tt.ip, tt.ip.Prev().Next(), tt.ip)
120 }
121 }
122 }
123
124 func TestIPBitLen(t *testing.T) {
125 tests := []struct {
126 ip Addr
127 want int
128 }{
129 {Addr{}, 0},
130 {mustIP("0.0.0.0"), 32},
131 {mustIP("10.0.0.1"), 32},
132 {mustIP("::"), 128},
133 {mustIP("fed0::1"), 128},
134 {mustIP("::ffff:10.0.0.1"), 128},
135 }
136 for _, tt := range tests {
137 got := tt.ip.BitLen()
138 if got != tt.want {
139 t.Errorf("BitLen(%v) = %d; want %d", tt.ip, got, tt.want)
140 }
141 }
142 }
143
144 func TestPrefixContains(t *testing.T) {
145 tests := []struct {
146 ipp Prefix
147 ip Addr
148 want bool
149 }{
150 {mustPrefix("9.8.7.6/0"), mustIP("9.8.7.6"), true},
151 {mustPrefix("9.8.7.6/16"), mustIP("9.8.7.6"), true},
152 {mustPrefix("9.8.7.6/16"), mustIP("9.8.6.4"), true},
153 {mustPrefix("9.8.7.6/16"), mustIP("9.9.7.6"), false},
154 {mustPrefix("9.8.7.6/32"), mustIP("9.8.7.6"), true},
155 {mustPrefix("9.8.7.6/32"), mustIP("9.8.7.7"), false},
156 {mustPrefix("9.8.7.6/32"), mustIP("9.8.7.7"), false},
157 {mustPrefix("::1/0"), mustIP("::1"), true},
158 {mustPrefix("::1/0"), mustIP("::2"), true},
159 {mustPrefix("::1/127"), mustIP("::1"), true},
160 {mustPrefix("::1/127"), mustIP("::2"), false},
161 {mustPrefix("::1/128"), mustIP("::1"), true},
162 {mustPrefix("::1/127"), mustIP("::2"), false},
163
164 {mustPrefix("::1%a/128"), mustIP("::1"), true},
165 {mustPrefix("::1%a/128"), mustIP("::1%a"), false},
166
167 {mustPrefix("::1/0"), Addr{}, false},
168 {mustPrefix("1.2.3.4/0"), Addr{}, false},
169
170 {Prefix{mustIP("::1"), 129}, mustIP("::1"), false},
171 {Prefix{mustIP("1.2.3.4"), 33}, mustIP("1.2.3.4"), false},
172 {Prefix{Addr{}, 0}, mustIP("1.2.3.4"), false},
173 {Prefix{Addr{}, 32}, mustIP("1.2.3.4"), false},
174 {Prefix{Addr{}, 128}, mustIP("::1"), false},
175
176 {mustPrefix("::1/0"), mustIP("1.2.3.4"), false},
177 {mustPrefix("1.2.3.4/0"), mustIP("::1"), false},
178 }
179 for _, tt := range tests {
180 got := tt.ipp.Contains(tt.ip)
181 if got != tt.want {
182 t.Errorf("(%v).Contains(%v) = %v want %v", tt.ipp, tt.ip, got, tt.want)
183 }
184 }
185 }
186
187 func TestParseIPError(t *testing.T) {
188 tests := []struct {
189 ip string
190 errstr string
191 }{
192 {
193 ip: "localhost",
194 },
195 {
196 ip: "500.0.0.1",
197 errstr: "field has value >255",
198 },
199 {
200 ip: "::gggg%eth0",
201 errstr: "must have at least one digit",
202 },
203 {
204 ip: "fe80::1cc0:3e8c:119f:c2e1%",
205 errstr: "zone must be a non-empty string",
206 },
207 {
208 ip: "%eth0",
209 errstr: "missing IPv6 address",
210 },
211 }
212 for _, test := range tests {
213 t.Run(test.ip, func(t *testing.T) {
214 _, err := ParseAddr(test.ip)
215 if err == nil {
216 t.Fatal("no error")
217 }
218 if _, ok := err.(parseAddrError); !ok {
219 t.Errorf("error type is %T, want parseIPError", err)
220 }
221 if test.errstr == "" {
222 test.errstr = "unable to parse IP"
223 }
224 if got := err.Error(); !strings.Contains(got, test.errstr) {
225 t.Errorf("error is missing substring %q: %s", test.errstr, got)
226 }
227 })
228 }
229 }
230
231 func TestParseAddrPort(t *testing.T) {
232 tests := []struct {
233 in string
234 want AddrPort
235 wantErr bool
236 }{
237 {in: "1.2.3.4:1234", want: AddrPort{mustIP("1.2.3.4"), 1234}},
238 {in: "1.1.1.1:123456", wantErr: true},
239 {in: "1.1.1.1:-123", wantErr: true},
240 {in: "[::1]:1234", want: AddrPort{mustIP("::1"), 1234}},
241 {in: "[1.2.3.4]:1234", wantErr: true},
242 {in: "fe80::1:1234", wantErr: true},
243 {in: ":0", wantErr: true},
244 }
245 for _, test := range tests {
246 t.Run(test.in, func(t *testing.T) {
247 got, err := ParseAddrPort(test.in)
248 if err != nil {
249 if test.wantErr {
250 return
251 }
252 t.Fatal(err)
253 }
254 if got != test.want {
255 t.Errorf("got %v; want %v", got, test.want)
256 }
257 if got.String() != test.in {
258 t.Errorf("String = %q; want %q", got.String(), test.in)
259 }
260 })
261
262 t.Run(test.in+"/AppendTo", func(t *testing.T) {
263 got, err := ParseAddrPort(test.in)
264 if err == nil {
265 testAppendToMarshal(t, got)
266 }
267 })
268
269
270
271
272 t.Run(test.in+"/Marshal", func(t *testing.T) {
273 var got AddrPort
274 jsin := `"` + test.in + `"`
275 err := json.Unmarshal([]byte(jsin), &got)
276 if err != nil {
277 if test.wantErr {
278 return
279 }
280 t.Fatal(err)
281 }
282 if got != test.want {
283 t.Errorf("got %v; want %v", got, test.want)
284 }
285 gotb, err := json.Marshal(got)
286 if err != nil {
287 t.Fatal(err)
288 }
289 if string(gotb) != jsin {
290 t.Errorf("Marshal = %q; want %q", string(gotb), jsin)
291 }
292 })
293 }
294 }
295
296 func TestAddrPortMarshalUnmarshal(t *testing.T) {
297 tests := []struct {
298 in string
299 want AddrPort
300 }{
301 {"", AddrPort{}},
302 }
303
304 for _, test := range tests {
305 t.Run(test.in, func(t *testing.T) {
306 orig := `"` + test.in + `"`
307
308 var ipp AddrPort
309 if err := json.Unmarshal([]byte(orig), &ipp); err != nil {
310 t.Fatalf("failed to unmarshal: %v", err)
311 }
312
313 ippb, err := json.Marshal(ipp)
314 if err != nil {
315 t.Fatalf("failed to marshal: %v", err)
316 }
317
318 back := string(ippb)
319 if orig != back {
320 t.Errorf("Marshal = %q; want %q", back, orig)
321 }
322
323 testAppendToMarshal(t, ipp)
324 })
325 }
326 }
327
328 type appendMarshaler interface {
329 encoding.TextMarshaler
330 AppendTo([]byte) []byte
331 }
332
333
334
335 func testAppendToMarshal(t *testing.T, x appendMarshaler) {
336 t.Helper()
337 m, err := x.MarshalText()
338 if err != nil {
339 t.Fatalf("(%v).MarshalText: %v", x, err)
340 }
341 a := make([]byte, 0, len(m))
342 a = x.AppendTo(a)
343 if !bytes.Equal(m, a) {
344 t.Errorf("(%v).MarshalText = %q, (%v).AppendTo = %q", x, m, x, a)
345 }
346 }
347
348 func TestIPv6Accessor(t *testing.T) {
349 var a [16]byte
350 for i := range a {
351 a[i] = uint8(i) + 1
352 }
353 ip := AddrFrom16(a)
354 for i := range a {
355 if got, want := ip.v6(uint8(i)), uint8(i)+1; got != want {
356 t.Errorf("v6(%v) = %v; want %v", i, got, want)
357 }
358 }
359 }
360
View as plain text