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//go:build !js 6 7package net 8 9import ( 10 "errors" 11 "internal/testenv" 12 "os" 13 "reflect" 14 "runtime" 15 "testing" 16 "time" 17) 18 19func BenchmarkUDP6LinkLocalUnicast(b *testing.B) { 20 testHookUninstaller.Do(uninstallTestHooks) 21 22 if !supportsIPv6() { 23 b.Skip("IPv6 is not supported") 24 } 25 ifi := loopbackInterface() 26 if ifi == nil { 27 b.Skip("loopback interface not found") 28 } 29 lla := ipv6LinkLocalUnicastAddr(ifi) 30 if lla == "" { 31 b.Skip("IPv6 link-local unicast address not found") 32 } 33 34 c1, err := ListenPacket("udp6", JoinHostPort(lla+"%"+ifi.Name, "0")) 35 if err != nil { 36 b.Fatal(err) 37 } 38 defer c1.Close() 39 c2, err := ListenPacket("udp6", JoinHostPort(lla+"%"+ifi.Name, "0")) 40 if err != nil { 41 b.Fatal(err) 42 } 43 defer c2.Close() 44 45 var buf [1]byte 46 for i := 0; i < b.N; i++ { 47 if _, err := c1.WriteTo(buf[:], c2.LocalAddr()); err != nil { 48 b.Fatal(err) 49 } 50 if _, _, err := c2.ReadFrom(buf[:]); err != nil { 51 b.Fatal(err) 52 } 53 } 54} 55 56type resolveUDPAddrTest struct { 57 network string 58 litAddrOrName string 59 addr *UDPAddr 60 err error 61} 62 63var resolveUDPAddrTests = []resolveUDPAddrTest{ 64 {"udp", "127.0.0.1:0", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, 65 {"udp4", "127.0.0.1:65535", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 65535}, nil}, 66 67 {"udp", "[::1]:0", &UDPAddr{IP: ParseIP("::1"), Port: 0}, nil}, 68 {"udp6", "[::1]:65535", &UDPAddr{IP: ParseIP("::1"), Port: 65535}, nil}, 69 70 {"udp", "[::1%en0]:1", &UDPAddr{IP: ParseIP("::1"), Port: 1, Zone: "en0"}, nil}, 71 {"udp6", "[::1%911]:2", &UDPAddr{IP: ParseIP("::1"), Port: 2, Zone: "911"}, nil}, 72 73 {"", "127.0.0.1:0", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, // Go 1.0 behavior 74 {"", "[::1]:0", &UDPAddr{IP: ParseIP("::1"), Port: 0}, nil}, // Go 1.0 behavior 75 76 {"udp", ":12345", &UDPAddr{Port: 12345}, nil}, 77 78 {"http", "127.0.0.1:0", nil, UnknownNetworkError("http")}, 79 80 {"udp", "127.0.0.1:domain", &UDPAddr{IP: ParseIP("127.0.0.1"), Port: 53}, nil}, 81 {"udp", "[::ffff:127.0.0.1]:domain", &UDPAddr{IP: ParseIP("::ffff:127.0.0.1"), Port: 53}, nil}, 82 {"udp", "[2001:db8::1]:domain", &UDPAddr{IP: ParseIP("2001:db8::1"), Port: 53}, nil}, 83 {"udp4", "127.0.0.1:domain", &UDPAddr{IP: ParseIP("127.0.0.1"), Port: 53}, nil}, 84 {"udp4", "[::ffff:127.0.0.1]:domain", &UDPAddr{IP: ParseIP("127.0.0.1"), Port: 53}, nil}, 85 {"udp6", "[2001:db8::1]:domain", &UDPAddr{IP: ParseIP("2001:db8::1"), Port: 53}, nil}, 86 87 {"udp4", "[2001:db8::1]:domain", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "2001:db8::1"}}, 88 {"udp6", "127.0.0.1:domain", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "127.0.0.1"}}, 89 {"udp6", "[::ffff:127.0.0.1]:domain", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "::ffff:127.0.0.1"}}, 90} 91 92func TestResolveUDPAddr(t *testing.T) { 93 origTestHookLookupIP := testHookLookupIP 94 defer func() { testHookLookupIP = origTestHookLookupIP }() 95 testHookLookupIP = lookupLocalhost 96 97 for _, tt := range resolveUDPAddrTests { 98 addr, err := ResolveUDPAddr(tt.network, tt.litAddrOrName) 99 if !reflect.DeepEqual(addr, tt.addr) || !reflect.DeepEqual(err, tt.err) { 100 t.Errorf("ResolveUDPAddr(%q, %q) = %#v, %v, want %#v, %v", tt.network, tt.litAddrOrName, addr, err, tt.addr, tt.err) 101 continue 102 } 103 if err == nil { 104 addr2, err := ResolveUDPAddr(addr.Network(), addr.String()) 105 if !reflect.DeepEqual(addr2, tt.addr) || err != tt.err { 106 t.Errorf("(%q, %q): ResolveUDPAddr(%q, %q) = %#v, %v, want %#v, %v", tt.network, tt.litAddrOrName, addr.Network(), addr.String(), addr2, err, tt.addr, tt.err) 107 } 108 } 109 } 110} 111 112func TestWriteToUDP(t *testing.T) { 113 switch runtime.GOOS { 114 case "plan9": 115 t.Skipf("not supported on %s", runtime.GOOS) 116 } 117 118 c, err := ListenPacket("udp", "127.0.0.1:0") 119 if err != nil { 120 t.Fatal(err) 121 } 122 defer c.Close() 123 124 testWriteToConn(t, c.LocalAddr().String()) 125 testWriteToPacketConn(t, c.LocalAddr().String()) 126} 127 128func testWriteToConn(t *testing.T, raddr string) { 129 c, err := Dial("udp", raddr) 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("CONNECTED-MODE SOCKET") 141 _, err = c.(*UDPConn).WriteToUDP(b, ra) 142 if err == nil { 143 t.Fatal("should fail") 144 } 145 if err != nil && err.(*OpError).Err != ErrWriteToConnected { 146 t.Fatalf("should fail as ErrWriteToConnected: %v", err) 147 } 148 _, err = c.(*UDPConn).WriteTo(b, ra) 149 if err == nil { 150 t.Fatal("should fail") 151 } 152 if err != nil && err.(*OpError).Err != ErrWriteToConnected { 153 t.Fatalf("should fail as ErrWriteToConnected: %v", err) 154 } 155 _, err = c.Write(b) 156 if err != nil { 157 t.Fatal(err) 158 } 159 _, _, err = c.(*UDPConn).WriteMsgUDP(b, nil, ra) 160 if err == nil { 161 t.Fatal("should fail") 162 } 163 if err != nil && err.(*OpError).Err != ErrWriteToConnected { 164 t.Fatalf("should fail as ErrWriteToConnected: %v", err) 165 } 166 _, _, err = c.(*UDPConn).WriteMsgUDP(b, nil, nil) 167 if err != nil { 168 t.Fatal(err) 169 } 170} 171 172func testWriteToPacketConn(t *testing.T, raddr string) { 173 c, err := ListenPacket("udp", "127.0.0.1:0") 174 if err != nil { 175 t.Fatal(err) 176 } 177 defer c.Close() 178 179 ra, err := ResolveUDPAddr("udp", raddr) 180 if err != nil { 181 t.Fatal(err) 182 } 183 184 b := []byte("UNCONNECTED-MODE SOCKET") 185 _, err = c.(*UDPConn).WriteToUDP(b, ra) 186 if err != nil { 187 t.Fatal(err) 188 } 189 _, err = c.WriteTo(b, ra) 190 if err != nil { 191 t.Fatal(err) 192 } 193 _, err = c.(*UDPConn).Write(b) 194 if err == nil { 195 t.Fatal("should fail") 196 } 197 _, _, err = c.(*UDPConn).WriteMsgUDP(b, nil, nil) 198 if err == nil { 199 t.Fatal("should fail") 200 } 201 if err != nil && err.(*OpError).Err != errMissingAddress { 202 t.Fatalf("should fail as errMissingAddress: %v", err) 203 } 204 _, _, err = c.(*UDPConn).WriteMsgUDP(b, nil, ra) 205 if err != nil { 206 t.Fatal(err) 207 } 208} 209 210var udpConnLocalNameTests = []struct { 211 net string 212 laddr *UDPAddr 213}{ 214 {"udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}}, 215 {"udp4", &UDPAddr{}}, 216 {"udp4", nil}, 217} 218 219func TestUDPConnLocalName(t *testing.T) { 220 testenv.MustHaveExternalNetwork(t) 221 222 for _, tt := range udpConnLocalNameTests { 223 c, err := ListenUDP(tt.net, tt.laddr) 224 if err != nil { 225 t.Fatal(err) 226 } 227 defer c.Close() 228 la := c.LocalAddr() 229 if a, ok := la.(*UDPAddr); !ok || a.Port == 0 { 230 t.Fatalf("got %v; expected a proper address with non-zero port number", la) 231 } 232 } 233} 234 235func TestUDPConnLocalAndRemoteNames(t *testing.T) { 236 for _, laddr := range []string{"", "127.0.0.1:0"} { 237 c1, err := ListenPacket("udp", "127.0.0.1:0") 238 if err != nil { 239 t.Fatal(err) 240 } 241 defer c1.Close() 242 243 var la *UDPAddr 244 if laddr != "" { 245 var err error 246 if la, err = ResolveUDPAddr("udp", laddr); err != nil { 247 t.Fatal(err) 248 } 249 } 250 c2, err := DialUDP("udp", la, c1.LocalAddr().(*UDPAddr)) 251 if err != nil { 252 t.Fatal(err) 253 } 254 defer c2.Close() 255 256 var connAddrs = [4]struct { 257 got Addr 258 ok bool 259 }{ 260 {c1.LocalAddr(), true}, 261 {c1.(*UDPConn).RemoteAddr(), false}, 262 {c2.LocalAddr(), true}, 263 {c2.RemoteAddr(), true}, 264 } 265 for _, ca := range connAddrs { 266 if a, ok := ca.got.(*UDPAddr); ok != ca.ok || ok && a.Port == 0 { 267 t.Fatalf("got %v; expected a proper address with non-zero port number", ca.got) 268 } 269 } 270 } 271} 272 273func TestIPv6LinkLocalUnicastUDP(t *testing.T) { 274 testenv.MustHaveExternalNetwork(t) 275 276 if !supportsIPv6() { 277 t.Skip("IPv6 is not supported") 278 } 279 280 for i, tt := range ipv6LinkLocalUnicastUDPTests { 281 c1, err := ListenPacket(tt.network, tt.address) 282 if err != nil { 283 // It might return "LookupHost returned no 284 // suitable address" error on some platforms. 285 t.Log(err) 286 continue 287 } 288 ls := (&packetListener{PacketConn: c1}).newLocalServer() 289 defer ls.teardown() 290 ch := make(chan error, 1) 291 handler := func(ls *localPacketServer, c PacketConn) { packetTransponder(c, ch) } 292 if err := ls.buildup(handler); err != nil { 293 t.Fatal(err) 294 } 295 if la, ok := c1.LocalAddr().(*UDPAddr); !ok || !tt.nameLookup && la.Zone == "" { 296 t.Fatalf("got %v; expected a proper address with zone identifier", la) 297 } 298 299 c2, err := Dial(tt.network, ls.PacketConn.LocalAddr().String()) 300 if err != nil { 301 t.Fatal(err) 302 } 303 defer c2.Close() 304 if la, ok := c2.LocalAddr().(*UDPAddr); !ok || !tt.nameLookup && la.Zone == "" { 305 t.Fatalf("got %v; expected a proper address with zone identifier", la) 306 } 307 if ra, ok := c2.RemoteAddr().(*UDPAddr); !ok || !tt.nameLookup && ra.Zone == "" { 308 t.Fatalf("got %v; expected a proper address with zone identifier", ra) 309 } 310 311 if _, err := c2.Write([]byte("UDP OVER IPV6 LINKLOCAL TEST")); err != nil { 312 t.Fatal(err) 313 } 314 b := make([]byte, 32) 315 if _, err := c2.Read(b); err != nil { 316 t.Fatal(err) 317 } 318 319 for err := range ch { 320 t.Errorf("#%d: %v", i, err) 321 } 322 } 323} 324 325func TestUDPZeroBytePayload(t *testing.T) { 326 switch runtime.GOOS { 327 case "plan9": 328 t.Skipf("not supported on %s", runtime.GOOS) 329 case "darwin", "ios": 330 testenv.SkipFlaky(t, 29225) 331 } 332 333 c := newLocalPacketListener(t, "udp") 334 defer c.Close() 335 336 for _, genericRead := range []bool{false, true} { 337 n, err := c.WriteTo(nil, c.LocalAddr()) 338 if err != nil { 339 t.Fatal(err) 340 } 341 if n != 0 { 342 t.Errorf("got %d; want 0", n) 343 } 344 c.SetReadDeadline(time.Now().Add(30 * time.Second)) 345 var b [1]byte 346 var name string 347 if genericRead { 348 _, err = c.(Conn).Read(b[:]) 349 name = "Read" 350 } else { 351 _, _, err = c.ReadFrom(b[:]) 352 name = "ReadFrom" 353 } 354 if err != nil { 355 t.Errorf("%s of zero byte packet failed: %v", name, err) 356 } 357 } 358} 359 360func TestUDPZeroByteBuffer(t *testing.T) { 361 switch runtime.GOOS { 362 case "plan9": 363 t.Skipf("not supported on %s", runtime.GOOS) 364 } 365 366 c := newLocalPacketListener(t, "udp") 367 defer c.Close() 368 369 b := []byte("UDP ZERO BYTE BUFFER TEST") 370 for _, genericRead := range []bool{false, true} { 371 n, err := c.WriteTo(b, c.LocalAddr()) 372 if err != nil { 373 t.Fatal(err) 374 } 375 if n != len(b) { 376 t.Errorf("got %d; want %d", n, len(b)) 377 } 378 c.SetReadDeadline(time.Now().Add(100 * time.Millisecond)) 379 if genericRead { 380 _, err = c.(Conn).Read(nil) 381 } else { 382 _, _, err = c.ReadFrom(nil) 383 } 384 switch err { 385 case nil: // ReadFrom succeeds 386 default: // Read may timeout, it depends on the platform 387 if nerr, ok := err.(Error); (!ok || !nerr.Timeout()) && runtime.GOOS != "windows" { // Windows returns WSAEMSGSIZE 388 t.Fatal(err) 389 } 390 } 391 } 392} 393 394func TestUDPReadSizeError(t *testing.T) { 395 switch runtime.GOOS { 396 case "plan9": 397 t.Skipf("not supported on %s", runtime.GOOS) 398 } 399 400 c1 := newLocalPacketListener(t, "udp") 401 defer c1.Close() 402 403 c2, err := Dial("udp", c1.LocalAddr().String()) 404 if err != nil { 405 t.Fatal(err) 406 } 407 defer c2.Close() 408 409 b1 := []byte("READ SIZE ERROR TEST") 410 for _, genericRead := range []bool{false, true} { 411 n, err := c2.Write(b1) 412 if err != nil { 413 t.Fatal(err) 414 } 415 if n != len(b1) { 416 t.Errorf("got %d; want %d", n, len(b1)) 417 } 418 c1.SetReadDeadline(time.Now().Add(100 * time.Millisecond)) 419 b2 := make([]byte, len(b1)-1) 420 if genericRead { 421 n, err = c1.(Conn).Read(b2) 422 } else { 423 n, _, err = c1.ReadFrom(b2) 424 } 425 switch err { 426 case nil: // ReadFrom succeeds 427 default: // Read may timeout, it depends on the platform 428 if nerr, ok := err.(Error); (!ok || !nerr.Timeout()) && runtime.GOOS != "windows" { // Windows returns WSAEMSGSIZE 429 t.Fatal(err) 430 } 431 } 432 if n != len(b1)-1 { 433 t.Fatalf("got %d; want %d", n, len(b1)-1) 434 } 435 } 436} 437 438// TestUDPReadTimeout verifies that ReadFromUDP with timeout returns an error 439// without data or an address. 440func TestUDPReadTimeout(t *testing.T) { 441 la, err := ResolveUDPAddr("udp4", "127.0.0.1:0") 442 if err != nil { 443 t.Fatal(err) 444 } 445 c, err := ListenUDP("udp4", la) 446 if err != nil { 447 t.Fatal(err) 448 } 449 defer c.Close() 450 451 c.SetDeadline(time.Now()) 452 b := make([]byte, 1) 453 n, addr, err := c.ReadFromUDP(b) 454 if !errors.Is(err, os.ErrDeadlineExceeded) { 455 t.Errorf("ReadFromUDP got err %v want os.ErrDeadlineExceeded", err) 456 } 457 if n != 0 { 458 t.Errorf("ReadFromUDP got n %d want 0", n) 459 } 460 if addr != nil { 461 t.Errorf("ReadFromUDP got addr %+#v want nil", addr) 462 } 463} 464 465func TestAllocs(t *testing.T) { 466 switch runtime.GOOS { 467 case "plan9": 468 // Plan9 wasn't optimized. 469 t.Skipf("skipping on %v", runtime.GOOS) 470 } 471 builder := os.Getenv("GO_BUILDER_NAME") 472 switch builder { 473 case "linux-amd64-noopt": 474 // Optimizations are required to remove the allocs. 475 t.Skipf("skipping on %v", builder) 476 } 477 conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}) 478 if err != nil { 479 t.Fatal(err) 480 } 481 defer conn.Close() 482 addr := conn.LocalAddr() 483 addrPort := addr.(*UDPAddr).AddrPort() 484 buf := make([]byte, 8) 485 486 allocs := testing.AllocsPerRun(1000, func() { 487 _, _, err := conn.WriteMsgUDPAddrPort(buf, nil, addrPort) 488 if err != nil { 489 t.Fatal(err) 490 } 491 _, _, _, _, err = conn.ReadMsgUDPAddrPort(buf, nil) 492 if err != nil { 493 t.Fatal(err) 494 } 495 }) 496 if got := int(allocs); got != 0 { 497 t.Errorf("WriteMsgUDPAddrPort/ReadMsgUDPAddrPort allocated %d objects", got) 498 } 499 500 allocs = testing.AllocsPerRun(1000, func() { 501 _, err := conn.WriteToUDPAddrPort(buf, addrPort) 502 if err != nil { 503 t.Fatal(err) 504 } 505 _, _, err = conn.ReadFromUDPAddrPort(buf) 506 if err != nil { 507 t.Fatal(err) 508 } 509 }) 510 if got := int(allocs); got != 0 { 511 t.Errorf("WriteToUDPAddrPort/ReadFromUDPAddrPort allocated %d objects", got) 512 } 513 514 allocs = testing.AllocsPerRun(1000, func() { 515 _, err := conn.WriteTo(buf, addr) 516 if err != nil { 517 t.Fatal(err) 518 } 519 _, _, err = conn.ReadFromUDP(buf) 520 if err != nil { 521 t.Fatal(err) 522 } 523 }) 524 if got := int(allocs); got != 1 { 525 t.Errorf("WriteTo/ReadFromUDP allocated %d objects", got) 526 } 527} 528 529func BenchmarkReadWriteMsgUDPAddrPort(b *testing.B) { 530 conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}) 531 if err != nil { 532 b.Fatal(err) 533 } 534 defer conn.Close() 535 addr := conn.LocalAddr().(*UDPAddr).AddrPort() 536 buf := make([]byte, 8) 537 b.ResetTimer() 538 b.ReportAllocs() 539 for i := 0; i < b.N; i++ { 540 _, _, err := conn.WriteMsgUDPAddrPort(buf, nil, addr) 541 if err != nil { 542 b.Fatal(err) 543 } 544 _, _, _, _, err = conn.ReadMsgUDPAddrPort(buf, nil) 545 if err != nil { 546 b.Fatal(err) 547 } 548 } 549} 550 551func BenchmarkWriteToReadFromUDP(b *testing.B) { 552 conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}) 553 if err != nil { 554 b.Fatal(err) 555 } 556 defer conn.Close() 557 addr := conn.LocalAddr() 558 buf := make([]byte, 8) 559 b.ResetTimer() 560 b.ReportAllocs() 561 for i := 0; i < b.N; i++ { 562 _, err := conn.WriteTo(buf, addr) 563 if err != nil { 564 b.Fatal(err) 565 } 566 _, _, err = conn.ReadFromUDP(buf) 567 if err != nil { 568 b.Fatal(err) 569 } 570 } 571} 572 573func BenchmarkWriteToReadFromUDPAddrPort(b *testing.B) { 574 conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}) 575 if err != nil { 576 b.Fatal(err) 577 } 578 defer conn.Close() 579 addr := conn.LocalAddr().(*UDPAddr).AddrPort() 580 buf := make([]byte, 8) 581 b.ResetTimer() 582 b.ReportAllocs() 583 for i := 0; i < b.N; i++ { 584 _, err := conn.WriteToUDPAddrPort(buf, addr) 585 if err != nil { 586 b.Fatal(err) 587 } 588 _, _, err = conn.ReadFromUDPAddrPort(buf) 589 if err != nil { 590 b.Fatal(err) 591 } 592 } 593} 594 595func TestUDPIPVersionReadMsg(t *testing.T) { 596 switch runtime.GOOS { 597 case "plan9": 598 t.Skipf("skipping on %v", runtime.GOOS) 599 } 600 conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}) 601 if err != nil { 602 t.Fatal(err) 603 } 604 defer conn.Close() 605 daddr := conn.LocalAddr().(*UDPAddr).AddrPort() 606 buf := make([]byte, 8) 607 _, err = conn.WriteToUDPAddrPort(buf, daddr) 608 if err != nil { 609 t.Fatal(err) 610 } 611 _, _, _, saddr, err := conn.ReadMsgUDPAddrPort(buf, nil) 612 if err != nil { 613 t.Fatal(err) 614 } 615 if !saddr.Addr().Is4() { 616 t.Error("returned AddrPort is not IPv4") 617 } 618 _, err = conn.WriteToUDPAddrPort(buf, daddr) 619 if err != nil { 620 t.Fatal(err) 621 } 622 _, _, _, soldaddr, err := conn.ReadMsgUDP(buf, nil) 623 if err != nil { 624 t.Fatal(err) 625 } 626 if len(soldaddr.IP) != 4 { 627 t.Error("returned UDPAddr is not IPv4") 628 } 629} 630