forked from quic-go/quic-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsend_conn_test.go
100 lines (86 loc) · 4.02 KB
/
send_conn_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package quic
import (
"net"
"net/netip"
"runtime"
"testing"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/utils"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
)
// Only if appendUDPSegmentSizeMsg actually appends a message (and isn't only a stub implementation),
// GSO is actually supported on this platform.
var platformSupportsGSO = len(appendUDPSegmentSizeMsg([]byte{}, 1337)) > 0
func TestSendConnLocalAndRemoteAddress(t *testing.T) {
remoteAddr := &net.UDPAddr{IP: net.IPv4(192, 168, 100, 200), Port: 1337}
rawConn := NewMockRawConn(gomock.NewController(t))
rawConn.EXPECT().LocalAddr().Return(&net.UDPAddr{IP: net.IPv4(10, 11, 12, 13), Port: 14}).Times(2)
c := newSendConn(
rawConn,
remoteAddr,
packetInfo{addr: netip.AddrFrom4([4]byte{127, 0, 0, 42})},
utils.DefaultLogger,
)
require.Equal(t, "127.0.0.42:14", c.LocalAddr().String())
require.Equal(t, remoteAddr, c.RemoteAddr())
// the local raw conn's local address is only used if we don't an address from the packet info
c = newSendConn(rawConn, remoteAddr, packetInfo{}, utils.DefaultLogger)
require.Equal(t, "10.11.12.13:14", c.LocalAddr().String())
}
func TestSendConnOOB(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("we don't OOB conn on windows, and no packet info will be available")
}
remoteAddr := &net.UDPAddr{IP: net.IPv4(192, 168, 100, 200), Port: 1337}
rawConn := NewMockRawConn(gomock.NewController(t))
rawConn.EXPECT().LocalAddr()
rawConn.EXPECT().capabilities().AnyTimes()
pi := packetInfo{addr: netip.IPv6Loopback()}
rawConn.EXPECT().WritePacket([]byte("foobar"), remoteAddr, pi.OOB(), uint16(0), protocol.ECT1)
require.NotEmpty(t, pi.OOB())
c := newSendConn(rawConn, remoteAddr, pi, utils.DefaultLogger)
require.NoError(t, c.Write([]byte("foobar"), 0, protocol.ECT1))
}
func TestSendConnDetectGSOFailure(t *testing.T) {
if !platformSupportsGSO {
t.Skip("GSO is not supported on this platform")
}
remoteAddr := &net.UDPAddr{IP: net.IPv4(192, 168, 100, 200), Port: 1337}
rawConn := NewMockRawConn(gomock.NewController(t))
rawConn.EXPECT().LocalAddr()
rawConn.EXPECT().capabilities().Return(connCapabilities{GSO: true}).MinTimes(1)
c := newSendConn(rawConn, remoteAddr, packetInfo{}, utils.DefaultLogger)
gomock.InOrder(
rawConn.EXPECT().WritePacket([]byte("foobar"), remoteAddr, gomock.Any(), uint16(4), protocol.ECNCE).Return(0, errGSO),
rawConn.EXPECT().WritePacket([]byte("foob"), remoteAddr, gomock.Any(), uint16(0), protocol.ECNCE).Return(4, nil),
rawConn.EXPECT().WritePacket([]byte("ar"), remoteAddr, gomock.Any(), uint16(0), protocol.ECNCE).Return(2, nil),
)
require.NoError(t, c.Write([]byte("foobar"), 4, protocol.ECNCE))
require.False(t, c.capabilities().GSO)
}
func TestSendConnSendmsgFailures(t *testing.T) {
if runtime.GOOS != "linux" {
t.Skip("only Linux exhibits this bug, we don't need to work around it on other platforms")
}
remoteAddr := &net.UDPAddr{IP: net.IPv4(192, 168, 100, 200), Port: 1337}
t.Run("first call to sendmsg fails", func(t *testing.T) {
rawConn := NewMockRawConn(gomock.NewController(t))
rawConn.EXPECT().LocalAddr()
rawConn.EXPECT().capabilities().AnyTimes()
c := newSendConn(rawConn, remoteAddr, packetInfo{}, utils.DefaultLogger)
gomock.InOrder(
rawConn.EXPECT().WritePacket([]byte("foobar"), remoteAddr, gomock.Any(), gomock.Any(), protocol.ECNCE).Return(0, errNotPermitted),
rawConn.EXPECT().WritePacket([]byte("foobar"), remoteAddr, gomock.Any(), uint16(0), protocol.ECNCE).Return(6, nil),
)
require.NoError(t, c.Write([]byte("foobar"), 0, protocol.ECNCE))
})
t.Run("later call to sendmsg fails", func(t *testing.T) {
rawConn := NewMockRawConn(gomock.NewController(t))
rawConn.EXPECT().LocalAddr()
rawConn.EXPECT().capabilities().AnyTimes()
c := newSendConn(rawConn, remoteAddr, packetInfo{}, utils.DefaultLogger)
rawConn.EXPECT().WritePacket([]byte("foobar"), remoteAddr, gomock.Any(), gomock.Any(), protocol.ECNCE).Return(0, errNotPermitted).Times(2)
require.Error(t, c.Write([]byte("foobar"), 0, protocol.ECNCE))
})
}