2008-09-17 14:49:23 -06:00
|
|
|
// 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.
|
|
|
|
|
2008-12-18 16:42:39 -07:00
|
|
|
package net
|
2008-09-17 14:49:23 -06:00
|
|
|
|
|
|
|
import (
|
2009-12-15 16:35:38 -07:00
|
|
|
"flag"
|
|
|
|
"io"
|
|
|
|
"os"
|
|
|
|
"strings"
|
|
|
|
"syscall"
|
|
|
|
"testing"
|
2010-09-11 20:02:29 -06:00
|
|
|
"runtime"
|
2008-09-17 14:49:23 -06:00
|
|
|
)
|
|
|
|
|
2009-12-03 23:19:55 -07:00
|
|
|
// Do not test empty datagrams by default.
|
|
|
|
// It causes unexplained timeouts on some systems,
|
|
|
|
// including Snow Leopard. I think that the kernel
|
|
|
|
// doesn't quite expect them.
|
2010-02-22 21:38:56 -07:00
|
|
|
var testUDP = flag.Bool("udp", false, "whether to test UDP datagrams")
|
2009-12-03 23:19:55 -07:00
|
|
|
|
2009-05-08 12:22:57 -06:00
|
|
|
func runEcho(fd io.ReadWriter, done chan<- int) {
|
2009-12-15 16:35:38 -07:00
|
|
|
var buf [1024]byte
|
2008-09-17 14:49:23 -06:00
|
|
|
|
|
|
|
for {
|
2010-05-27 15:51:47 -06:00
|
|
|
n, err := fd.Read(buf[0:])
|
2008-09-17 14:49:23 -06:00
|
|
|
if err != nil || n == 0 {
|
2009-11-09 13:07:39 -07:00
|
|
|
break
|
2008-09-17 14:49:23 -06:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
fd.Write(buf[0:n])
|
2008-09-17 14:49:23 -06:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
done <- 1
|
2008-09-17 14:49:23 -06:00
|
|
|
}
|
|
|
|
|
2009-06-17 22:44:26 -06:00
|
|
|
func runServe(t *testing.T, network, addr string, listening chan<- string, done chan<- int) {
|
2009-12-15 16:35:38 -07:00
|
|
|
l, err := Listen(network, addr)
|
2008-09-17 14:49:23 -06:00
|
|
|
if err != nil {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Fatalf("net.Listen(%q, %q) = _, %v", network, addr, err)
|
2008-09-17 14:49:23 -06:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
listening <- l.Addr().String()
|
2008-09-17 14:49:23 -06:00
|
|
|
|
|
|
|
for {
|
2009-12-15 16:35:38 -07:00
|
|
|
fd, err := l.Accept()
|
2008-09-17 14:49:23 -06:00
|
|
|
if err != nil {
|
2009-11-09 13:07:39 -07:00
|
|
|
break
|
2008-09-17 14:49:23 -06:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
echodone := make(chan int)
|
|
|
|
go runEcho(fd, echodone)
|
|
|
|
<-echodone // make sure Echo stops
|
|
|
|
l.Close()
|
2008-09-17 14:49:23 -06:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
done <- 1
|
2008-09-17 14:49:23 -06:00
|
|
|
}
|
|
|
|
|
2009-12-02 16:17:49 -07:00
|
|
|
func connect(t *testing.T, network, addr string, isEmpty bool) {
|
2009-12-15 16:35:38 -07:00
|
|
|
var laddr string
|
2009-11-02 19:37:30 -07:00
|
|
|
if network == "unixgram" {
|
2009-11-09 22:23:52 -07:00
|
|
|
laddr = addr + ".local"
|
2009-11-02 19:37:30 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
fd, err := Dial(network, laddr, addr)
|
2008-09-17 14:49:23 -06:00
|
|
|
if err != nil {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Fatalf("net.Dial(%q, %q, %q) = _, %v", network, laddr, addr, err)
|
2008-09-17 14:49:23 -06:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
fd.SetReadTimeout(1e9) // 1s
|
2008-09-17 14:49:23 -06:00
|
|
|
|
2009-12-15 16:35:38 -07:00
|
|
|
var b []byte
|
2009-12-02 16:17:49 -07:00
|
|
|
if !isEmpty {
|
2010-02-25 17:01:29 -07:00
|
|
|
b = []byte("hello, world\n")
|
2009-12-02 16:17:49 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
var b1 [100]byte
|
2008-09-17 14:49:23 -06:00
|
|
|
|
2010-04-26 23:15:25 -06:00
|
|
|
n, err1 := fd.Write(b)
|
2008-09-17 14:49:23 -06:00
|
|
|
if n != len(b) {
|
2010-04-26 23:15:25 -06:00
|
|
|
t.Fatalf("fd.Write(%q) = %d, %v", b, n, err1)
|
2008-09-17 14:49:23 -06:00
|
|
|
}
|
|
|
|
|
2010-05-27 15:51:47 -06:00
|
|
|
n, err1 = fd.Read(b1[0:])
|
2010-04-26 23:15:25 -06:00
|
|
|
if n != len(b) || err1 != nil {
|
|
|
|
t.Fatalf("fd.Read() = %d, %v (want %d, nil)", n, err1, len(b))
|
2008-09-17 14:49:23 -06:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
fd.Close()
|
2008-09-17 14:49:23 -06:00
|
|
|
}
|
|
|
|
|
2009-01-16 15:16:31 -07:00
|
|
|
func doTest(t *testing.T, network, listenaddr, dialaddr string) {
|
2009-12-15 16:35:38 -07:00
|
|
|
t.Logf("Test %s %s %s\n", network, listenaddr, dialaddr)
|
|
|
|
listening := make(chan string)
|
|
|
|
done := make(chan int)
|
2009-06-17 22:44:26 -06:00
|
|
|
if network == "tcp" {
|
2009-12-15 16:35:38 -07:00
|
|
|
listenaddr += ":0" // any available port
|
2009-06-17 22:44:26 -06:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
go runServe(t, network, listenaddr, listening, done)
|
|
|
|
addr := <-listening // wait for server to start
|
2009-06-17 22:44:26 -06:00
|
|
|
if network == "tcp" {
|
2009-11-20 12:45:05 -07:00
|
|
|
dialaddr += addr[strings.LastIndex(addr, ":"):]
|
2009-06-17 22:44:26 -06:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
connect(t, network, dialaddr, false)
|
|
|
|
<-done // make sure server stopped
|
2008-09-17 14:49:23 -06:00
|
|
|
}
|
|
|
|
|
2009-11-02 19:37:30 -07:00
|
|
|
func TestTCPServer(t *testing.T) {
|
2009-12-15 16:35:38 -07:00
|
|
|
doTest(t, "tcp", "0.0.0.0", "127.0.0.1")
|
|
|
|
doTest(t, "tcp", "", "127.0.0.1")
|
2009-11-10 19:00:27 -07:00
|
|
|
if kernelSupportsIPv6() {
|
2009-12-15 16:35:38 -07:00
|
|
|
doTest(t, "tcp", "[::]", "[::ffff:127.0.0.1]")
|
|
|
|
doTest(t, "tcp", "[::]", "127.0.0.1")
|
|
|
|
doTest(t, "tcp", "0.0.0.0", "[::ffff:127.0.0.1]")
|
2009-11-10 19:00:27 -07:00
|
|
|
}
|
2008-09-17 14:49:23 -06:00
|
|
|
}
|
|
|
|
|
2009-05-13 19:03:41 -06:00
|
|
|
func TestUnixServer(t *testing.T) {
|
2010-09-11 20:02:29 -06:00
|
|
|
// "unix" sockets are not supported on windows.
|
|
|
|
if runtime.GOOS == "windows" {
|
|
|
|
return
|
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
os.Remove("/tmp/gotest.net")
|
|
|
|
doTest(t, "unix", "/tmp/gotest.net", "/tmp/gotest.net")
|
|
|
|
os.Remove("/tmp/gotest.net")
|
2011-01-19 12:21:58 -07:00
|
|
|
if syscall.OS != "darwin" {
|
|
|
|
doTest(t, "unixpacket", "/tmp/gotest.net", "/tmp/gotest.net")
|
|
|
|
os.Remove("/tmp/gotest.net")
|
|
|
|
}
|
2009-05-13 19:03:41 -06:00
|
|
|
if syscall.OS == "linux" {
|
|
|
|
// Test abstract unix domain socket, a Linux-ism
|
2009-11-09 13:07:39 -07:00
|
|
|
doTest(t, "unix", "@gotest/net", "@gotest/net")
|
2011-01-19 12:21:58 -07:00
|
|
|
doTest(t, "unixpacket", "@gotest/net", "@gotest/net")
|
2009-05-13 19:03:41 -06:00
|
|
|
}
|
|
|
|
}
|
2009-11-02 19:37:30 -07:00
|
|
|
|
|
|
|
func runPacket(t *testing.T, network, addr string, listening chan<- string, done chan<- int) {
|
2009-12-15 16:35:38 -07:00
|
|
|
c, err := ListenPacket(network, addr)
|
2009-11-02 19:37:30 -07:00
|
|
|
if err != nil {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Fatalf("net.ListenPacket(%q, %q) = _, %v", network, addr, err)
|
2009-11-02 19:37:30 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
listening <- c.LocalAddr().String()
|
|
|
|
c.SetReadTimeout(10e6) // 10ms
|
|
|
|
var buf [1000]byte
|
2009-11-02 19:37:30 -07:00
|
|
|
for {
|
2010-05-27 15:51:47 -06:00
|
|
|
n, addr, err := c.ReadFrom(buf[0:])
|
2010-04-26 23:15:25 -06:00
|
|
|
if e, ok := err.(Error); ok && e.Timeout() {
|
2009-11-02 19:37:30 -07:00
|
|
|
if done <- 1 {
|
2009-11-09 13:07:39 -07:00
|
|
|
break
|
2009-11-02 19:37:30 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
continue
|
2009-11-02 19:37:30 -07:00
|
|
|
}
|
|
|
|
if err != nil {
|
2009-11-09 13:07:39 -07:00
|
|
|
break
|
2009-11-02 19:37:30 -07:00
|
|
|
}
|
|
|
|
if _, err = c.WriteTo(buf[0:n], addr); err != nil {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Fatalf("WriteTo %v: %v", addr, err)
|
2009-11-02 19:37:30 -07:00
|
|
|
}
|
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
c.Close()
|
|
|
|
done <- 1
|
2009-11-02 19:37:30 -07:00
|
|
|
}
|
|
|
|
|
2009-12-02 16:17:49 -07:00
|
|
|
func doTestPacket(t *testing.T, network, listenaddr, dialaddr string, isEmpty bool) {
|
2009-12-15 16:35:38 -07:00
|
|
|
t.Logf("TestPacket %s %s %s\n", network, listenaddr, dialaddr)
|
|
|
|
listening := make(chan string)
|
|
|
|
done := make(chan int)
|
2009-11-02 19:37:30 -07:00
|
|
|
if network == "udp" {
|
2009-12-15 16:35:38 -07:00
|
|
|
listenaddr += ":0" // any available port
|
2009-11-02 19:37:30 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
go runPacket(t, network, listenaddr, listening, done)
|
|
|
|
addr := <-listening // wait for server to start
|
2009-11-02 19:37:30 -07:00
|
|
|
if network == "udp" {
|
2009-11-20 12:45:05 -07:00
|
|
|
dialaddr += addr[strings.LastIndex(addr, ":"):]
|
2009-11-02 19:37:30 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
connect(t, network, dialaddr, isEmpty)
|
|
|
|
<-done // tell server to stop
|
|
|
|
<-done // wait for stop
|
2009-11-02 19:37:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestUDPServer(t *testing.T) {
|
2010-02-22 21:38:56 -07:00
|
|
|
if !*testUDP {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
for _, isEmpty := range []bool{false, true} {
|
2009-12-15 16:35:38 -07:00
|
|
|
doTestPacket(t, "udp", "0.0.0.0", "127.0.0.1", isEmpty)
|
|
|
|
doTestPacket(t, "udp", "", "127.0.0.1", isEmpty)
|
2009-12-02 16:17:49 -07:00
|
|
|
if kernelSupportsIPv6() {
|
2009-12-15 16:35:38 -07:00
|
|
|
doTestPacket(t, "udp", "[::]", "[::ffff:127.0.0.1]", isEmpty)
|
|
|
|
doTestPacket(t, "udp", "[::]", "127.0.0.1", isEmpty)
|
|
|
|
doTestPacket(t, "udp", "0.0.0.0", "[::ffff:127.0.0.1]", isEmpty)
|
2009-12-02 16:17:49 -07:00
|
|
|
}
|
2009-11-10 19:00:27 -07:00
|
|
|
}
|
2009-11-02 19:37:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestUnixDatagramServer(t *testing.T) {
|
2010-09-11 20:02:29 -06:00
|
|
|
// "unix" sockets are not supported on windows.
|
|
|
|
if runtime.GOOS == "windows" {
|
|
|
|
return
|
|
|
|
}
|
2010-02-22 21:38:56 -07:00
|
|
|
for _, isEmpty := range []bool{false} {
|
2009-12-15 16:35:38 -07:00
|
|
|
os.Remove("/tmp/gotest1.net")
|
|
|
|
os.Remove("/tmp/gotest1.net.local")
|
|
|
|
doTestPacket(t, "unixgram", "/tmp/gotest1.net", "/tmp/gotest1.net", isEmpty)
|
|
|
|
os.Remove("/tmp/gotest1.net")
|
|
|
|
os.Remove("/tmp/gotest1.net.local")
|
2009-12-02 16:17:49 -07:00
|
|
|
if syscall.OS == "linux" {
|
|
|
|
// Test abstract unix domain socket, a Linux-ism
|
|
|
|
doTestPacket(t, "unixgram", "@gotest1/net", "@gotest1/net", isEmpty)
|
|
|
|
}
|
2009-11-02 19:37:30 -07:00
|
|
|
}
|
|
|
|
}
|