Source file
src/net/interface_test.go
1
2
3
4
5 package net
6
7 import (
8 "fmt"
9 "reflect"
10 "runtime"
11 "testing"
12 )
13
14
15
16
17 func loopbackInterface() *Interface {
18 ift, err := Interfaces()
19 if err != nil {
20 return nil
21 }
22 for _, ifi := range ift {
23 if ifi.Flags&FlagLoopback != 0 && ifi.Flags&FlagUp != 0 {
24 return &ifi
25 }
26 }
27 return nil
28 }
29
30
31
32
33 func ipv6LinkLocalUnicastAddr(ifi *Interface) string {
34 if ifi == nil {
35 return ""
36 }
37 ifat, err := ifi.Addrs()
38 if err != nil {
39 return ""
40 }
41 for _, ifa := range ifat {
42 if ifa, ok := ifa.(*IPNet); ok {
43 if ifa.IP.To4() == nil && ifa.IP.IsLinkLocalUnicast() {
44 return ifa.IP.String()
45 }
46 }
47 }
48 return ""
49 }
50
51 func TestInterfaces(t *testing.T) {
52 ift, err := Interfaces()
53 if err != nil {
54 t.Fatal(err)
55 }
56 for _, ifi := range ift {
57 ifxi, err := InterfaceByIndex(ifi.Index)
58 if err != nil {
59 t.Fatal(err)
60 }
61 switch runtime.GOOS {
62 case "solaris", "illumos":
63 if ifxi.Index != ifi.Index {
64 t.Errorf("got %v; want %v", ifxi, ifi)
65 }
66 default:
67 if !reflect.DeepEqual(ifxi, &ifi) {
68 t.Errorf("got %v; want %v", ifxi, ifi)
69 }
70 }
71 if ifi.Name != "" {
72 ifxn, err := InterfaceByName(ifi.Name)
73 if err != nil {
74 t.Fatal(err)
75 }
76 if !reflect.DeepEqual(ifxn, &ifi) {
77 t.Errorf("got %v; want %v", ifxn, ifi)
78 }
79 }
80 t.Logf("%s: flags=%v index=%d mtu=%d hwaddr=%v", ifi.Name, ifi.Flags, ifi.Index, ifi.MTU, ifi.HardwareAddr)
81 }
82 }
83
84 func TestInterfaceAddrs(t *testing.T) {
85 ift, err := Interfaces()
86 if err != nil {
87 t.Fatal(err)
88 }
89 ifStats := interfaceStats(ift)
90 ifat, err := InterfaceAddrs()
91 if err != nil {
92 t.Fatal(err)
93 }
94 uniStats, err := validateInterfaceUnicastAddrs(ifat)
95 if err != nil {
96 t.Fatal(err)
97 }
98 if err := checkUnicastStats(ifStats, uniStats); err != nil {
99 t.Fatal(err)
100 }
101 }
102
103 func TestInterfaceUnicastAddrs(t *testing.T) {
104 ift, err := Interfaces()
105 if err != nil {
106 t.Fatal(err)
107 }
108 ifStats := interfaceStats(ift)
109 if err != nil {
110 t.Fatal(err)
111 }
112 var uniStats routeStats
113 for _, ifi := range ift {
114 ifat, err := ifi.Addrs()
115 if err != nil {
116 t.Fatal(ifi, err)
117 }
118 stats, err := validateInterfaceUnicastAddrs(ifat)
119 if err != nil {
120 t.Fatal(ifi, err)
121 }
122 uniStats.ipv4 += stats.ipv4
123 uniStats.ipv6 += stats.ipv6
124 }
125 if err := checkUnicastStats(ifStats, &uniStats); err != nil {
126 t.Fatal(err)
127 }
128 }
129
130 func TestInterfaceMulticastAddrs(t *testing.T) {
131 ift, err := Interfaces()
132 if err != nil {
133 t.Fatal(err)
134 }
135 ifStats := interfaceStats(ift)
136 ifat, err := InterfaceAddrs()
137 if err != nil {
138 t.Fatal(err)
139 }
140 uniStats, err := validateInterfaceUnicastAddrs(ifat)
141 if err != nil {
142 t.Fatal(err)
143 }
144 var multiStats routeStats
145 for _, ifi := range ift {
146 ifmat, err := ifi.MulticastAddrs()
147 if err != nil {
148 t.Fatal(ifi, err)
149 }
150 stats, err := validateInterfaceMulticastAddrs(ifmat)
151 if err != nil {
152 t.Fatal(ifi, err)
153 }
154 multiStats.ipv4 += stats.ipv4
155 multiStats.ipv6 += stats.ipv6
156 }
157 if err := checkMulticastStats(ifStats, uniStats, &multiStats); err != nil {
158 t.Fatal(err)
159 }
160 }
161
162 type ifStats struct {
163 loop int
164 other int
165 }
166
167 func interfaceStats(ift []Interface) *ifStats {
168 var stats ifStats
169 for _, ifi := range ift {
170 if ifi.Flags&FlagUp != 0 {
171 if ifi.Flags&FlagLoopback != 0 {
172 stats.loop++
173 } else {
174 stats.other++
175 }
176 }
177 }
178 return &stats
179 }
180
181 type routeStats struct {
182 ipv4, ipv6 int
183 }
184
185 func validateInterfaceUnicastAddrs(ifat []Addr) (*routeStats, error) {
186
187
188
189
190
191
192 stats := new(routeStats)
193 for _, ifa := range ifat {
194 switch ifa := ifa.(type) {
195 case *IPNet:
196 if ifa == nil || ifa.IP == nil || ifa.IP.IsMulticast() || ifa.Mask == nil {
197 return nil, fmt.Errorf("unexpected value: %#v", ifa)
198 }
199 if len(ifa.IP) != IPv6len {
200 return nil, fmt.Errorf("should be internal representation either IPv6 or IPv4-mapped IPv6 address: %#v", ifa)
201 }
202 prefixLen, maxPrefixLen := ifa.Mask.Size()
203 if ifa.IP.To4() != nil {
204 if 0 >= prefixLen || prefixLen > 8*IPv4len || maxPrefixLen != 8*IPv4len {
205 return nil, fmt.Errorf("unexpected prefix length: %d/%d for %#v", prefixLen, maxPrefixLen, ifa)
206 }
207 if ifa.IP.IsLoopback() && prefixLen < 8 {
208 return nil, fmt.Errorf("unexpected prefix length: %d/%d for %#v", prefixLen, maxPrefixLen, ifa)
209 }
210 stats.ipv4++
211 }
212 if ifa.IP.To16() != nil && ifa.IP.To4() == nil {
213 if 0 >= prefixLen || prefixLen > 8*IPv6len || maxPrefixLen != 8*IPv6len {
214 return nil, fmt.Errorf("unexpected prefix length: %d/%d for %#v", prefixLen, maxPrefixLen, ifa)
215 }
216 if ifa.IP.IsLoopback() && prefixLen != 8*IPv6len {
217 return nil, fmt.Errorf("unexpected prefix length: %d/%d for %#v", prefixLen, maxPrefixLen, ifa)
218 }
219 stats.ipv6++
220 }
221 case *IPAddr:
222 if ifa == nil || ifa.IP == nil || ifa.IP.IsMulticast() {
223 return nil, fmt.Errorf("unexpected value: %#v", ifa)
224 }
225 if len(ifa.IP) != IPv6len {
226 return nil, fmt.Errorf("should be internal representation either IPv6 or IPv4-mapped IPv6 address: %#v", ifa)
227 }
228 if ifa.IP.To4() != nil {
229 stats.ipv4++
230 }
231 if ifa.IP.To16() != nil && ifa.IP.To4() == nil {
232 stats.ipv6++
233 }
234 default:
235 return nil, fmt.Errorf("unexpected type: %T", ifa)
236 }
237 }
238 return stats, nil
239 }
240
241 func validateInterfaceMulticastAddrs(ifat []Addr) (*routeStats, error) {
242 stats := new(routeStats)
243 for _, ifa := range ifat {
244 switch ifa := ifa.(type) {
245 case *IPAddr:
246 if ifa == nil || ifa.IP == nil || ifa.IP.IsUnspecified() || !ifa.IP.IsMulticast() {
247 return nil, fmt.Errorf("unexpected value: %#v", ifa)
248 }
249 if len(ifa.IP) != IPv6len {
250 return nil, fmt.Errorf("should be internal representation either IPv6 or IPv4-mapped IPv6 address: %#v", ifa)
251 }
252 if ifa.IP.To4() != nil {
253 stats.ipv4++
254 }
255 if ifa.IP.To16() != nil && ifa.IP.To4() == nil {
256 stats.ipv6++
257 }
258 default:
259 return nil, fmt.Errorf("unexpected type: %T", ifa)
260 }
261 }
262 return stats, nil
263 }
264
265 func checkUnicastStats(ifStats *ifStats, uniStats *routeStats) error {
266
267 if supportsIPv4() && ifStats.loop+ifStats.other > 0 && uniStats.ipv4 == 0 {
268 return fmt.Errorf("num IPv4 unicast routes = 0; want >0; summary: %+v, %+v", ifStats, uniStats)
269 }
270
271
272
273 if supportsIPv6() && ifStats.loop > 0 && uniStats.ipv6 == 0 {
274 return fmt.Errorf("num IPv6 unicast routes = 0; want >0; summary: %+v, %+v", ifStats, uniStats)
275 }
276 return nil
277 }
278
279 func checkMulticastStats(ifStats *ifStats, uniStats, multiStats *routeStats) error {
280 switch runtime.GOOS {
281 case "aix", "dragonfly", "netbsd", "openbsd", "plan9", "solaris", "illumos":
282 default:
283
284
285
286
287
288
289
290
291
292
293
294
295 if supportsIPv6() && ifStats.loop > 0 && uniStats.ipv6 > 1 && multiStats.ipv6 == 0 {
296 return fmt.Errorf("num IPv6 multicast route clones = 0; want >0; summary: %+v, %+v, %+v", ifStats, uniStats, multiStats)
297 }
298 }
299 return nil
300 }
301
302 func BenchmarkInterfaces(b *testing.B) {
303 b.ReportAllocs()
304 testHookUninstaller.Do(uninstallTestHooks)
305
306 for i := 0; i < b.N; i++ {
307 if _, err := Interfaces(); err != nil {
308 b.Fatal(err)
309 }
310 }
311 }
312
313 func BenchmarkInterfaceByIndex(b *testing.B) {
314 b.ReportAllocs()
315 testHookUninstaller.Do(uninstallTestHooks)
316
317 ifi := loopbackInterface()
318 if ifi == nil {
319 b.Skip("loopback interface not found")
320 }
321 for i := 0; i < b.N; i++ {
322 if _, err := InterfaceByIndex(ifi.Index); err != nil {
323 b.Fatal(err)
324 }
325 }
326 }
327
328 func BenchmarkInterfaceByName(b *testing.B) {
329 b.ReportAllocs()
330 testHookUninstaller.Do(uninstallTestHooks)
331
332 ifi := loopbackInterface()
333 if ifi == nil {
334 b.Skip("loopback interface not found")
335 }
336 for i := 0; i < b.N; i++ {
337 if _, err := InterfaceByName(ifi.Name); err != nil {
338 b.Fatal(err)
339 }
340 }
341 }
342
343 func BenchmarkInterfaceAddrs(b *testing.B) {
344 b.ReportAllocs()
345 testHookUninstaller.Do(uninstallTestHooks)
346
347 for i := 0; i < b.N; i++ {
348 if _, err := InterfaceAddrs(); err != nil {
349 b.Fatal(err)
350 }
351 }
352 }
353
354 func BenchmarkInterfacesAndAddrs(b *testing.B) {
355 b.ReportAllocs()
356 testHookUninstaller.Do(uninstallTestHooks)
357
358 ifi := loopbackInterface()
359 if ifi == nil {
360 b.Skip("loopback interface not found")
361 }
362 for i := 0; i < b.N; i++ {
363 if _, err := ifi.Addrs(); err != nil {
364 b.Fatal(err)
365 }
366 }
367 }
368
369 func BenchmarkInterfacesAndMulticastAddrs(b *testing.B) {
370 b.ReportAllocs()
371 testHookUninstaller.Do(uninstallTestHooks)
372
373 ifi := loopbackInterface()
374 if ifi == nil {
375 b.Skip("loopback interface not found")
376 }
377 for i := 0; i < b.N; i++ {
378 if _, err := ifi.MulticastAddrs(); err != nil {
379 b.Fatal(err)
380 }
381 }
382 }
383
View as plain text