1 // Copyright 2012 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 "reflect" 9 "runtime" 10 "testing" 11 "time" 12 ) 13 14 type resolveUDPAddrTest struct { 15 network string 16 litAddrOrName string 17 addr *UDPAddr 18 err error 19 } 20 21 var resolveUDPAddrTests = []resolveUDPAddrTest{ 22 {"udp", "127.0.0.1:0", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, 23 {"udp4", "127.0.0.1:65535", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 65535}, nil}, 24 25 {"udp", "[::1]:0", &UDPAddr{IP: ParseIP("::1"), Port: 0}, nil}, 26 {"udp6", "[::1]:65535", &UDPAddr{IP: ParseIP("::1"), Port: 65535}, nil}, 27 28 {"udp", "[::1%en0]:1", &UDPAddr{IP: ParseIP("::1"), Port: 1, Zone: "en0"}, nil}, 29 {"udp6", "[::1%911]:2", &UDPAddr{IP: ParseIP("::1"), Port: 2, Zone: "911"}, nil}, 30 31 {"", "127.0.0.1:0", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, // Go 1.0 behavior 32 {"", "[::1]:0", &UDPAddr{IP: ParseIP("::1"), Port: 0}, nil}, // Go 1.0 behavior 33 34 {"udp", ":12345", &UDPAddr{Port: 12345}, nil}, 35 36 {"http", "127.0.0.1:0", nil, UnknownNetworkError("http")}, 37 } 38 39 func TestResolveUDPAddr(t *testing.T) { 40 origTestHookLookupIP := testHookLookupIP 41 defer func() { testHookLookupIP = origTestHookLookupIP }() 42 testHookLookupIP = lookupLocalhost 43 44 for i, tt := range resolveUDPAddrTests { 45 addr, err := ResolveUDPAddr(tt.network, tt.litAddrOrName) 46 if err != tt.err { 47 t.Errorf("#%d: %v", i, err) 48 } else if !reflect.DeepEqual(addr, tt.addr) { 49 t.Errorf("#%d: got %#v; want %#v", i, addr, tt.addr) 50 } 51 if err != nil { 52 continue 53 } 54 rtaddr, err := ResolveUDPAddr(addr.Network(), addr.String()) 55 if err != nil { 56 t.Errorf("#%d: %v", i, err) 57 } else if !reflect.DeepEqual(rtaddr, addr) { 58 t.Errorf("#%d: got %#v; want %#v", i, rtaddr, addr) 59 } 60 } 61 } 62 63 func TestWriteToUDP(t *testing.T) { 64 switch runtime.GOOS { 65 case "plan9": 66 t.Skipf("not supported on %s", runtime.GOOS) 67 } 68 69 c, err := ListenPacket("udp", "127.0.0.1:0") 70 if err != nil { 71 t.Fatal(err) 72 } 73 defer c.Close() 74 75 testWriteToConn(t, c.LocalAddr().String()) 76 testWriteToPacketConn(t, c.LocalAddr().String()) 77 } 78 79 func testWriteToConn(t *testing.T, raddr string) { 80 c, err := Dial("udp", raddr) 81 if err != nil { 82 t.Fatal(err) 83 } 84 defer c.Close() 85 86 ra, err := ResolveUDPAddr("udp", raddr) 87 if err != nil { 88 t.Fatal(err) 89 } 90 91 b := []byte("CONNECTED-MODE SOCKET") 92 _, err = c.(*UDPConn).WriteToUDP(b, ra) 93 if err == nil { 94 t.Fatal("should fail") 95 } 96 if err != nil && err.(*OpError).Err != ErrWriteToConnected { 97 t.Fatalf("should fail as ErrWriteToConnected: %v", err) 98 } 99 _, err = c.(*UDPConn).WriteTo(b, ra) 100 if err == nil { 101 t.Fatal("should fail") 102 } 103 if err != nil && err.(*OpError).Err != ErrWriteToConnected { 104 t.Fatalf("should fail as ErrWriteToConnected: %v", err) 105 } 106 _, err = c.Write(b) 107 if err != nil { 108 t.Fatal(err) 109 } 110 _, _, err = c.(*UDPConn).WriteMsgUDP(b, nil, ra) 111 if err == nil { 112 t.Fatal("should fail") 113 } 114 if err != nil && err.(*OpError).Err != ErrWriteToConnected { 115 t.Fatalf("should fail as ErrWriteToConnected: %v", err) 116 } 117 _, _, err = c.(*UDPConn).WriteMsgUDP(b, nil, nil) 118 switch runtime.GOOS { 119 case "nacl", "windows": // see golang.org/issue/9252 120 t.Skipf("not implemented yet on %s", runtime.GOOS) 121 default: 122 if err != nil { 123 t.Fatal(err) 124 } 125 } 126 } 127 128 func testWriteToPacketConn(t *testing.T, raddr string) { 129 c, err := ListenPacket("udp", "127.0.0.1:0") 130 if err != nil { 131 t.Fatal(err) 132 } 133 defer c.Close() 134 135 ra, err := ResolveUDPAddr("udp", raddr) 136 if err != nil { 137 t.Fatal(err) 138 } 139 140 b := []byte("UNCONNECTED-MODE SOCKET") 141 _, err = c.(*UDPConn).WriteToUDP(b, ra) 142 if err != nil { 143 t.Fatal(err) 144 } 145 _, err = c.WriteTo(b, ra) 146 if err != nil { 147 t.Fatal(err) 148 } 149 _, err = c.(*UDPConn).Write(b) 150 if err == nil { 151 t.Fatal("should fail") 152 } 153 _, _, err = c.(*UDPConn).WriteMsgUDP(b, nil, nil) 154 if err == nil { 155 t.Fatal("should fail") 156 } 157 if err != nil && err.(*OpError).Err != errMissingAddress { 158 t.Fatalf("should fail as errMissingAddress: %v", err) 159 } 160 _, _, err = c.(*UDPConn).WriteMsgUDP(b, nil, ra) 161 switch runtime.GOOS { 162 case "nacl", "windows": // see golang.org/issue/9252 163 t.Skipf("not implemented yet on %s", runtime.GOOS) 164 default: 165 if err != nil { 166 t.Fatal(err) 167 } 168 } 169 } 170 171 var udpConnLocalNameTests = []struct { 172 net string 173 laddr *UDPAddr 174 }{ 175 {"udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}}, 176 {"udp4", &UDPAddr{}}, 177 {"udp4", nil}, 178 } 179 180 func TestUDPConnLocalName(t *testing.T) { 181 if testing.Short() || !*testExternal { 182 t.Skip("avoid external network") 183 } 184 185 for _, tt := range udpConnLocalNameTests { 186 c, err := ListenUDP(tt.net, tt.laddr) 187 if err != nil { 188 t.Fatal(err) 189 } 190 defer c.Close() 191 la := c.LocalAddr() 192 if a, ok := la.(*UDPAddr); !ok || a.Port == 0 { 193 t.Fatalf("got %v; expected a proper address with non-zero port number", la) 194 } 195 } 196 } 197 198 func TestUDPConnLocalAndRemoteNames(t *testing.T) { 199 for _, laddr := range []string{"", "127.0.0.1:0"} { 200 c1, err := ListenPacket("udp", "127.0.0.1:0") 201 if err != nil { 202 t.Fatal(err) 203 } 204 defer c1.Close() 205 206 var la *UDPAddr 207 if laddr != "" { 208 var err error 209 if la, err = ResolveUDPAddr("udp", laddr); err != nil { 210 t.Fatal(err) 211 } 212 } 213 c2, err := DialUDP("udp", la, c1.LocalAddr().(*UDPAddr)) 214 if err != nil { 215 t.Fatal(err) 216 } 217 defer c2.Close() 218 219 var connAddrs = [4]struct { 220 got Addr 221 ok bool 222 }{ 223 {c1.LocalAddr(), true}, 224 {c1.(*UDPConn).RemoteAddr(), false}, 225 {c2.LocalAddr(), true}, 226 {c2.RemoteAddr(), true}, 227 } 228 for _, ca := range connAddrs { 229 if a, ok := ca.got.(*UDPAddr); ok != ca.ok || ok && a.Port == 0 { 230 t.Fatalf("got %v; expected a proper address with non-zero port number", ca.got) 231 } 232 } 233 } 234 } 235 236 func TestIPv6LinkLocalUnicastUDP(t *testing.T) { 237 if testing.Short() || !*testExternal { 238 t.Skip("avoid external network") 239 } 240 if !supportsIPv6 { 241 t.Skip("IPv6 is not supported") 242 } 243 244 for i, tt := range ipv6LinkLocalUnicastUDPTests { 245 c1, err := ListenPacket(tt.network, tt.address) 246 if err != nil { 247 // It might return "LookupHost returned no 248 // suitable address" error on some platforms. 249 t.Log(err) 250 continue 251 } 252 ls, err := (&packetListener{PacketConn: c1}).newLocalServer() 253 if err != nil { 254 t.Fatal(err) 255 } 256 defer ls.teardown() 257 ch := make(chan error, 1) 258 handler := func(ls *localPacketServer, c PacketConn) { packetTransponder(c, ch) } 259 if err := ls.buildup(handler); err != nil { 260 t.Fatal(err) 261 } 262 if la, ok := c1.LocalAddr().(*UDPAddr); !ok || !tt.nameLookup && la.Zone == "" { 263 t.Fatalf("got %v; expected a proper address with zone identifier", la) 264 } 265 266 c2, err := Dial(tt.network, ls.PacketConn.LocalAddr().String()) 267 if err != nil { 268 t.Fatal(err) 269 } 270 defer c2.Close() 271 if la, ok := c2.LocalAddr().(*UDPAddr); !ok || !tt.nameLookup && la.Zone == "" { 272 t.Fatalf("got %v; expected a proper address with zone identifier", la) 273 } 274 if ra, ok := c2.RemoteAddr().(*UDPAddr); !ok || !tt.nameLookup && ra.Zone == "" { 275 t.Fatalf("got %v; expected a proper address with zone identifier", ra) 276 } 277 278 if _, err := c2.Write([]byte("UDP OVER IPV6 LINKLOCAL TEST")); err != nil { 279 t.Fatal(err) 280 } 281 b := make([]byte, 32) 282 if _, err := c2.Read(b); err != nil { 283 t.Fatal(err) 284 } 285 286 for err := range ch { 287 t.Errorf("#%d: %v", i, err) 288 } 289 } 290 } 291 292 func TestUDPZeroBytePayload(t *testing.T) { 293 switch runtime.GOOS { 294 case "nacl", "plan9": 295 t.Skipf("not supported on %s", runtime.GOOS) 296 } 297 298 c, err := newLocalPacketListener("udp") 299 if err != nil { 300 t.Fatal(err) 301 } 302 defer c.Close() 303 304 for _, genericRead := range []bool{false, true} { 305 n, err := c.WriteTo(nil, c.LocalAddr()) 306 if err != nil { 307 t.Fatal(err) 308 } 309 if n != 0 { 310 t.Errorf("got %d; want 0", n) 311 } 312 c.SetReadDeadline(time.Now().Add(100 * time.Millisecond)) 313 var b [1]byte 314 if genericRead { 315 _, err = c.(Conn).Read(b[:]) 316 } else { 317 _, _, err = c.ReadFrom(b[:]) 318 } 319 switch err { 320 case nil: // ReadFrom succeeds 321 default: // Read may timeout, it depends on the platform 322 if nerr, ok := err.(Error); !ok || !nerr.Timeout() { 323 t.Fatal(err) 324 } 325 } 326 } 327 } 328 329 func TestUDPZeroByteBuffer(t *testing.T) { 330 switch runtime.GOOS { 331 case "nacl", "plan9": 332 t.Skipf("not supported on %s", runtime.GOOS) 333 } 334 335 c, err := newLocalPacketListener("udp") 336 if err != nil { 337 t.Fatal(err) 338 } 339 defer c.Close() 340 341 b := []byte("UDP ZERO BYTE BUFFER TEST") 342 for _, genericRead := range []bool{false, true} { 343 n, err := c.WriteTo(b, c.LocalAddr()) 344 if err != nil { 345 t.Fatal(err) 346 } 347 if n != len(b) { 348 t.Errorf("got %d; want %d", n, len(b)) 349 } 350 c.SetReadDeadline(time.Now().Add(100 * time.Millisecond)) 351 if genericRead { 352 _, err = c.(Conn).Read(nil) 353 } else { 354 _, _, err = c.ReadFrom(nil) 355 } 356 switch err { 357 case nil: // ReadFrom succeeds 358 default: // Read may timeout, it depends on the platform 359 if nerr, ok := err.(Error); (!ok || !nerr.Timeout()) && runtime.GOOS != "windows" { // Windows retruns WSAEMSGSIZ 360 t.Fatal(err) 361 } 362 } 363 } 364 } 365