forked from quic-go/quic-go
migrate the send conn tests away from Ginkgo (#4817)
This commit is contained in:
@@ -4,12 +4,12 @@ import (
|
||||
"net"
|
||||
"net/netip"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/quic-go/quic-go/internal/protocol"
|
||||
"github.com/quic-go/quic-go/internal/utils"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
@@ -17,86 +17,84 @@ import (
|
||||
// GSO is actually supported on this platform.
|
||||
var platformSupportsGSO = len(appendUDPSegmentSizeMsg([]byte{}, 1337)) > 0
|
||||
|
||||
var _ = Describe("Connection (for sending packets)", func() {
|
||||
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())
|
||||
|
||||
It("gets the local and remote addresses", func() {
|
||||
localAddr := &net.UDPAddr{IP: net.IPv4(192, 168, 0, 1), Port: 1234}
|
||||
rawConn := NewMockRawConn(mockCtrl)
|
||||
rawConn.EXPECT().LocalAddr().Return(localAddr)
|
||||
c := newSendConn(rawConn, remoteAddr, packetInfo{}, utils.DefaultLogger)
|
||||
Expect(c.LocalAddr().String()).To(Equal("192.168.0.1:1234"))
|
||||
Expect(c.RemoteAddr().String()).To(Equal("192.168.100.200:1337"))
|
||||
})
|
||||
// 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())
|
||||
}
|
||||
|
||||
It("uses the local address from the packet info", func() {
|
||||
localAddr := &net.UDPAddr{IP: net.IPv4(192, 168, 0, 1), Port: 1234}
|
||||
rawConn := NewMockRawConn(mockCtrl)
|
||||
rawConn.EXPECT().LocalAddr().Return(localAddr)
|
||||
c := newSendConn(rawConn, remoteAddr, packetInfo{addr: netip.AddrFrom4([4]byte{127, 0, 0, 42})}, utils.DefaultLogger)
|
||||
Expect(c.LocalAddr().String()).To(Equal("127.0.0.42:1234"))
|
||||
})
|
||||
|
||||
// We're not using an OOB conn on windows, and packetInfo.OOB() always returns an empty slice.
|
||||
if runtime.GOOS != "windows" {
|
||||
It("sets the OOB", func() {
|
||||
rawConn := NewMockRawConn(mockCtrl)
|
||||
rawConn.EXPECT().LocalAddr()
|
||||
rawConn.EXPECT().capabilities().AnyTimes()
|
||||
pi := packetInfo{addr: netip.IPv6Loopback()}
|
||||
Expect(pi.OOB()).ToNot(BeEmpty())
|
||||
c := newSendConn(rawConn, remoteAddr, pi, utils.DefaultLogger)
|
||||
rawConn.EXPECT().WritePacket([]byte("foobar"), remoteAddr, pi.OOB(), uint16(0), protocol.ECT1)
|
||||
Expect(c.Write([]byte("foobar"), 0, protocol.ECT1)).To(Succeed())
|
||||
})
|
||||
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")
|
||||
}
|
||||
|
||||
It("writes", func() {
|
||||
rawConn := NewMockRawConn(mockCtrl)
|
||||
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)
|
||||
rawConn.EXPECT().WritePacket([]byte("foobar"), remoteAddr, gomock.Any(), uint16(3), protocol.ECNCE)
|
||||
Expect(c.Write([]byte("foobar"), 3, protocol.ECNCE)).To(Succeed())
|
||||
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))
|
||||
})
|
||||
|
||||
if platformSupportsGSO {
|
||||
It("disables GSO if sending fails", func() {
|
||||
rawConn := NewMockRawConn(mockCtrl)
|
||||
rawConn.EXPECT().LocalAddr()
|
||||
rawConn.EXPECT().capabilities().Return(connCapabilities{GSO: true}).AnyTimes()
|
||||
c := newSendConn(rawConn, remoteAddr, packetInfo{}, utils.DefaultLogger)
|
||||
Expect(c.capabilities().GSO).To(BeTrue())
|
||||
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),
|
||||
)
|
||||
Expect(c.Write([]byte("foobar"), 4, protocol.ECNCE)).To(Succeed())
|
||||
Expect(c.capabilities().GSO).To(BeFalse())
|
||||
})
|
||||
}
|
||||
|
||||
if runtime.GOOS == "linux" {
|
||||
It("doesn't fail if the very first sendmsg call fails", func() {
|
||||
rawConn := NewMockRawConn(mockCtrl)
|
||||
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),
|
||||
)
|
||||
Expect(c.Write([]byte("foobar"), 0, protocol.ECNCE)).To(Succeed())
|
||||
})
|
||||
|
||||
It("fails if the sendmsg calls fail multiple times", func() {
|
||||
rawConn := NewMockRawConn(mockCtrl)
|
||||
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)
|
||||
Expect(c.Write([]byte("foobar"), 0, protocol.ECNCE)).To(MatchError(errNotPermitted))
|
||||
})
|
||||
}
|
||||
})
|
||||
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))
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user