OSDN Git Service

Hulk did something
[bytom/vapor.git] / vendor / golang.org / x / net / icmp / ping_test.go
diff --git a/vendor/golang.org/x/net/icmp/ping_test.go b/vendor/golang.org/x/net/icmp/ping_test.go
new file mode 100644 (file)
index 0000000..3171dad
--- /dev/null
@@ -0,0 +1,200 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package icmp_test
+
+import (
+       "errors"
+       "fmt"
+       "net"
+       "os"
+       "runtime"
+       "sync"
+       "testing"
+       "time"
+
+       "golang.org/x/net/icmp"
+       "golang.org/x/net/internal/iana"
+       "golang.org/x/net/internal/nettest"
+       "golang.org/x/net/ipv4"
+       "golang.org/x/net/ipv6"
+)
+
+func googleAddr(c *icmp.PacketConn, protocol int) (net.Addr, error) {
+       const host = "www.google.com"
+       ips, err := net.LookupIP(host)
+       if err != nil {
+               return nil, err
+       }
+       netaddr := func(ip net.IP) (net.Addr, error) {
+               switch c.LocalAddr().(type) {
+               case *net.UDPAddr:
+                       return &net.UDPAddr{IP: ip}, nil
+               case *net.IPAddr:
+                       return &net.IPAddr{IP: ip}, nil
+               default:
+                       return nil, errors.New("neither UDPAddr nor IPAddr")
+               }
+       }
+       for _, ip := range ips {
+               switch protocol {
+               case iana.ProtocolICMP:
+                       if ip.To4() != nil {
+                               return netaddr(ip)
+                       }
+               case iana.ProtocolIPv6ICMP:
+                       if ip.To16() != nil && ip.To4() == nil {
+                               return netaddr(ip)
+                       }
+               }
+       }
+       return nil, errors.New("no A or AAAA record")
+}
+
+type pingTest struct {
+       network, address string
+       protocol         int
+       mtype            icmp.Type
+}
+
+var nonPrivilegedPingTests = []pingTest{
+       {"udp4", "0.0.0.0", iana.ProtocolICMP, ipv4.ICMPTypeEcho},
+
+       {"udp6", "::", iana.ProtocolIPv6ICMP, ipv6.ICMPTypeEchoRequest},
+}
+
+func TestNonPrivilegedPing(t *testing.T) {
+       if testing.Short() {
+               t.Skip("avoid external network")
+       }
+       switch runtime.GOOS {
+       case "darwin":
+       case "linux":
+               t.Log("you may need to adjust the net.ipv4.ping_group_range kernel state")
+       default:
+               t.Skipf("not supported on %s", runtime.GOOS)
+       }
+
+       for i, tt := range nonPrivilegedPingTests {
+               if err := doPing(tt, i); err != nil {
+                       t.Error(err)
+               }
+       }
+}
+
+var privilegedPingTests = []pingTest{
+       {"ip4:icmp", "0.0.0.0", iana.ProtocolICMP, ipv4.ICMPTypeEcho},
+
+       {"ip6:ipv6-icmp", "::", iana.ProtocolIPv6ICMP, ipv6.ICMPTypeEchoRequest},
+}
+
+func TestPrivilegedPing(t *testing.T) {
+       if testing.Short() {
+               t.Skip("avoid external network")
+       }
+       if m, ok := nettest.SupportsRawIPSocket(); !ok {
+               t.Skip(m)
+       }
+
+       for i, tt := range privilegedPingTests {
+               if err := doPing(tt, i); err != nil {
+                       t.Error(err)
+               }
+       }
+}
+
+func doPing(tt pingTest, seq int) error {
+       c, err := icmp.ListenPacket(tt.network, tt.address)
+       if err != nil {
+               return err
+       }
+       defer c.Close()
+
+       dst, err := googleAddr(c, tt.protocol)
+       if err != nil {
+               return err
+       }
+
+       if tt.network != "udp6" && tt.protocol == iana.ProtocolIPv6ICMP {
+               var f ipv6.ICMPFilter
+               f.SetAll(true)
+               f.Accept(ipv6.ICMPTypeDestinationUnreachable)
+               f.Accept(ipv6.ICMPTypePacketTooBig)
+               f.Accept(ipv6.ICMPTypeTimeExceeded)
+               f.Accept(ipv6.ICMPTypeParameterProblem)
+               f.Accept(ipv6.ICMPTypeEchoReply)
+               if err := c.IPv6PacketConn().SetICMPFilter(&f); err != nil {
+                       return err
+               }
+       }
+
+       wm := icmp.Message{
+               Type: tt.mtype, Code: 0,
+               Body: &icmp.Echo{
+                       ID: os.Getpid() & 0xffff, Seq: 1 << uint(seq),
+                       Data: []byte("HELLO-R-U-THERE"),
+               },
+       }
+       wb, err := wm.Marshal(nil)
+       if err != nil {
+               return err
+       }
+       if n, err := c.WriteTo(wb, dst); err != nil {
+               return err
+       } else if n != len(wb) {
+               return fmt.Errorf("got %v; want %v", n, len(wb))
+       }
+
+       rb := make([]byte, 1500)
+       if err := c.SetReadDeadline(time.Now().Add(3 * time.Second)); err != nil {
+               return err
+       }
+       n, peer, err := c.ReadFrom(rb)
+       if err != nil {
+               return err
+       }
+       rm, err := icmp.ParseMessage(tt.protocol, rb[:n])
+       if err != nil {
+               return err
+       }
+       switch rm.Type {
+       case ipv4.ICMPTypeEchoReply, ipv6.ICMPTypeEchoReply:
+               return nil
+       default:
+               return fmt.Errorf("got %+v from %v; want echo reply", rm, peer)
+       }
+}
+
+func TestConcurrentNonPrivilegedListenPacket(t *testing.T) {
+       if testing.Short() {
+               t.Skip("avoid external network")
+       }
+       switch runtime.GOOS {
+       case "darwin":
+       case "linux":
+               t.Log("you may need to adjust the net.ipv4.ping_group_range kernel state")
+       default:
+               t.Skipf("not supported on %s", runtime.GOOS)
+       }
+
+       network, address := "udp4", "127.0.0.1"
+       if !nettest.SupportsIPv4() {
+               network, address = "udp6", "::1"
+       }
+       const N = 1000
+       var wg sync.WaitGroup
+       wg.Add(N)
+       for i := 0; i < N; i++ {
+               go func() {
+                       defer wg.Done()
+                       c, err := icmp.ListenPacket(network, address)
+                       if err != nil {
+                               t.Error(err)
+                               return
+                       }
+                       c.Close()
+               }()
+       }
+       wg.Wait()
+}