Commit e16ed287 authored by Mikio Hara's avatar Mikio Hara

net: remove full stack test cases for IPConn

A few packages that handle net.IPConn in golang.org/x/net sub repository
already implement full stack test cases with more coverage than the net
package. There is no need to keep duplicate code around here.

This change removes full stack test cases for IPConn that require
knowing how to speak with each of protocol stack implementation of
supported platforms.

Change-Id: I871119a9746fc6a2b997b69cfd733463558f5816
Reviewed-on: https://go-review.googlesource.com/3404Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
parent 5e279ddd
......@@ -226,7 +226,3 @@ func setReadBuffer(fd *netFD, bytes int) error {
func setWriteBuffer(fd *netFD, bytes int) error {
return syscall.EPLAN9
}
func skipRawSocketTests() (skip bool, skipmsg string, err error) {
return true, "skipping test on plan9", nil
}
......@@ -502,10 +502,3 @@ func (fd *netFD) dup() (f *os.File, err error) {
func closesocket(s int) error {
return syscall.Close(s)
}
func skipRawSocketTests() (skip bool, skipmsg string, err error) {
if os.Getuid() != 0 {
return true, "skipping test; must be root", nil
}
return false, "", nil
}
......@@ -617,25 +617,6 @@ func (fd *netFD) accept() (*netFD, error) {
return netfd, nil
}
func skipRawSocketTests() (skip bool, skipmsg string, err error) {
// From http://msdn.microsoft.com/en-us/library/windows/desktop/ms740548.aspx:
// Note: To use a socket of type SOCK_RAW requires administrative privileges.
// Users running Winsock applications that use raw sockets must be a member of
// the Administrators group on the local computer, otherwise raw socket calls
// will fail with an error code of WSAEACCES. On Windows Vista and later, access
// for raw sockets is enforced at socket creation. In earlier versions of Windows,
// access for raw sockets is enforced during other socket operations.
s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, 0)
if err == syscall.WSAEACCES {
return true, "skipping test; no access to raw socket allowed", nil
}
if err != nil {
return true, "", err
}
defer syscall.Closesocket(s)
return false, "", nil
}
// Unimplemented functions.
func (fd *netFD) dup() (*os.File, error) {
......
......@@ -5,15 +5,19 @@
package net
import (
"bytes"
"fmt"
"os"
"reflect"
"runtime"
"testing"
"time"
)
// The full stack test cases for IPConn have been moved to the
// following:
// golang.org/x/net/ipv4
// golang.org/x/net/ipv6
// golang.org/x/net/icmp
type resolveIPAddrTest struct {
net string
litAddrOrName string
......@@ -59,14 +63,6 @@ func init() {
}
}
func skipRawSocketTest(t *testing.T) (skip bool, skipmsg string) {
skip, skipmsg, err := skipRawSocketTests()
if err != nil {
t.Fatal(err)
}
return skip, skipmsg
}
func TestResolveIPAddr(t *testing.T) {
switch runtime.GOOS {
case "nacl":
......@@ -83,164 +79,6 @@ func TestResolveIPAddr(t *testing.T) {
}
}
var icmpEchoTests = []struct {
net string
laddr string
raddr string
}{
{"ip4:icmp", "0.0.0.0", "127.0.0.1"},
{"ip6:ipv6-icmp", "::", "::1"},
}
func TestConnICMPEcho(t *testing.T) {
if skip, skipmsg := skipRawSocketTest(t); skip {
t.Skip(skipmsg)
}
for i, tt := range icmpEchoTests {
net, _, err := parseNetwork(tt.net)
if err != nil {
t.Fatalf("parseNetwork failed: %v", err)
}
if net == "ip6" && !supportsIPv6 {
continue
}
c, err := Dial(tt.net, tt.raddr)
if err != nil {
t.Fatalf("Dial failed: %v", err)
}
c.SetDeadline(time.Now().Add(100 * time.Millisecond))
defer c.Close()
typ := icmpv4EchoRequest
if net == "ip6" {
typ = icmpv6EchoRequest
}
xid, xseq := os.Getpid()&0xffff, i+1
wb, err := (&icmpMessage{
Type: typ, Code: 0,
Body: &icmpEcho{
ID: xid, Seq: xseq,
Data: bytes.Repeat([]byte("Go Go Gadget Ping!!!"), 3),
},
}).Marshal()
if err != nil {
t.Fatalf("icmpMessage.Marshal failed: %v", err)
}
if _, err := c.Write(wb); err != nil {
t.Fatalf("Conn.Write failed: %v", err)
}
var m *icmpMessage
rb := make([]byte, 20+len(wb))
for {
if _, err := c.Read(rb); err != nil {
t.Fatalf("Conn.Read failed: %v", err)
}
if net == "ip4" {
rb = ipv4Payload(rb)
}
if m, err = parseICMPMessage(rb); err != nil {
t.Fatalf("parseICMPMessage failed: %v", err)
}
switch m.Type {
case icmpv4EchoRequest, icmpv6EchoRequest:
continue
}
break
}
switch p := m.Body.(type) {
case *icmpEcho:
if p.ID != xid || p.Seq != xseq {
t.Fatalf("got id=%v, seqnum=%v; expected id=%v, seqnum=%v", p.ID, p.Seq, xid, xseq)
}
default:
t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, typ, 0)
}
}
}
func TestPacketConnICMPEcho(t *testing.T) {
if skip, skipmsg := skipRawSocketTest(t); skip {
t.Skip(skipmsg)
}
for i, tt := range icmpEchoTests {
net, _, err := parseNetwork(tt.net)
if err != nil {
t.Fatalf("parseNetwork failed: %v", err)
}
if net == "ip6" && !supportsIPv6 {
continue
}
c, err := ListenPacket(tt.net, tt.laddr)
if err != nil {
t.Fatalf("ListenPacket failed: %v", err)
}
c.SetDeadline(time.Now().Add(100 * time.Millisecond))
defer c.Close()
ra, err := ResolveIPAddr(tt.net, tt.raddr)
if err != nil {
t.Fatalf("ResolveIPAddr failed: %v", err)
}
typ := icmpv4EchoRequest
if net == "ip6" {
typ = icmpv6EchoRequest
}
xid, xseq := os.Getpid()&0xffff, i+1
wb, err := (&icmpMessage{
Type: typ, Code: 0,
Body: &icmpEcho{
ID: xid, Seq: xseq,
Data: bytes.Repeat([]byte("Go Go Gadget Ping!!!"), 3),
},
}).Marshal()
if err != nil {
t.Fatalf("icmpMessage.Marshal failed: %v", err)
}
if _, err := c.WriteTo(wb, ra); err != nil {
t.Fatalf("PacketConn.WriteTo failed: %v", err)
}
var m *icmpMessage
rb := make([]byte, 20+len(wb))
for {
if _, _, err := c.ReadFrom(rb); err != nil {
t.Fatalf("PacketConn.ReadFrom failed: %v", err)
}
// See BUG section.
//if net == "ip4" {
// rb = ipv4Payload(rb)
//}
if m, err = parseICMPMessage(rb); err != nil {
t.Fatalf("parseICMPMessage failed: %v", err)
}
switch m.Type {
case icmpv4EchoRequest, icmpv6EchoRequest:
continue
}
break
}
switch p := m.Body.(type) {
case *icmpEcho:
if p.ID != xid || p.Seq != xseq {
t.Fatalf("got id=%v, seqnum=%v; expected id=%v, seqnum=%v", p.ID, p.Seq, xid, xseq)
}
default:
t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, typ, 0)
}
}
}
func ipv4Payload(b []byte) []byte {
if len(b) < 20 {
return b
}
hdrlen := int(b[0]&0x0f) << 2
return b[hdrlen:]
}
var ipConnLocalNameTests = []struct {
net string
laddr *IPAddr
......
// Copyright 2009 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 net
import "errors"
const (
icmpv4EchoRequest = 8
icmpv4EchoReply = 0
icmpv6EchoRequest = 128
icmpv6EchoReply = 129
)
// icmpMessage represents an ICMP message.
type icmpMessage struct {
Type int // type
Code int // code
Checksum int // checksum
Body icmpMessageBody // body
}
// icmpMessageBody represents an ICMP message body.
type icmpMessageBody interface {
Len() int
Marshal() ([]byte, error)
}
// Marshal returns the binary enconding of the ICMP echo request or
// reply message m.
func (m *icmpMessage) Marshal() ([]byte, error) {
b := []byte{byte(m.Type), byte(m.Code), 0, 0}
if m.Body != nil && m.Body.Len() != 0 {
mb, err := m.Body.Marshal()
if err != nil {
return nil, err
}
b = append(b, mb...)
}
switch m.Type {
case icmpv6EchoRequest, icmpv6EchoReply:
return b, nil
}
csumcv := len(b) - 1 // checksum coverage
s := uint32(0)
for i := 0; i < csumcv; i += 2 {
s += uint32(b[i+1])<<8 | uint32(b[i])
}
if csumcv&1 == 0 {
s += uint32(b[csumcv])
}
s = s>>16 + s&0xffff
s = s + s>>16
// Place checksum back in header; using ^= avoids the
// assumption the checksum bytes are zero.
b[2] ^= byte(^s)
b[3] ^= byte(^s >> 8)
return b, nil
}
// parseICMPMessage parses b as an ICMP message.
func parseICMPMessage(b []byte) (*icmpMessage, error) {
msglen := len(b)
if msglen < 4 {
return nil, errors.New("message too short")
}
m := &icmpMessage{Type: int(b[0]), Code: int(b[1]), Checksum: int(b[2])<<8 | int(b[3])}
if msglen > 4 {
var err error
switch m.Type {
case icmpv4EchoRequest, icmpv4EchoReply, icmpv6EchoRequest, icmpv6EchoReply:
m.Body, err = parseICMPEcho(b[4:])
if err != nil {
return nil, err
}
}
}
return m, nil
}
// imcpEcho represenets an ICMP echo request or reply message body.
type icmpEcho struct {
ID int // identifier
Seq int // sequence number
Data []byte // data
}
func (p *icmpEcho) Len() int {
if p == nil {
return 0
}
return 4 + len(p.Data)
}
// Marshal returns the binary enconding of the ICMP echo request or
// reply message body p.
func (p *icmpEcho) Marshal() ([]byte, error) {
b := make([]byte, 4+len(p.Data))
b[0], b[1] = byte(p.ID>>8), byte(p.ID)
b[2], b[3] = byte(p.Seq>>8), byte(p.Seq)
copy(b[4:], p.Data)
return b, nil
}
// parseICMPEcho parses b as an ICMP echo request or reply message
// body.
func parseICMPEcho(b []byte) (*icmpEcho, error) {
bodylen := len(b)
p := &icmpEcho{ID: int(b[0])<<8 | int(b[1]), Seq: int(b[2])<<8 | int(b[3])}
if bodylen > 4 {
p.Data = make([]byte, bodylen-4)
copy(p.Data, b[4:])
}
return p, nil
}
......@@ -15,29 +15,16 @@ import (
"time"
)
// The full stack test cases for IPConn have been moved to the
// following:
// golang.org/x/net/ipv4
// golang.org/x/net/ipv6
// golang.org/x/net/icmp
func packetConnTestData(t *testing.T, net string, i int) ([]byte, func()) {
switch net {
case "udp":
return []byte("UDP PACKETCONN TEST"), nil
case "ip":
if skip, skipmsg := skipRawSocketTest(t); skip {
return nil, func() {
t.Logf(skipmsg)
}
}
b, err := (&icmpMessage{
Type: icmpv4EchoRequest, Code: 0,
Body: &icmpEcho{
ID: os.Getpid() & 0xffff, Seq: i + 1,
Data: []byte("IP PACKETCONN TEST"),
},
}).Marshal()
if err != nil {
return nil, func() {
t.Fatalf("icmpMessage.Marshal failed: %v", err)
}
}
return b, nil
case "unixgram":
switch runtime.GOOS {
case "nacl", "plan9", "windows":
......@@ -60,7 +47,6 @@ var packetConnTests = []struct {
addr2 string
}{
{"udp", "127.0.0.1:0", "127.0.0.1:0"},
{"ip:icmp", "127.0.0.1", "127.0.0.1"},
{"unixgram", testUnixAddr(), testUnixAddr()},
}
......
......@@ -15,6 +15,12 @@ import (
"time"
)
// The full stack test cases for IPConn have been moved to the
// following:
// golang.org/x/net/ipv4
// golang.org/x/net/ipv6
// golang.org/x/net/icmp
// testUnixAddr uses ioutil.TempFile to get a name that is unique. It
// also uses /tmp directory in case it is prohibited to create UNIX
// sockets in TMPDIR.
......@@ -173,8 +179,8 @@ func TestUDPConnSpecificMethods(t *testing.T) {
}
func TestIPConnSpecificMethods(t *testing.T) {
if skip, skipmsg := skipRawSocketTest(t); skip {
t.Skip(skipmsg)
if os.Getuid() != 0 {
t.Skip("must be root")
}
la, err := ResolveIPAddr("ip4", "127.0.0.1")
......@@ -194,30 +200,6 @@ func TestIPConnSpecificMethods(t *testing.T) {
c.SetReadBuffer(2048)
c.SetWriteBuffer(2048)
wb, err := (&icmpMessage{
Type: icmpv4EchoRequest, Code: 0,
Body: &icmpEcho{
ID: os.Getpid() & 0xffff, Seq: 1,
Data: []byte("IPCONN TEST "),
},
}).Marshal()
if err != nil {
t.Fatalf("icmpMessage.Marshal failed: %v", err)
}
rb := make([]byte, 20+len(wb))
if _, err := c.WriteToIP(wb, c.LocalAddr().(*IPAddr)); err != nil {
t.Fatalf("IPConn.WriteToIP failed: %v", err)
}
if _, _, err := c.ReadFromIP(rb); err != nil {
t.Fatalf("IPConn.ReadFromIP failed: %v", err)
}
if _, _, err := c.WriteMsgIP(wb, nil, c.LocalAddr().(*IPAddr)); err != nil {
condFatalf(t, "IPConn.WriteMsgIP failed: %v", err)
}
if _, _, _, _, err := c.ReadMsgIP(rb, nil); err != nil {
condFatalf(t, "IPConn.ReadMsgIP failed: %v", err)
}
if f, err := c.File(); err != nil {
condFatalf(t, "IPConn.File failed: %v", err)
} else {
......@@ -230,6 +212,7 @@ func TestIPConnSpecificMethods(t *testing.T) {
}
}()
wb := []byte("IPCONN TEST")
c.WriteToIP(wb, nil)
c.WriteMsgIP(wb, nil, nil)
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment