go.net/ipv6: add missing API tests
Now the package has a code coverage of 76.1% of statements.
Also fixes flaky concurrent test.
Fixes golang/go#5696.
R=golang-codereviews, dave
CC=golang-codereviews
https://golang.org/cl/45620043
diff --git a/ipv6/control_test.go b/ipv6/control_test.go
deleted file mode 100644
index 0f99321..0000000
--- a/ipv6/control_test.go
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2013 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 ipv6
-
-import (
- "sync"
- "testing"
-)
-
-func TestControlFlags(t *testing.T) {
- tf := FlagInterface | FlagPathMTU
- opt := rawOpt{cflags: tf | FlagHopLimit}
-
- // This loop runs methods of raw.Opt concurrently for testing
- // concurrent access to the rawOpt. The first entry shold be
- // opt.set and the last entry should be opt.clear.
- tfns := []func(ControlFlags){opt.set, opt.clear, opt.clear}
- ch := make(chan bool)
- var wg sync.WaitGroup
- for i, fn := range tfns {
- wg.Add(1)
- go func(i int, fn func(ControlFlags)) {
- defer wg.Done()
- switch i {
- case 0:
- close(ch)
- case len(tfns) - 1:
- <-ch
- }
- opt.Lock()
- defer opt.Unlock()
- fn(tf)
- }(i, fn)
- }
- wg.Wait()
-
- if opt.isset(tf) {
- t.Fatalf("got %#x; expected %#x", opt.cflags, FlagHopLimit)
- }
-}
diff --git a/ipv6/icmp_test.go b/ipv6/icmp_test.go
index a7833dd..4005036 100644
--- a/ipv6/icmp_test.go
+++ b/ipv6/icmp_test.go
@@ -14,6 +14,24 @@
"testing"
)
+var icmpStringTests = []struct {
+ in ipv6.ICMPType
+ out string
+}{
+ {ipv6.ICMPTypeDestinationUnreachable, "destination unreachable"},
+
+ {256, "<nil>"},
+}
+
+func TestICMPString(t *testing.T) {
+ for _, tt := range icmpStringTests {
+ s := tt.in.String()
+ if s != tt.out {
+ t.Errorf("got %s; expected %s", s, tt.out)
+ }
+ }
+}
+
func TestICMPFilter(t *testing.T) {
switch runtime.GOOS {
case "plan9", "windows":
diff --git a/ipv6/multicast_test.go b/ipv6/multicast_test.go
index 79568f4..6801681 100644
--- a/ipv6/multicast_test.go
+++ b/ipv6/multicast_test.go
@@ -5,6 +5,7 @@
package ipv6_test
import (
+ "bytes"
"code.google.com/p/go.net/ipv6"
"net"
"os"
@@ -64,9 +65,11 @@
cm := ipv6.ControlMessage{
TrafficClass: DiffServAF11 | CongestionExperienced,
+ Src: net.IPv6loopback,
IfIndex: ifi.Index,
}
- cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagInterface | ipv6.FlagPathMTU
+ cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
+ wb := []byte("HELLO-R-U-THERE")
for i, toggle := range []bool{true, false, true} {
if err := p.SetControlMessage(cf, toggle); err != nil {
@@ -76,12 +79,16 @@
t.Fatalf("ipv6.PacketConn.SetDeadline failed: %v", err)
}
cm.HopLimit = i + 1
- if _, err := p.WriteTo([]byte("HELLO-R-U-THERE"), &cm, dst); err != nil {
+ if n, err := p.WriteTo(wb, &cm, dst); err != nil {
t.Fatalf("ipv6.PacketConn.WriteTo failed: %v", err)
+ } else if n != len(wb) {
+ t.Fatalf("ipv6.PacketConn.WriteTo failed: short write: %v", n)
}
- b := make([]byte, 128)
- if _, cm, _, err := p.ReadFrom(b); err != nil {
+ rb := make([]byte, 128)
+ if n, cm, _, err := p.ReadFrom(rb); err != nil {
t.Fatalf("ipv6.PacketConn.ReadFrom failed: %v", err)
+ } else if !bytes.Equal(rb[:n], wb) {
+ t.Fatalf("got %v; expected %v", rb[:n], wb)
} else {
t.Logf("rcvd cmsg: %v", cm)
}
@@ -136,9 +143,10 @@
cm := ipv6.ControlMessage{
TrafficClass: DiffServAF11 | CongestionExperienced,
+ Src: net.IPv6loopback,
IfIndex: ifi.Index,
}
- cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagInterface | ipv6.FlagPathMTU
+ cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
var f ipv6.ICMPFilter
f.SetAll(true)
@@ -177,15 +185,17 @@
t.Fatalf("ipv6.PacketConn.SetDeadline failed: %v", err)
}
cm.HopLimit = i + 1
- if _, err := p.WriteTo(wb, &cm, dst); err != nil {
+ if n, err := p.WriteTo(wb, &cm, dst); err != nil {
t.Fatalf("ipv6.PacketConn.WriteTo failed: %v", err)
+ } else if n != len(wb) {
+ t.Fatalf("ipv6.PacketConn.WriteTo failed: short write: %v", n)
}
- b := make([]byte, 128)
- if n, cm, _, err := p.ReadFrom(b); err != nil {
+ rb := make([]byte, 128)
+ if n, cm, _, err := p.ReadFrom(rb); err != nil {
t.Fatalf("ipv6.PacketConn.ReadFrom failed: %v", err)
} else {
t.Logf("rcvd cmsg: %v", cm)
- if m, err := parseICMPMessage(b[:n]); err != nil {
+ if m, err := parseICMPMessage(rb[:n]); err != nil {
t.Fatalf("parseICMPMessage failed: %v", err)
} else if m.Type != ipv6.ICMPTypeEchoReply || m.Code != 0 {
t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, ipv6.ICMPTypeEchoReply, 0)
diff --git a/ipv6/readwrite_test.go b/ipv6/readwrite_test.go
new file mode 100644
index 0000000..f0d09b3
--- /dev/null
+++ b/ipv6/readwrite_test.go
@@ -0,0 +1,168 @@
+// Copyright 2013 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 ipv6_test
+
+import (
+ "bytes"
+ "code.google.com/p/go.net/ipv6"
+ "net"
+ "runtime"
+ "sync"
+ "testing"
+)
+
+func benchmarkUDPListener() (net.PacketConn, net.Addr, error) {
+ c, err := net.ListenPacket("udp6", "[::1]:0")
+ if err != nil {
+ return nil, nil, err
+ }
+ dst, err := net.ResolveUDPAddr("udp6", c.LocalAddr().String())
+ if err != nil {
+ c.Close()
+ return nil, nil, err
+ }
+ return c, dst, nil
+}
+
+func BenchmarkReadWriteNetUDP(b *testing.B) {
+ c, dst, err := benchmarkUDPListener()
+ if err != nil {
+ b.Fatalf("benchmarkUDPListener failed: %v", err)
+ }
+ defer c.Close()
+
+ wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128)
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ benchmarkReadWriteNetUDP(b, c, wb, rb, dst)
+ }
+}
+
+func benchmarkReadWriteNetUDP(b *testing.B, c net.PacketConn, wb, rb []byte, dst net.Addr) {
+ if _, err := c.WriteTo(wb, dst); err != nil {
+ b.Fatalf("net.PacketConn.WriteTo failed: %v", err)
+ }
+ if _, _, err := c.ReadFrom(rb); err != nil {
+ b.Fatalf("net.PacketConn.ReadFrom failed: %v", err)
+ }
+}
+
+func BenchmarkReadWriteIPv6UDP(b *testing.B) {
+ c, dst, err := benchmarkUDPListener()
+ if err != nil {
+ b.Fatalf("benchmarkUDPListener failed: %v", err)
+ }
+ defer c.Close()
+
+ p := ipv6.NewPacketConn(c)
+ cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagInterface | ipv6.FlagPathMTU
+ if err := p.SetControlMessage(cf, true); err != nil {
+ b.Fatalf("ipv6.PacketConn.SetControlMessage failed: %v", err)
+ }
+ ifi := loopbackInterface()
+
+ wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128)
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ benchmarkReadWriteIPv6UDP(b, p, wb, rb, dst, ifi)
+ }
+}
+
+func benchmarkReadWriteIPv6UDP(b *testing.B, p *ipv6.PacketConn, wb, rb []byte, dst net.Addr, ifi *net.Interface) {
+ cm := ipv6.ControlMessage{
+ TrafficClass: DiffServAF11 | CongestionExperienced,
+ HopLimit: 1,
+ }
+ if ifi != nil {
+ cm.IfIndex = ifi.Index
+ }
+ if n, err := p.WriteTo(wb, &cm, dst); err != nil {
+ b.Fatalf("ipv6.PacketConn.WriteTo failed: %v", err)
+ } else if n != len(wb) {
+ b.Fatalf("ipv6.PacketConn.WriteTo failed: short write: %v", n)
+ }
+ if _, _, _, err := p.ReadFrom(rb); err != nil {
+ b.Fatalf("ipv6.PacketConn.ReadFrom failed: %v", err)
+ }
+}
+
+func TestPacketConnConcurrentReadWriteUnicastUDP(t *testing.T) {
+ switch runtime.GOOS {
+ case "plan9", "windows":
+ t.Skipf("not supported on %q", runtime.GOOS)
+ }
+ if !supportsIPv6 {
+ t.Skip("ipv6 is not supported")
+ }
+
+ c, err := net.ListenPacket("udp6", "[::1]:0")
+ if err != nil {
+ t.Fatalf("net.ListenPacket failed: %v", err)
+ }
+ defer c.Close()
+ p := ipv6.NewPacketConn(c)
+ defer p.Close()
+
+ dst, err := net.ResolveUDPAddr("udp6", c.LocalAddr().String())
+ if err != nil {
+ t.Fatalf("net.ResolveUDPAddr failed: %v", err)
+ }
+
+ ifi := loopbackInterface()
+ cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
+ wb := []byte("HELLO-R-U-THERE")
+
+ var wg sync.WaitGroup
+ reader := func() {
+ defer wg.Done()
+ rb := make([]byte, 128)
+ if n, cm, _, err := p.ReadFrom(rb); err != nil {
+ t.Errorf("ipv6.PacketConn.ReadFrom failed: %v", err)
+ return
+ } else if !bytes.Equal(rb[:n], wb) {
+ t.Errorf("got %v; expected %v", rb[:n], wb)
+ return
+ } else {
+ t.Logf("rcvd cmsg: %v", cm)
+ }
+ }
+ writer := func(toggle bool) {
+ defer wg.Done()
+ cm := ipv6.ControlMessage{
+ TrafficClass: DiffServAF11 | CongestionExperienced,
+ Src: net.IPv6loopback,
+ Dst: net.IPv6loopback,
+ }
+ if ifi != nil {
+ cm.IfIndex = ifi.Index
+ }
+ if err := p.SetControlMessage(cf, toggle); err != nil {
+ t.Errorf("ipv6.PacketConn.SetControlMessage failed: %v", err)
+ return
+ }
+ if n, err := p.WriteTo(wb, &cm, dst); err != nil {
+ t.Errorf("ipv6.PacketConn.WriteTo failed: %v", err)
+ return
+ } else if n != len(wb) {
+ t.Errorf("ipv6.PacketConn.WriteTo failed: short write: %v", n)
+ return
+ }
+ }
+
+ const N = 10
+ wg.Add(N)
+ for i := 0; i < N; i++ {
+ go reader()
+ }
+ wg.Add(2 * N)
+ for i := 0; i < 2*N; i++ {
+ go writer(i%2 != 0)
+ }
+ wg.Add(N)
+ for i := 0; i < N; i++ {
+ go reader()
+ }
+ wg.Wait()
+}
diff --git a/ipv6/unicast_test.go b/ipv6/unicast_test.go
index fed8a69..ad42b5e 100644
--- a/ipv6/unicast_test.go
+++ b/ipv6/unicast_test.go
@@ -5,6 +5,7 @@
package ipv6_test
import (
+ "bytes"
"code.google.com/p/go.net/ipv6"
"net"
"os"
@@ -13,79 +14,6 @@
"time"
)
-func benchmarkUDPListener() (net.PacketConn, net.Addr, error) {
- c, err := net.ListenPacket("udp6", "[::1]:0")
- if err != nil {
- return nil, nil, err
- }
- dst, err := net.ResolveUDPAddr("udp6", c.LocalAddr().String())
- if err != nil {
- c.Close()
- return nil, nil, err
- }
- return c, dst, nil
-}
-
-func BenchmarkReadWriteNetUDP(b *testing.B) {
- c, dst, err := benchmarkUDPListener()
- if err != nil {
- b.Fatalf("benchmarkUDPListener failed: %v", err)
- }
- defer c.Close()
-
- wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128)
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- benchmarkReadWriteNetUDP(b, c, wb, rb, dst)
- }
-}
-
-func benchmarkReadWriteNetUDP(b *testing.B, c net.PacketConn, wb, rb []byte, dst net.Addr) {
- if _, err := c.WriteTo(wb, dst); err != nil {
- b.Fatalf("net.PacketConn.WriteTo failed: %v", err)
- }
- if _, _, err := c.ReadFrom(rb); err != nil {
- b.Fatalf("net.PacketConn.ReadFrom failed: %v", err)
- }
-}
-
-func BenchmarkReadWriteIPv6UDP(b *testing.B) {
- c, dst, err := benchmarkUDPListener()
- if err != nil {
- b.Fatalf("benchmarkUDPListener failed: %v", err)
- }
- defer c.Close()
-
- p := ipv6.NewPacketConn(c)
- cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagInterface | ipv6.FlagPathMTU
- if err := p.SetControlMessage(cf, true); err != nil {
- b.Fatalf("ipv6.PacketConn.SetControlMessage failed: %v", err)
- }
- ifi := loopbackInterface()
-
- wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128)
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- benchmarkReadWriteIPv6UDP(b, p, wb, rb, dst, ifi)
- }
-}
-
-func benchmarkReadWriteIPv6UDP(b *testing.B, p *ipv6.PacketConn, wb, rb []byte, dst net.Addr, ifi *net.Interface) {
- cm := ipv6.ControlMessage{
- TrafficClass: DiffServAF11 | CongestionExperienced,
- HopLimit: 1,
- }
- if ifi != nil {
- cm.IfIndex = ifi.Index
- }
- if _, err := p.WriteTo(wb, &cm, dst); err != nil {
- b.Fatalf("ipv6.PacketConn.WriteTo failed: %v", err)
- }
- if _, _, _, err := p.ReadFrom(rb); err != nil {
- b.Fatalf("ipv6.PacketConn.ReadFrom failed: %v", err)
- }
-}
-
func TestPacketConnReadWriteUnicastUDP(t *testing.T) {
switch runtime.GOOS {
case "plan9", "windows":
@@ -100,22 +28,25 @@
t.Fatalf("net.ListenPacket failed: %v", err)
}
defer c.Close()
+ p := ipv6.NewPacketConn(c)
+ defer p.Close()
dst, err := net.ResolveUDPAddr("udp6", c.LocalAddr().String())
if err != nil {
t.Fatalf("net.ResolveUDPAddr failed: %v", err)
}
- p := ipv6.NewPacketConn(c)
- defer p.Close()
cm := ipv6.ControlMessage{
TrafficClass: DiffServAF11 | CongestionExperienced,
+ Src: net.IPv6loopback,
+ Dst: net.IPv6loopback,
}
- cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagInterface | ipv6.FlagPathMTU
+ cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
ifi := loopbackInterface()
if ifi != nil {
cm.IfIndex = ifi.Index
}
+ wb := []byte("HELLO-R-U-THERE")
for i, toggle := range []bool{true, false, true} {
if err := p.SetControlMessage(cf, toggle); err != nil {
@@ -125,15 +56,19 @@
if err := p.SetWriteDeadline(time.Now().Add(time.Millisecond * 100)); err != nil {
t.Fatalf("ipv6.PacketConn.SetWriteDeadline failed: %v", err)
}
- if _, err := p.WriteTo([]byte("HELLO-R-U-THERE"), &cm, dst); err != nil {
+ if n, err := p.WriteTo(wb, &cm, dst); err != nil {
t.Fatalf("ipv6.PacketConn.WriteTo failed: %v", err)
+ } else if n != len(wb) {
+ t.Fatalf("ipv6.PacketConn.WriteTo failed: short write: %v", n)
}
- b := make([]byte, 128)
+ rb := make([]byte, 128)
if err := p.SetReadDeadline(time.Now().Add(time.Millisecond * 100)); err != nil {
t.Fatalf("ipv6.PacketConn.SetReadDeadline failed: %v", err)
}
- if _, cm, _, err := p.ReadFrom(b); err != nil {
+ if n, cm, _, err := p.ReadFrom(rb); err != nil {
t.Fatalf("ipv6.PacketConn.ReadFrom failed: %v", err)
+ } else if !bytes.Equal(rb[:n], wb) {
+ t.Fatalf("got %v; expected %v", rb[:n], wb)
} else {
t.Logf("rcvd cmsg: %v", cm)
}
@@ -157,6 +92,8 @@
t.Fatalf("net.ListenPacket failed: %v", err)
}
defer c.Close()
+ p := ipv6.NewPacketConn(c)
+ defer p.Close()
dst, err := net.ResolveIPAddr("ip6", "::1")
if err != nil {
@@ -164,10 +101,12 @@
}
pshicmp := ipv6PseudoHeader(c.LocalAddr().(*net.IPAddr).IP, dst.IP, ianaProtocolIPv6ICMP)
- p := ipv6.NewPacketConn(c)
- defer p.Close()
- cm := ipv6.ControlMessage{TrafficClass: DiffServAF11 | CongestionExperienced}
- cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagInterface | ipv6.FlagPathMTU
+ cm := ipv6.ControlMessage{
+ TrafficClass: DiffServAF11 | CongestionExperienced,
+ Src: net.IPv6loopback,
+ Dst: net.IPv6loopback,
+ }
+ cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
ifi := loopbackInterface()
if ifi != nil {
cm.IfIndex = ifi.Index
@@ -210,18 +149,20 @@
if err := p.SetWriteDeadline(time.Now().Add(time.Millisecond * 100)); err != nil {
t.Fatalf("ipv6.PacketConn.SetWriteDeadline failed: %v", err)
}
- if _, err := p.WriteTo(wb, &cm, dst); err != nil {
+ if n, err := p.WriteTo(wb, &cm, dst); err != nil {
t.Fatalf("ipv6.PacketConn.WriteTo failed: %v", err)
+ } else if n != len(wb) {
+ t.Fatalf("ipv6.PacketConn.WriteTo failed: short write: %v", n)
}
- b := make([]byte, 128)
+ rb := make([]byte, 128)
if err := p.SetReadDeadline(time.Now().Add(time.Millisecond * 100)); err != nil {
t.Fatalf("ipv6.PacketConn.SetReadDeadline failed: %v", err)
}
- if n, cm, _, err := p.ReadFrom(b); err != nil {
+ if n, cm, _, err := p.ReadFrom(rb); err != nil {
t.Fatalf("ipv6.PacketConn.ReadFrom failed: %v", err)
} else {
t.Logf("rcvd cmsg: %v", cm)
- if m, err := parseICMPMessage(b[:n]); err != nil {
+ if m, err := parseICMPMessage(rb[:n]); err != nil {
t.Fatalf("parseICMPMessage failed: %v", err)
} else if m.Type != ipv6.ICMPTypeEchoReply || m.Code != 0 {
t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, ipv6.ICMPTypeEchoReply, 0)