Skip to content

Commit 8ecd624

Browse files
committed
go.net/ipv4: fix flaky test cases
Fixes golang/go#5709. Fixes golang/go#5811. LGTM=dave R=dave CC=golang-codereviews https://golang.org/cl/21360043
1 parent fbcd5c9 commit 8ecd624

5 files changed

+398
-295
lines changed

ipv4/mocktransponder_test.go

Lines changed: 11 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -5,74 +5,10 @@
55
package ipv4_test
66

77
import (
8-
"code.google.com/p/go.net/ipv4"
98
"net"
109
"testing"
11-
"time"
1210
)
1311

14-
// writeThenReadPayload transmits IPv4 datagram payloads to the
15-
// loopback address or interface and captures the loopback'd datagram
16-
// payloads.
17-
func writeThenReadPayload(t *testing.T, i int, c *ipv4.PacketConn, wb []byte, dst net.Addr) []byte {
18-
rb := make([]byte, 1500)
19-
c.SetTOS(i + 1)
20-
var ip net.IP
21-
switch v := dst.(type) {
22-
case *net.UDPAddr:
23-
ip = v.IP
24-
case *net.IPAddr:
25-
ip = v.IP
26-
}
27-
if ip.IsMulticast() {
28-
c.SetMulticastTTL(i + 1)
29-
} else {
30-
c.SetTTL(i + 1)
31-
}
32-
c.SetDeadline(time.Now().Add(100 * time.Millisecond))
33-
if _, err := c.WriteTo(wb, nil, dst); err != nil {
34-
t.Fatalf("ipv4.PacketConn.WriteTo failed: %v", err)
35-
}
36-
n, cm, _, err := c.ReadFrom(rb)
37-
if err != nil {
38-
t.Fatalf("ipv4.PacketConn.ReadFrom failed: %v", err)
39-
}
40-
t.Logf("rcvd cmsg: %v", cm)
41-
return rb[:n]
42-
}
43-
44-
// writeThenReadDatagram transmits ICMP for IPv4 datagrams to the
45-
// loopback address or interface and captures the response datagrams
46-
// from the protocol stack within the kernel.
47-
func writeThenReadDatagram(t *testing.T, i int, c *ipv4.RawConn, wb []byte, src, dst net.Addr) []byte {
48-
rb := make([]byte, ipv4.HeaderLen+len(wb))
49-
wh := &ipv4.Header{
50-
Version: ipv4.Version,
51-
Len: ipv4.HeaderLen,
52-
TOS: i + 1,
53-
TotalLen: ipv4.HeaderLen + len(wb),
54-
TTL: i + 1,
55-
Protocol: 1,
56-
}
57-
if src != nil {
58-
wh.Src = src.(*net.IPAddr).IP
59-
}
60-
if dst != nil {
61-
wh.Dst = dst.(*net.IPAddr).IP
62-
}
63-
c.SetDeadline(time.Now().Add(100 * time.Millisecond))
64-
if err := c.WriteTo(wh, wb, nil); err != nil {
65-
t.Fatalf("ipv4.RawConn.WriteTo failed: %v", err)
66-
}
67-
rh, b, cm, err := c.ReadFrom(rb)
68-
if err != nil {
69-
t.Fatalf("ipv4.RawConn.ReadFrom failed: %v", err)
70-
}
71-
t.Logf("rcvd cmsg: %v", cm.String())
72-
t.Logf("rcvd hdr: %v", rh.String())
73-
return b
74-
}
75-
7612
func isUnicast(ip net.IP) bool {
7713
return ip.To4() != nil && (ip.IsLoopback() || ip.IsLinkLocalUnicast() || ip.IsGlobalUnicast())
7814
}
@@ -133,3 +69,14 @@ func isMulticastAvailable(ifi *net.Interface) (net.IP, bool) {
13369
}
13470
return nil, false
13571
}
72+
73+
func acceptor(t *testing.T, ln net.Listener, done chan<- bool) {
74+
defer func() { done <- true }()
75+
76+
c, err := ln.Accept()
77+
if err != nil {
78+
t.Errorf("net.Listener.Accept failed: %v", err)
79+
return
80+
}
81+
c.Close()
82+
}

ipv4/multicast_test.go

Lines changed: 122 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,87 +2,124 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
// +build darwin freebsd linux netbsd openbsd
6-
75
package ipv4_test
86

