Commit e89441ba authored by Russ Cox's avatar Russ Cox

net: test and fix support for 0-length datagram packets.

Fixes #274.

R=r
CC=jonathan.r.hudson
https://golang.org/cl/163072
parent acf4dd4d
...@@ -386,6 +386,10 @@ func (fd *netFD) Read(p []byte) (n int, err os.Error) { ...@@ -386,6 +386,10 @@ func (fd *netFD) Read(p []byte) (n int, err os.Error) {
} }
break; break;
} }
if fd.proto == syscall.SOCK_DGRAM && err == os.EOF {
// 0 in datagram protocol just means 0-length packet
err = nil
}
return; return;
} }
...@@ -433,7 +437,9 @@ func (fd *netFD) Write(p []byte) (n int, err os.Error) { ...@@ -433,7 +437,9 @@ func (fd *netFD) Write(p []byte) (n int, err os.Error) {
} }
err = nil; err = nil;
nn := 0; nn := 0;
for nn < len(p) { first := true; // force at least one Write, to send 0-length datagram packets
for nn < len(p) || first {
first = false;
n, err = fd.sysfile.Write(p[nn:]); n, err = fd.sysfile.Write(p[nn:]);
if n > 0 { if n > 0 {
nn += n nn += n
......
...@@ -45,7 +45,7 @@ func runServe(t *testing.T, network, addr string, listening chan<- string, done ...@@ -45,7 +45,7 @@ func runServe(t *testing.T, network, addr string, listening chan<- string, done
done <- 1; done <- 1;
} }
func connect(t *testing.T, network, addr string) { func connect(t *testing.T, network, addr string, isEmpty bool) {
var laddr string; var laddr string;
if network == "unixgram" { if network == "unixgram" {
laddr = addr + ".local" laddr = addr + ".local"
...@@ -54,18 +54,22 @@ func connect(t *testing.T, network, addr string) { ...@@ -54,18 +54,22 @@ func connect(t *testing.T, network, addr string) {
if err != nil { if err != nil {
t.Fatalf("net.Dial(%q, %q, %q) = _, %v", network, laddr, addr, err) t.Fatalf("net.Dial(%q, %q, %q) = _, %v", network, laddr, addr, err)
} }
fd.SetReadTimeout(10e6); // 10ms
b := strings.Bytes("hello, world\n"); var b []byte;
if !isEmpty {
b = strings.Bytes("hello, world\n")
}
var b1 [100]byte; var b1 [100]byte;
n, errno := fd.Write(b); n, err := fd.Write(b);
if n != len(b) { if n != len(b) {
t.Fatalf("fd.Write(%q) = %d, %v", b, n, errno) t.Fatalf("fd.Write(%q) = %d, %v", b, n, err)
} }
n, errno = fd.Read(&b1); n, err = fd.Read(&b1);
if n != len(b) { if n != len(b) || err != nil {
t.Fatalf("fd.Read() = %d, %v", n, errno) t.Fatalf("fd.Read() = %d, %v (want %d, nil)", n, err, len(b))
} }
fd.Close(); fd.Close();
} }
...@@ -82,7 +86,7 @@ func doTest(t *testing.T, network, listenaddr, dialaddr string) { ...@@ -82,7 +86,7 @@ func doTest(t *testing.T, network, listenaddr, dialaddr string) {
if network == "tcp" { if network == "tcp" {
dialaddr += addr[strings.LastIndex(addr, ":"):] dialaddr += addr[strings.LastIndex(addr, ":"):]
} }
connect(t, network, dialaddr); connect(t, network, dialaddr, false);
<-done; // make sure server stopped <-done; // make sure server stopped
} }
...@@ -133,7 +137,7 @@ func runPacket(t *testing.T, network, addr string, listening chan<- string, done ...@@ -133,7 +137,7 @@ func runPacket(t *testing.T, network, addr string, listening chan<- string, done
done <- 1; done <- 1;
} }
func doTestPacket(t *testing.T, network, listenaddr, dialaddr string) { func doTestPacket(t *testing.T, network, listenaddr, dialaddr string, isEmpty bool) {
t.Logf("TestPacket %s %s %s\n", network, listenaddr, dialaddr); t.Logf("TestPacket %s %s %s\n", network, listenaddr, dialaddr);
listening := make(chan string); listening := make(chan string);
done := make(chan int); done := make(chan int);
...@@ -145,29 +149,33 @@ func doTestPacket(t *testing.T, network, listenaddr, dialaddr string) { ...@@ -145,29 +149,33 @@ func doTestPacket(t *testing.T, network, listenaddr, dialaddr string) {
if network == "udp" { if network == "udp" {
dialaddr += addr[strings.LastIndex(addr, ":"):] dialaddr += addr[strings.LastIndex(addr, ":"):]
} }
connect(t, network, dialaddr); connect(t, network, dialaddr, isEmpty);
<-done; // tell server to stop <-done; // tell server to stop
<-done; // wait for stop <-done; // wait for stop
} }
func TestUDPServer(t *testing.T) { func TestUDPServer(t *testing.T) {
doTestPacket(t, "udp", "0.0.0.0", "127.0.0.1"); for _, isEmpty := range []bool{false, true} {
doTestPacket(t, "udp", "", "127.0.0.1"); doTestPacket(t, "udp", "0.0.0.0", "127.0.0.1", isEmpty);
doTestPacket(t, "udp", "", "127.0.0.1", isEmpty);
if kernelSupportsIPv6() { if kernelSupportsIPv6() {
doTestPacket(t, "udp", "[::]", "[::ffff:127.0.0.1]"); doTestPacket(t, "udp", "[::]", "[::ffff:127.0.0.1]", isEmpty);
doTestPacket(t, "udp", "[::]", "127.0.0.1"); doTestPacket(t, "udp", "[::]", "127.0.0.1", isEmpty);
doTestPacket(t, "udp", "0.0.0.0", "[::ffff:127.0.0.1]"); doTestPacket(t, "udp", "0.0.0.0", "[::ffff:127.0.0.1]", isEmpty);
}
} }
} }
func TestUnixDatagramServer(t *testing.T) { func TestUnixDatagramServer(t *testing.T) {
for _, isEmpty := range []bool{false, true} {
os.Remove("/tmp/gotest1.net"); os.Remove("/tmp/gotest1.net");
os.Remove("/tmp/gotest1.net.local"); os.Remove("/tmp/gotest1.net.local");
doTestPacket(t, "unixgram", "/tmp/gotest1.net", "/tmp/gotest1.net"); doTestPacket(t, "unixgram", "/tmp/gotest1.net", "/tmp/gotest1.net", isEmpty);
os.Remove("/tmp/gotest1.net"); os.Remove("/tmp/gotest1.net");
os.Remove("/tmp/gotest1.net.local"); os.Remove("/tmp/gotest1.net.local");
if syscall.OS == "linux" { if syscall.OS == "linux" {
// Test abstract unix domain socket, a Linux-ism // Test abstract unix domain socket, a Linux-ism
doTestPacket(t, "unixgram", "@gotest1/net", "@gotest1/net") doTestPacket(t, "unixgram", "@gotest1/net", "@gotest1/net", isEmpty)
}
} }
} }
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