mirror of
https://github.com/golang/go
synced 2024-11-20 05:44:44 -07:00
net: add test for Conn, PacketConn and Listener
I just realized that there is no good place for adding exposed function or method tests because server, unicast and multicast_test.go do test complicated multiple test objects, platform behaviros, protocol behaviors and API, at the same time. Perhaps splitting them into per test object might be better, so this CL provides tests focused on API. R=rsc CC=gobot, golang-dev https://golang.org/cl/6501057
This commit is contained in:
parent
922c0b4755
commit
4545dc6a69
103
src/pkg/net/conn_test.go
Normal file
103
src/pkg/net/conn_test.go
Normal file
@ -0,0 +1,103 @@
|
||||
// Copyright 2012 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_test
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var connTests = []struct {
|
||||
net string
|
||||
addr string
|
||||
}{
|
||||
{"tcp", "127.0.0.1:0"},
|
||||
{"unix", "/tmp/gotest.net"},
|
||||
{"unixpacket", "/tmp/gotest.net"},
|
||||
}
|
||||
|
||||
func TestConnAndListener(t *testing.T) {
|
||||
for _, tt := range connTests {
|
||||
switch tt.net {
|
||||
case "unix", "unixpacket":
|
||||
switch runtime.GOOS {
|
||||
case "plan9", "windows":
|
||||
continue
|
||||
}
|
||||
if tt.net == "unixpacket" && runtime.GOOS != "linux" {
|
||||
continue
|
||||
}
|
||||
os.Remove(tt.addr)
|
||||
}
|
||||
|
||||
ln, err := net.Listen(tt.net, tt.addr)
|
||||
if err != nil {
|
||||
t.Errorf("net.Listen failed: %v", err)
|
||||
return
|
||||
}
|
||||
ln.Addr()
|
||||
defer ln.Close()
|
||||
|
||||
done := make(chan int)
|
||||
go transponder(t, ln, done)
|
||||
|
||||
c, err := net.Dial(tt.net, ln.Addr().String())
|
||||
if err != nil {
|
||||
t.Errorf("net.Dial failed: %v", err)
|
||||
return
|
||||
}
|
||||
c.LocalAddr()
|
||||
c.RemoteAddr()
|
||||
c.SetDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
c.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
defer c.Close()
|
||||
|
||||
if _, err := c.Write([]byte("CONN TEST")); err != nil {
|
||||
t.Errorf("net.Conn.Write failed: %v", err)
|
||||
return
|
||||
}
|
||||
rb := make([]byte, 128)
|
||||
if _, err := c.Read(rb); err != nil {
|
||||
t.Errorf("net.Conn.Read failed: %v", err)
|
||||
}
|
||||
|
||||
<-done
|
||||
switch tt.net {
|
||||
case "unix", "unixpacket":
|
||||
os.Remove(tt.addr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func transponder(t *testing.T, ln net.Listener, done chan<- int) {
|
||||
defer func() { done <- 1 }()
|
||||
|
||||
c, err := ln.Accept()
|
||||
if err != nil {
|
||||
t.Errorf("net.Listener.Accept failed: %v", err)
|
||||
return
|
||||
}
|
||||
c.LocalAddr()
|
||||
c.RemoteAddr()
|
||||
c.SetDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
c.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
defer c.Close()
|
||||
|
||||
b := make([]byte, 128)
|
||||
n, err := c.Read(b)
|
||||
if err != nil {
|
||||
t.Errorf("net.Conn.Read failed: %v", err)
|
||||
return
|
||||
}
|
||||
if _, err := c.Write(b[:n]); err != nil {
|
||||
t.Errorf("net.Conn.Write failed: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
161
src/pkg/net/packetconn_test.go
Normal file
161
src/pkg/net/packetconn_test.go
Normal file
@ -0,0 +1,161 @@
|
||||
// Copyright 2012 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_test
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var packetConnTests = []struct {
|
||||
net string
|
||||
addr1 string
|
||||
addr2 string
|
||||
}{
|
||||
{"udp", "127.0.0.1:0", "127.0.0.1:0"},
|
||||
{"ip:icmp", "127.0.0.1", "127.0.0.1"},
|
||||
{"unixgram", "/tmp/gotest.net1", "/tmp/gotest.net2"},
|
||||
}
|
||||
|
||||
func TestPacketConn(t *testing.T) {
|
||||
for _, tt := range packetConnTests {
|
||||
var wb []byte
|
||||
netstr := strings.Split(tt.net, ":")
|
||||
switch netstr[0] {
|
||||
case "udp":
|
||||
wb = []byte("UDP PACKETCONN TEST")
|
||||
case "ip":
|
||||
switch runtime.GOOS {
|
||||
case "plan9":
|
||||
continue
|
||||
}
|
||||
if os.Getuid() != 0 {
|
||||
continue
|
||||
}
|
||||
id := os.Getpid() & 0xffff
|
||||
wb = newICMPEchoRequest(id, 1, 128, []byte("IP PACKETCONN TEST "))
|
||||
case "unixgram":
|
||||
switch runtime.GOOS {
|
||||
case "plan9", "windows":
|
||||
continue
|
||||
}
|
||||
os.Remove(tt.addr1)
|
||||
os.Remove(tt.addr2)
|
||||
wb = []byte("UNIXGRAM PACKETCONN TEST")
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
c1, err := net.ListenPacket(tt.net, tt.addr1)
|
||||
if err != nil {
|
||||
t.Fatalf("net.ListenPacket failed: %v", err)
|
||||
}
|
||||
c1.LocalAddr()
|
||||
c1.SetDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
c1.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
c1.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
defer c1.Close()
|
||||
|
||||
c2, err := net.ListenPacket(tt.net, tt.addr2)
|
||||
if err != nil {
|
||||
t.Fatalf("net.ListenPacket failed: %v", err)
|
||||
}
|
||||
c2.LocalAddr()
|
||||
c2.SetDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
c2.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
c2.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
defer c2.Close()
|
||||
|
||||
if _, err := c1.WriteTo(wb, c2.LocalAddr()); err != nil {
|
||||
t.Fatalf("net.PacketConn.WriteTo failed: %v", err)
|
||||
}
|
||||
rb2 := make([]byte, 128)
|
||||
if _, _, err := c2.ReadFrom(rb2); err != nil {
|
||||
t.Fatalf("net.PacketConn.ReadFrom failed: %v", err)
|
||||
}
|
||||
if _, err := c2.WriteTo(wb, c1.LocalAddr()); err != nil {
|
||||
t.Fatalf("net.PacketConn.WriteTo failed: %v", err)
|
||||
}
|
||||
rb1 := make([]byte, 128)
|
||||
if _, _, err := c1.ReadFrom(rb1); err != nil {
|
||||
t.Fatalf("net.PacketConn.ReadFrom failed: %v", err)
|
||||
}
|
||||
|
||||
switch netstr[0] {
|
||||
case "unixgram":
|
||||
os.Remove(tt.addr1)
|
||||
os.Remove(tt.addr2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestConnAndPacketConn(t *testing.T) {
|
||||
for _, tt := range packetConnTests {
|
||||
var wb []byte
|
||||
netstr := strings.Split(tt.net, ":")
|
||||
switch netstr[0] {
|
||||
case "udp":
|
||||
wb = []byte("UDP PACKETCONN TEST")
|
||||
case "ip":
|
||||
switch runtime.GOOS {
|
||||
case "plan9":
|
||||
continue
|
||||
}
|
||||
if os.Getuid() != 0 {
|
||||
continue
|
||||
}
|
||||
id := os.Getpid() & 0xffff
|
||||
wb = newICMPEchoRequest(id, 1, 128, []byte("IP PACKETCONN TEST"))
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
c1, err := net.ListenPacket(tt.net, tt.addr1)
|
||||
if err != nil {
|
||||
t.Fatalf("net.ListenPacket failed: %v", err)
|
||||
}
|
||||
c1.LocalAddr()
|
||||
c1.SetDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
c1.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
c1.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
defer c1.Close()
|
||||
|
||||
c2, err := net.Dial(tt.net, c1.LocalAddr().String())
|
||||
if err != nil {
|
||||
t.Fatalf("net.Dial failed: %v", err)
|
||||
}
|
||||
c2.LocalAddr()
|
||||
c2.RemoteAddr()
|
||||
c2.SetDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
c2.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
c2.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
defer c2.Close()
|
||||
|
||||
if _, err := c2.Write(wb); err != nil {
|
||||
t.Fatalf("net.Conn.Write failed: %v", err)
|
||||
}
|
||||
rb1 := make([]byte, 128)
|
||||
if _, _, err := c1.ReadFrom(rb1); err != nil {
|
||||
t.Fatalf("net.PacetConn.ReadFrom failed: %v", err)
|
||||
}
|
||||
var dst net.Addr
|
||||
if netstr[0] == "ip" {
|
||||
dst = &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}
|
||||
} else {
|
||||
dst = c2.LocalAddr()
|
||||
}
|
||||
if _, err := c1.WriteTo(wb, dst); err != nil {
|
||||
t.Fatalf("net.PacketConn.WriteTo failed: %v", err)
|
||||
}
|
||||
rb2 := make([]byte, 128)
|
||||
if _, err := c2.Read(rb2); err != nil {
|
||||
t.Fatalf("net.Conn.Read failed: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
185
src/pkg/net/protoconn_test.go
Normal file
185
src/pkg/net/protoconn_test.go
Normal file
@ -0,0 +1,185 @@
|
||||
// Copyright 2012 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_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestUDPConnSpecificMethods(t *testing.T) {
|
||||
la, err := net.ResolveUDPAddr("udp4", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatalf("net.ResolveUDPAddr failed: %v", err)
|
||||
}
|
||||
c, err := net.ListenUDP("udp4", la)
|
||||
if err != nil {
|
||||
t.Fatalf("net.ListenUDP failed: %v", err)
|
||||
}
|
||||
c.File()
|
||||
c.LocalAddr()
|
||||
c.RemoteAddr()
|
||||
c.SetDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
c.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
c.SetReadBuffer(2048)
|
||||
c.SetWriteBuffer(2048)
|
||||
defer c.Close()
|
||||
|
||||
wb := []byte("UDPCONN TEST")
|
||||
if _, err := c.WriteToUDP(wb, c.LocalAddr().(*net.UDPAddr)); err != nil {
|
||||
t.Fatalf("net.UDPConn.WriteToUDP failed: %v", err)
|
||||
}
|
||||
rb := make([]byte, 128)
|
||||
if _, _, err := c.ReadFromUDP(rb); err != nil {
|
||||
t.Fatalf("net.UDPConn.ReadFromUDP failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIPConnSpecificMethods(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "plan9":
|
||||
t.Logf("skipping read test on %q", runtime.GOOS)
|
||||
return
|
||||
}
|
||||
if os.Getuid() != 0 {
|
||||
t.Logf("skipping test; must be root")
|
||||
return
|
||||
}
|
||||
|
||||
la, err := net.ResolveIPAddr("ip4", "127.0.0.1")
|
||||
if err != nil {
|
||||
t.Fatalf("net.ResolveIPAddr failed: %v", err)
|
||||
}
|
||||
c, err := net.ListenIP("ip4:icmp", la)
|
||||
if err != nil {
|
||||
t.Fatalf("net.ListenIP failed: %v", err)
|
||||
}
|
||||
c.File()
|
||||
c.LocalAddr()
|
||||
c.RemoteAddr()
|
||||
c.SetDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
c.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
c.SetReadBuffer(2048)
|
||||
c.SetWriteBuffer(2048)
|
||||
defer c.Close()
|
||||
|
||||
id := os.Getpid() & 0xffff
|
||||
wb := newICMPEchoRequest(id, 1, 128, []byte("IPCONN TEST "))
|
||||
if _, err := c.WriteToIP(wb, c.LocalAddr().(*net.IPAddr)); err != nil {
|
||||
t.Fatalf("net.IPConn.WriteToIP failed: %v", err)
|
||||
}
|
||||
rb := make([]byte, 20+128)
|
||||
if _, _, err := c.ReadFromIP(rb); err != nil {
|
||||
t.Fatalf("net.IPConn.ReadFromIP failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Find out the use case of ListenUnixgram, I have no idea.
|
||||
func TestUnixConnSpecificMethods(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "plan9", "windows":
|
||||
t.Logf("skipping test on %q", runtime.GOOS)
|
||||
return
|
||||
}
|
||||
|
||||
p1, p2 := "/tmp/gotest.net1", "/tmp/gotest.net2"
|
||||
os.Remove(p1)
|
||||
os.Remove(p2)
|
||||
|
||||
a1, err := net.ResolveUnixAddr("unixgram", p1)
|
||||
if err != nil {
|
||||
t.Fatalf("net.ResolveUnixAddr failed: %v", err)
|
||||
}
|
||||
c1, err := net.DialUnix("unixgram", a1, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("net.DialUnix failed: %v", err)
|
||||
}
|
||||
c1.File()
|
||||
c1.LocalAddr()
|
||||
c1.RemoteAddr()
|
||||
c1.SetDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
c1.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
c1.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
c1.SetReadBuffer(2048)
|
||||
c1.SetWriteBuffer(2048)
|
||||
defer c1.Close()
|
||||
defer os.Remove(p1)
|
||||
|
||||
a2, err := net.ResolveUnixAddr("unixgram", p2)
|
||||
if err != nil {
|
||||
t.Fatalf("net.ResolveUnixAddr failed: %v", err)
|
||||
}
|
||||
c2, err := net.DialUnix("unixgram", a2, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("net.DialUnix failed: %v", err)
|
||||
}
|
||||
c2.File()
|
||||
c2.LocalAddr()
|
||||
c2.RemoteAddr()
|
||||
c2.SetDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
c2.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
c2.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
c2.SetReadBuffer(2048)
|
||||
c2.SetWriteBuffer(2048)
|
||||
defer c2.Close()
|
||||
defer os.Remove(p2)
|
||||
|
||||
wb := []byte("UNIXCONN TEST")
|
||||
if _, _, err := c1.WriteMsgUnix(wb, nil, a2); err != nil {
|
||||
t.Fatalf("net.UnixConn.WriteMsgUnix failed: %v", err)
|
||||
}
|
||||
rb2 := make([]byte, 128)
|
||||
if _, _, _, _, err := c2.ReadMsgUnix(rb2, nil); err != nil {
|
||||
t.Fatalf("net.UnixConn.ReadMsgUnix failed: %v", err)
|
||||
}
|
||||
if _, err := c2.WriteToUnix(wb, a1); err != nil {
|
||||
t.Fatalf("net.UnixConn.WriteToUnix failed: %v", err)
|
||||
}
|
||||
rb1 := make([]byte, 128)
|
||||
if _, _, err := c1.ReadFromUnix(rb1); err != nil {
|
||||
t.Fatalf("net.UnixConn.ReadFromUnix failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func newICMPEchoRequest(id, seqnum, msglen int, filler []byte) []byte {
|
||||
b := newICMPInfoMessage(id, seqnum, msglen, filler)
|
||||
b[0] = 8
|
||||
// calculate ICMP checksum
|
||||
cklen := len(b)
|
||||
s := uint32(0)
|
||||
for i := 0; i < cklen-1; i += 2 {
|
||||
s += uint32(b[i+1])<<8 | uint32(b[i])
|
||||
}
|
||||
if cklen&1 == 1 {
|
||||
s += uint32(b[cklen-1])
|
||||
}
|
||||
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 & 0xff)
|
||||
b[3] ^= byte(^s >> 8)
|
||||
return b
|
||||
}
|
||||
|
||||
func newICMPInfoMessage(id, seqnum, msglen int, filler []byte) []byte {
|
||||
b := make([]byte, msglen)
|
||||
copy(b[8:], bytes.Repeat(filler, (msglen-8)/len(filler)+1))
|
||||
b[0] = 0 // type
|
||||
b[1] = 0 // code
|
||||
b[2] = 0 // checksum
|
||||
b[3] = 0 // checksum
|
||||
b[4] = byte(id >> 8) // identifier
|
||||
b[5] = byte(id & 0xff) // identifier
|
||||
b[6] = byte(seqnum >> 8) // sequence number
|
||||
b[7] = byte(seqnum & 0xff) // sequence number
|
||||
return b
|
||||
}
|
Loading…
Reference in New Issue
Block a user