97
import (
108
"code.google.com/p/go.net/ipv4"
119
"net"
1210
"os"
11+
"runtime"
1312
"testing"
13+
"time"
1414
)
1515

16-
func TestReadWriteMulticastIPPayloadUDP(t *testing.T) {
17-
if testing.Short() || !*testExternal {
18-
t.Skip("to avoid external network")
16+
func TestPacketConnReadWriteMulticastUDP(t *testing.T) {
17+
switch runtime.GOOS {
18+
case "plan9", "windows":
19+
t.Skipf("not supported on %q", runtime.GOOS)
20+
}
21+
ifi := loopbackInterface()
22+
if ifi == nil {
23+
t.Skipf("not available on %q", runtime.GOOS)
1924
}
2025

21-
c, err := net.ListenPacket("udp4", "224.0.0.0:1024") // see RFC 4727
26+
c, err := net.ListenPacket("udp4", "224.0.0.0:0") // see RFC 4727
2227
if err != nil {
2328
t.Fatalf("net.ListenPacket failed: %v", err)
2429
}
2530
defer c.Close()
2631

27-
ifi := loopbackInterface()
28-
if ifi == nil {
29-
t.Skip("an appropriate interface not found")
32+
_, port, err := net.SplitHostPort(c.LocalAddr().String())
33+
if err != nil {
34+
t.Fatalf("net.SplitHostPort failed: %v", err)
3035
}
31-
dst, err := net.ResolveUDPAddr("udp4", "224.0.0.254:1024") // see RFC 4727
36+
dst, err := net.ResolveUDPAddr("udp4", "224.0.0.254:"+port) // see RFC 4727
3237
if err != nil {
3338
t.Fatalf("net.ResolveUDPAddr failed: %v", err)
3439
}
3540

3641
p := ipv4.NewPacketConn(c)
42+
defer p.Close()
3743
if err := p.JoinGroup(ifi, dst); err != nil {
3844
t.Fatalf("ipv4.PacketConn.JoinGroup on %v failed: %v", ifi, err)
3945
}
4046
if err := p.SetMulticastInterface(ifi); err != nil {
4147
t.Fatalf("ipv4.PacketConn.SetMulticastInterface failed: %v", err)
4248
}
49+
if _, err := p.MulticastInterface(); err != nil {
50+
t.Fatalf("ipv4.PacketConn.MulticastInterface failed: %v", err)
51+
}
4352
if err := p.SetMulticastLoopback(true); err != nil {
4453
t.Fatalf("ipv4.PacketConn.SetMulticastLoopback failed: %v", err)
4554
}
55+
if _, err := p.MulticastLoopback(); err != nil {
56+
t.Fatalf("ipv4.PacketConn.MulticastLoopback failed: %v", err)
57+
}
4658
cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
59+
4760
for i, toggle := range []bool{true, false, true} {
4861
if err := p.SetControlMessage(cf, toggle); err != nil {
4962
t.Fatalf("ipv4.PacketConn.SetControlMessage failed: %v", err)
5063
}
51-
writeThenReadPayload(t, i, p, []byte("HELLO-R-U-THERE"), dst)
64+
if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
65+
t.Fatalf("ipv4.PacketConn.SetDeadline failed: %v", err)
66+
}
67+
p.SetMulticastTTL(i + 1)
68+
if _, err := p.WriteTo([]byte("HELLO-R-U-THERE"), nil, dst); err != nil {
69+
t.Fatalf("ipv4.PacketConn.WriteTo failed: %v", err)
70+
}
71+
b := make([]byte, 128)
72+
if _, cm, _, err := p.ReadFrom(b); err != nil {
73+
t.Fatalf("ipv4.PacketConn.ReadFrom failed: %v", err)
74+
} else {
75+
t.Logf("rcvd cmsg: %v", cm)
76+
}
5277
}
5378
}
5479

55-
func TestReadWriteMulticastIPPayloadICMP(t *testing.T) {
56-
if testing.Short() || !*testExternal {
57-
t.Skip("to avoid external network")
80+
func TestPacketConnReadWriteMulticastICMP(t *testing.T) {
81+
switch runtime.GOOS {
82+
case "plan9", "windows":
83+
t.Skipf("not supported on %q", runtime.GOOS)
5884
}
5985
if os.Getuid() != 0 {
6086
t.Skip("must be root")
6187
}
88+
ifi := loopbackInterface()
89+
if ifi == nil {
90+
t.Skipf("not available on %q", runtime.GOOS)
91+
}
6292

6393
c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
6494
if err != nil {
6595
t.Fatalf("net.ListenPacket failed: %v", err)
6696
}
6797
defer c.Close()
6898

69-
ifi := loopbackInterface()
70-
if ifi == nil {
71-
t.Skip("an appropriate interface not found")
72-
}
7399
dst, err := net.ResolveIPAddr("ip4", "224.0.0.254") // see RFC 4727
74100
if err != nil {
75101
t.Fatalf("net.ResolveIPAddr failed: %v", err)
76102
}
77103

78104
p := ipv4.NewPacketConn(c)
105+
defer p.Close()
79106
if err := p.JoinGroup(ifi, dst); err != nil {
80107
t.Fatalf("ipv4.PacketConn.JoinGroup on %v failed: %v", ifi, err)
81108
}
82109
if err := p.SetMulticastInterface(ifi); err != nil {
83110
t.Fatalf("ipv4.PacketConn.SetMulticastInterface failed: %v", err)
84111
}
112+
if _, err := p.MulticastInterface(); err != nil {
113+
t.Fatalf("ipv4.PacketConn.MulticastInterface failed: %v", err)
114+
}
115+
if err := p.SetMulticastLoopback(true); err != nil {
116+
t.Fatalf("ipv4.PacketConn.SetMulticastLoopback failed: %v", err)
117+
}
118+
if _, err := p.MulticastLoopback(); err != nil {
119+
t.Fatalf("ipv4.PacketConn.MulticastLoopback failed: %v", err)
120+
}
85121
cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
122+
86123
for i, toggle := range []bool{true, false, true} {
87124
wb, err := (&icmpMessage{
88125
Type: ipv4.ICMPTypeEcho, Code: 0,
@@ -97,35 +134,50 @@ func TestReadWriteMulticastIPPayloadICMP(t *testing.T) {
97134
if err := p.SetControlMessage(cf, toggle); err != nil {
98135
t.Fatalf("ipv4.PacketConn.SetControlMessage failed: %v", err)
99136
}
100-
rb := writeThenReadPayload(t, i, p, wb, dst)
101-
m, err := parseICMPMessage(rb)
102-
if err != nil {
103-
t.Fatalf("parseICMPMessage failed: %v", err)
137+
if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
138+
t.Fatalf("ipv4.PacketConn.SetDeadline failed: %v", err)
139+
}
140+
p.SetMulticastTTL(i + 1)
141+
if _, err := p.WriteTo(wb, nil, dst); err != nil {
142+
t.Fatalf("ipv4.PacketConn.WriteTo failed: %v", err)
104143
}
105-
if m.Type != ipv4.ICMPTypeEchoReply || m.Code != 0 {
106-
t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
144+
b := make([]byte, 128)
145+
if n, cm, _, err := p.ReadFrom(b); err != nil {
146+
t.Fatalf("ipv4.PacketConn.ReadFrom failed: %v", err)
147+
} else {
148+
t.Logf("rcvd cmsg: %v", cm)
149+
m, err := parseICMPMessage(b[:n])
150+
if err != nil {
151+
t.Fatalf("parseICMPMessage failed: %v", err)
152+
}
153+
switch {
154+
case m.Type == ipv4.ICMPTypeEchoReply && m.Code == 0: // net.inet.icmp.bmcastecho=1
155+
case m.Type == ipv4.ICMPTypeEcho && m.Code == 0: // net.inet.icmp.bmcastecho=0
156+
default:
157+
t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
158+
}
107159
}
108160
}
109161
}
110162

111-
func TestReadWriteMulticastIPDatagram(t *testing.T) {
163+
func TestRawConnReadWriteMulticastICMP(t *testing.T) {
112164
if testing.Short() || !*testExternal {
113165
t.Skip("to avoid external network")
114166
}
115167
if os.Getuid() != 0 {
116168
t.Skip("must be root")
117169
}
170+
ifi := loopbackInterface()
171+
if ifi == nil {
172+
t.Skipf("not available on %q", runtime.GOOS)
173+
}
118174

119175
c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
120176
if err != nil {
121177
t.Fatalf("net.ListenPacket failed: %v", err)
122178
}
123179
defer c.Close()
124180

125-
ifi := loopbackInterface()
126-
if ifi == nil {
127-
t.Skip("an appropriate interface not found")
128-
}
129181
dst, err := net.ResolveIPAddr("ip4", "224.0.0.254") // see RFC 4727
130182
if err != nil {
131183
t.Fatalf("ResolveIPAddr failed: %v", err)
@@ -135,13 +187,24 @@ func TestReadWriteMulticastIPDatagram(t *testing.T) {
135187
if err != nil {
136188
t.Fatalf("ipv4.NewRawConn failed: %v", err)
137189
}
190+
defer r.Close()
138191
if err := r.JoinGroup(ifi, dst); err != nil {
139192
t.Fatalf("ipv4.RawConn.JoinGroup on %v failed: %v", ifi, err)
140193
}
141194
if err := r.SetMulticastInterface(ifi); err != nil {
142-
t.Fatalf("ipv4.PacketConn.SetMulticastInterface failed: %v", err)
195+
t.Fatalf("ipv4.RawConn.SetMulticastInterface failed: %v", err)
196+
}
197+
if _, err := r.MulticastInterface(); err != nil {
198+
t.Fatalf("ipv4.RawConn.MulticastInterface failed: %v", err)
199+
}
200+
if err := r.SetMulticastLoopback(true); err != nil {
201+
t.Fatalf("ipv4.RawConn.SetMulticastLoopback failed: %v", err)
202+
}
203+
if _, err := r.MulticastLoopback(); err != nil {
204+
t.Fatalf("ipv4.RawConn.MulticastLoopback failed: %v", err)
143205
}
144206
cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
207+
145208
for i, toggle := range []bool{true, false, true} {
146209
wb, err := (&icmpMessage{
147210
Type: ipv4.ICMPTypeEcho, Code: 0,
@@ -153,16 +216,39 @@ func TestReadWriteMulticastIPDatagram(t *testing.T) {
153216
if err != nil {
154217
t.Fatalf("icmpMessage.Marshal failed: %v", err)
155218
}
219+
wh := &ipv4.Header{
220+
Version: ipv4.Version,
221+
Len: ipv4.HeaderLen,
222+
TOS: i + 1,
223+
TotalLen: ipv4.HeaderLen + len(wb),
224+
Protocol: 1,
225+
Dst: dst.IP,
226+
}
156227
if err := r.SetControlMessage(cf, toggle); err != nil {
157228
t.Fatalf("ipv4.RawConn.SetControlMessage failed: %v", err)
158229
}
159-
rb := writeThenReadDatagram(t, i, r, wb, nil, dst)
160-
m, err := parseICMPMessage(rb)
161-
if err != nil {
162-
t.Fatalf("parseICMPMessage failed: %v", err)
230+
if err := r.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
231+
t.Fatalf("ipv4.RawConn.SetDeadline failed: %v", err)
232+
}
233+
r.SetMulticastTTL(i + 1)
234+
if err := r.WriteTo(wh, wb, nil); err != nil {
235+
t.Fatalf("ipv4.RawConn.WriteTo failed: %v", err)
163236
}
164-
if m.Type != ipv4.ICMPTypeEchoReply || m.Code != 0 {
165-
t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
237+
rb := make([]byte, ipv4.HeaderLen+128)
238+
if rh, b, cm, err := r.ReadFrom(rb); err != nil {
239+
t.Fatalf("ipv4.RawConn.ReadFrom failed: %v", err)
240+
} else {
241+
t.Logf("rcvd cmsg: %v", cm)
242+
m, err := parseICMPMessage(b)
243+
if err != nil {
244+
t.Fatalf("parseICMPMessage failed: %v", err)
245+
}
246+
switch {
247+
case isUnicast(rh.Dst) && m.Type == ipv4.ICMPTypeEchoReply && m.Code == 0: // net.inet.icmp.bmcastecho=1
248+
case rh.Dst.IsMulticast() && m.Type == ipv4.ICMPTypeEcho && m.Code == 0: // net.inet.icmp.bmcastecho=0
249+
default:
250+
t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
251+
}
166252
}
167253
}
168254
}

0 commit comments

Comments
 (0)