github.com/spotify/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/net/multicast_test.go (about) 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 "fmt" 9 "os" 10 "runtime" 11 "testing" 12 ) 13 14 var ipv4MulticastListenerTests = []struct { 15 net string 16 gaddr *UDPAddr // see RFC 4727 17 }{ 18 {"udp", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}}, 19 20 {"udp4", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}}, 21 } 22 23 // TestIPv4MulticastListener tests both single and double listen to a 24 // test listener with same address family, same group address and same 25 // port. 26 func TestIPv4MulticastListener(t *testing.T) { 27 switch runtime.GOOS { 28 case "plan9": 29 t.Skipf("skipping test on %q", runtime.GOOS) 30 } 31 32 closer := func(cs []*UDPConn) { 33 for _, c := range cs { 34 if c != nil { 35 c.Close() 36 } 37 } 38 } 39 40 for _, ifi := range []*Interface{loopbackInterface(), nil} { 41 // Note that multicast interface assignment by system 42 // is not recommended because it usually relies on 43 // routing stuff for finding out an appropriate 44 // nexthop containing both network and link layer 45 // adjacencies. 46 if ifi == nil && !*testExternal { 47 continue 48 } 49 for _, tt := range ipv4MulticastListenerTests { 50 var err error 51 cs := make([]*UDPConn, 2) 52 if cs[0], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil { 53 t.Fatalf("First ListenMulticastUDP on %v failed: %v", ifi, err) 54 } 55 if err := checkMulticastListener(cs[0], tt.gaddr.IP); err != nil { 56 closer(cs) 57 t.Fatal(err) 58 } 59 if cs[1], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil { 60 closer(cs) 61 t.Fatalf("Second ListenMulticastUDP on %v failed: %v", ifi, err) 62 } 63 if err := checkMulticastListener(cs[1], tt.gaddr.IP); err != nil { 64 closer(cs) 65 t.Fatal(err) 66 } 67 closer(cs) 68 } 69 } 70 } 71 72 var ipv6MulticastListenerTests = []struct { 73 net string 74 gaddr *UDPAddr // see RFC 4727 75 }{ 76 {"udp", &UDPAddr{IP: ParseIP("ff01::114"), Port: 12345}}, 77 {"udp", &UDPAddr{IP: ParseIP("ff02::114"), Port: 12345}}, 78 {"udp", &UDPAddr{IP: ParseIP("ff04::114"), Port: 12345}}, 79 {"udp", &UDPAddr{IP: ParseIP("ff05::114"), Port: 12345}}, 80 {"udp", &UDPAddr{IP: ParseIP("ff08::114"), Port: 12345}}, 81 {"udp", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}}, 82 83 {"udp6", &UDPAddr{IP: ParseIP("ff01::114"), Port: 12345}}, 84 {"udp6", &UDPAddr{IP: ParseIP("ff02::114"), Port: 12345}}, 85 {"udp6", &UDPAddr{IP: ParseIP("ff04::114"), Port: 12345}}, 86 {"udp6", &UDPAddr{IP: ParseIP("ff05::114"), Port: 12345}}, 87 {"udp6", &UDPAddr{IP: ParseIP("ff08::114"), Port: 12345}}, 88 {"udp6", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}}, 89 } 90 91 // TestIPv6MulticastListener tests both single and double listen to a 92 // test listener with same address family, same group address and same 93 // port. 94 func TestIPv6MulticastListener(t *testing.T) { 95 switch runtime.GOOS { 96 case "plan9", "solaris": 97 t.Skipf("skipping test on %q", runtime.GOOS) 98 } 99 if !supportsIPv6 { 100 t.Skip("ipv6 is not supported") 101 } 102 if os.Getuid() != 0 { 103 t.Skip("skipping test; must be root") 104 } 105 106 closer := func(cs []*UDPConn) { 107 for _, c := range cs { 108 if c != nil { 109 c.Close() 110 } 111 } 112 } 113 114 for _, ifi := range []*Interface{loopbackInterface(), nil} { 115 // Note that multicast interface assignment by system 116 // is not recommended because it usually relies on 117 // routing stuff for finding out an appropriate 118 // nexthop containing both network and link layer 119 // adjacencies. 120 if ifi == nil && (!*testExternal || !*testIPv6) { 121 continue 122 } 123 for _, tt := range ipv6MulticastListenerTests { 124 var err error 125 cs := make([]*UDPConn, 2) 126 if cs[0], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil { 127 t.Fatalf("First ListenMulticastUDP on %v failed: %v", ifi, err) 128 } 129 if err := checkMulticastListener(cs[0], tt.gaddr.IP); err != nil { 130 closer(cs) 131 t.Fatal(err) 132 } 133 if cs[1], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil { 134 closer(cs) 135 t.Fatalf("Second ListenMulticastUDP on %v failed: %v", ifi, err) 136 } 137 if err := checkMulticastListener(cs[1], tt.gaddr.IP); err != nil { 138 closer(cs) 139 t.Fatal(err) 140 } 141 closer(cs) 142 } 143 } 144 } 145 146 func checkMulticastListener(c *UDPConn, ip IP) error { 147 if ok, err := multicastRIBContains(ip); err != nil { 148 return err 149 } else if !ok { 150 return fmt.Errorf("%q not found in multicast RIB", ip.String()) 151 } 152 la := c.LocalAddr() 153 if la, ok := la.(*UDPAddr); !ok || la.Port == 0 { 154 return fmt.Errorf("got %v; expected a proper address with non-zero port number", la) 155 } 156 return nil 157 } 158 159 func multicastRIBContains(ip IP) (bool, error) { 160 switch runtime.GOOS { 161 case "dragonfly", "netbsd", "openbsd", "plan9", "solaris", "windows": 162 return true, nil // not implemented yet 163 case "linux": 164 if runtime.GOARCH == "arm" || runtime.GOARCH == "alpha" { 165 return true, nil // not implemented yet 166 } 167 } 168 ift, err := Interfaces() 169 if err != nil { 170 return false, err 171 } 172 for _, ifi := range ift { 173 ifmat, err := ifi.MulticastAddrs() 174 if err != nil { 175 return false, err 176 } 177 for _, ifma := range ifmat { 178 if ifma.(*IPAddr).IP.Equal(ip) { 179 return true, nil 180 } 181 } 182 } 183 return false, nil 184 }