Imported Upstream version 4.7.2
[platform/upstream/gcc48.git] / libgo / go / net / multicast_test.go
1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package net
6
7 import (
8         "errors"
9         "os"
10         "runtime"
11         "syscall"
12         "testing"
13 )
14
15 var multicastListenerTests = []struct {
16         net   string
17         gaddr *UDPAddr
18         flags Flags
19         ipv6  bool // test with underlying AF_INET6 socket
20 }{
21         // cf. RFC 4727: Experimental Values in IPv4, IPv6, ICMPv4, ICMPv6, UDP, and TCP Headers
22
23         {"udp", &UDPAddr{IPv4(224, 0, 0, 254), 12345}, FlagUp | FlagLoopback, false},
24         {"udp", &UDPAddr{IPv4(224, 0, 0, 254), 12345}, 0, false},
25         {"udp", &UDPAddr{ParseIP("ff0e::114"), 12345}, FlagUp | FlagLoopback, true},
26         {"udp", &UDPAddr{ParseIP("ff0e::114"), 12345}, 0, true},
27
28         {"udp4", &UDPAddr{IPv4(224, 0, 0, 254), 12345}, FlagUp | FlagLoopback, false},
29         {"udp4", &UDPAddr{IPv4(224, 0, 0, 254), 12345}, 0, false},
30
31         {"udp6", &UDPAddr{ParseIP("ff01::114"), 12345}, FlagUp | FlagLoopback, true},
32         {"udp6", &UDPAddr{ParseIP("ff01::114"), 12345}, 0, true},
33         {"udp6", &UDPAddr{ParseIP("ff02::114"), 12345}, FlagUp | FlagLoopback, true},
34         {"udp6", &UDPAddr{ParseIP("ff02::114"), 12345}, 0, true},
35         {"udp6", &UDPAddr{ParseIP("ff04::114"), 12345}, FlagUp | FlagLoopback, true},
36         {"udp6", &UDPAddr{ParseIP("ff04::114"), 12345}, 0, true},
37         {"udp6", &UDPAddr{ParseIP("ff05::114"), 12345}, FlagUp | FlagLoopback, true},
38         {"udp6", &UDPAddr{ParseIP("ff05::114"), 12345}, 0, true},
39         {"udp6", &UDPAddr{ParseIP("ff08::114"), 12345}, FlagUp | FlagLoopback, true},
40         {"udp6", &UDPAddr{ParseIP("ff08::114"), 12345}, 0, true},
41         {"udp6", &UDPAddr{ParseIP("ff0e::114"), 12345}, FlagUp | FlagLoopback, true},
42         {"udp6", &UDPAddr{ParseIP("ff0e::114"), 12345}, 0, true},
43 }
44
45 // TestMulticastListener tests both single and double listen to a test
46 // listener with same address family, same group address and same port.
47 func TestMulticastListener(t *testing.T) {
48         switch runtime.GOOS {
49         case "netbsd", "openbsd", "plan9", "solaris", "windows":
50                 t.Logf("skipping test on %q", runtime.GOOS)
51                 return
52         case "linux":
53                 if runtime.GOARCH == "arm" || runtime.GOARCH == "alpha" {
54                         t.Logf("skipping test on %q/%q", runtime.GOOS, runtime.GOARCH)
55                         return
56                 }
57         }
58
59         for _, tt := range multicastListenerTests {
60                 if tt.ipv6 && (!supportsIPv6 || os.Getuid() != 0) {
61                         continue
62                 }
63                 ifi, err := availMulticastInterface(t, tt.flags)
64                 if err != nil {
65                         continue
66                 }
67                 c1, err := ListenMulticastUDP(tt.net, ifi, tt.gaddr)
68                 if err != nil {
69                         t.Fatalf("First ListenMulticastUDP failed: %v", err)
70                 }
71                 checkMulticastListener(t, err, c1, tt.gaddr)
72                 c2, err := ListenMulticastUDP(tt.net, ifi, tt.gaddr)
73                 if err != nil {
74                         t.Fatalf("Second ListenMulticastUDP failed: %v", err)
75                 }
76                 checkMulticastListener(t, err, c2, tt.gaddr)
77                 c2.Close()
78                 switch c1.fd.family {
79                 case syscall.AF_INET:
80                         testIPv4MulticastSocketOptions(t, c1.fd, ifi)
81                 case syscall.AF_INET6:
82                         testIPv6MulticastSocketOptions(t, c1.fd, ifi)
83                 }
84                 c1.Close()
85         }
86 }
87
88 func TestSimpleMulticastListener(t *testing.T) {
89         switch runtime.GOOS {
90         case "plan9":
91                 t.Logf("skipping test on %q", runtime.GOOS)
92                 return
93         case "windows":
94                 if testing.Short() || !*testExternal {
95                         t.Logf("skipping test on windows to avoid firewall")
96                         return
97                 }
98         }
99
100         for _, tt := range multicastListenerTests {
101                 if tt.ipv6 {
102                         continue
103                 }
104                 tt.flags = FlagUp | FlagMulticast // for windows testing
105                 ifi, err := availMulticastInterface(t, tt.flags)
106                 if err != nil {
107                         continue
108                 }
109                 c1, err := ListenMulticastUDP(tt.net, ifi, tt.gaddr)
110                 if err != nil {
111                         t.Fatalf("First ListenMulticastUDP failed: %v", err)
112                 }
113                 checkSimpleMulticastListener(t, err, c1, tt.gaddr)
114                 c2, err := ListenMulticastUDP(tt.net, ifi, tt.gaddr)
115                 if err != nil {
116                         t.Fatalf("Second ListenMulticastUDP failed: %v", err)
117                 }
118                 checkSimpleMulticastListener(t, err, c2, tt.gaddr)
119                 c2.Close()
120                 c1.Close()
121         }
122 }
123
124 func checkMulticastListener(t *testing.T, err error, c *UDPConn, gaddr *UDPAddr) {
125         if !multicastRIBContains(t, gaddr.IP) {
126                 t.Fatalf("%q not found in RIB", gaddr.String())
127         }
128         if c.LocalAddr().String() != gaddr.String() {
129                 t.Fatalf("LocalAddr returns %q, expected %q", c.LocalAddr().String(), gaddr.String())
130         }
131 }
132
133 func checkSimpleMulticastListener(t *testing.T, err error, c *UDPConn, gaddr *UDPAddr) {
134         if c.LocalAddr().String() != gaddr.String() {
135                 t.Fatalf("LocalAddr returns %q, expected %q", c.LocalAddr().String(), gaddr.String())
136         }
137 }
138
139 func availMulticastInterface(t *testing.T, flags Flags) (*Interface, error) {
140         var ifi *Interface
141         if flags != Flags(0) {
142                 ift, err := Interfaces()
143                 if err != nil {
144                         t.Fatalf("Interfaces failed: %v", err)
145                 }
146                 for _, x := range ift {
147                         if x.Flags&flags == flags {
148                                 ifi = &x
149                                 break
150                         }
151                 }
152                 if ifi == nil {
153                         return nil, errors.New("an appropriate multicast interface not found")
154                 }
155         }
156         return ifi, nil
157 }
158
159 func multicastRIBContains(t *testing.T, ip IP) bool {
160         ift, err := Interfaces()
161         if err != nil {
162                 t.Fatalf("Interfaces failed: %v", err)
163         }
164         for _, ifi := range ift {
165                 ifmat, err := ifi.MulticastAddrs()
166                 if err != nil {
167                         t.Fatalf("MulticastAddrs failed: %v", err)
168                 }
169                 for _, ifma := range ifmat {
170                         if ifma.(*IPAddr).IP.Equal(ip) {
171                                 return true
172                         }
173                 }
174         }
175         return false
176 }
177
178 func testIPv4MulticastSocketOptions(t *testing.T, fd *netFD, ifi *Interface) {
179         _, err := ipv4MulticastInterface(fd)
180         if err != nil {
181                 t.Fatalf("ipv4MulticastInterface failed: %v", err)
182         }
183         if ifi != nil {
184                 err = setIPv4MulticastInterface(fd, ifi)
185                 if err != nil {
186                         t.Fatalf("setIPv4MulticastInterface failed: %v", err)
187                 }
188         }
189         _, err = ipv4MulticastTTL(fd)
190         if err != nil {
191                 t.Fatalf("ipv4MulticastTTL failed: %v", err)
192         }
193         err = setIPv4MulticastTTL(fd, 1)
194         if err != nil {
195                 t.Fatalf("setIPv4MulticastTTL failed: %v", err)
196         }
197         _, err = ipv4MulticastLoopback(fd)
198         if err != nil {
199                 t.Fatalf("ipv4MulticastLoopback failed: %v", err)
200         }
201         err = setIPv4MulticastLoopback(fd, false)
202         if err != nil {
203                 t.Fatalf("setIPv4MulticastLoopback failed: %v", err)
204         }
205 }
206
207 func testIPv6MulticastSocketOptions(t *testing.T, fd *netFD, ifi *Interface) {
208         _, err := ipv6MulticastInterface(fd)
209         if err != nil {
210                 t.Fatalf("ipv6MulticastInterface failed: %v", err)
211         }
212         if ifi != nil {
213                 err = setIPv6MulticastInterface(fd, ifi)
214                 if err != nil {
215                         t.Fatalf("setIPv6MulticastInterface failed: %v", err)
216                 }
217         }
218         _, err = ipv6MulticastHopLimit(fd)
219         if err != nil {
220                 t.Fatalf("ipv6MulticastHopLimit failed: %v", err)
221         }
222         err = setIPv6MulticastHopLimit(fd, 1)
223         if err != nil {
224                 t.Fatalf("setIPv6MulticastHopLimit failed: %v", err)
225         }
226         _, err = ipv6MulticastLoopback(fd)
227         if err != nil {
228                 t.Fatalf("ipv6MulticastLoopback failed: %v", err)
229         }
230         err = setIPv6MulticastLoopback(fd, false)
231         if err != nil {
232                 t.Fatalf("setIPv6MulticastLoopback failed: %v", err)
233         }
234 }