refactor(netxlite): hide details without breaking the rest of the tree (#454)
## Description This PR continues the refactoring of `netx` under the following principles: 1. do not break the rest of the tree and do not engage in extensive tree-wide refactoring yet 2. move under `netxlite` clearly related subpackages (e.g., `iox`, `netxmocks`) 3. move into `internal/netxlite/internal` stuff that is clearly private of `netxlite` 4. hide implementation details in `netxlite` pending new factories 5. refactor `tls` code in `netxlite` to clearly separate `crypto/tls` code from `utls` code After each commit, I run `go test -short -race ./...` locally. Each individual commit explains what it does. I will squash, but this operation will preserve the original commit titles, so this will give further insight on each step. ## Commits * refactor: rename netxmocks -> netxlite/mocks Part of https://github.com/ooni/probe/issues/1591 * refactor: rename quicx -> netxlite/quicx See https://github.com/ooni/probe/issues/1591 * refactor: rename iox -> netxlite/iox Regenerate sources and make sure the tests pass. See https://github.com/ooni/probe/issues/1591. * refactor(iox): move MockableReader to netxlite/mocks See https://github.com/ooni/probe/issues/1591 * refactor(netxlite): generator is an implementation detail See https://github.com/ooni/probe/issues/1591 * refactor(netxlite): separate tls and utls code See https://github.com/ooni/probe/issues/1591 * refactor(netxlite): hide most types but keep old names as legacy With this change we avoid breaking the rest of the tree, but we start hiding some implementation details a bit. Factories will follow. See https://github.com/ooni/probe/issues/1591
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
package mocks
|
||||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Conn is a mockable net.Conn.
|
||||
type Conn struct {
|
||||
MockRead func(b []byte) (int, error)
|
||||
MockWrite func(b []byte) (int, error)
|
||||
MockClose func() error
|
||||
MockLocalAddr func() net.Addr
|
||||
MockRemoteAddr func() net.Addr
|
||||
MockSetDeadline func(t time.Time) error
|
||||
MockSetReadDeadline func(t time.Time) error
|
||||
MockSetWriteDeadline func(t time.Time) error
|
||||
}
|
||||
|
||||
// Read calls MockRead.
|
||||
func (c *Conn) Read(b []byte) (int, error) {
|
||||
return c.MockRead(b)
|
||||
}
|
||||
|
||||
// Write calls MockWrite.
|
||||
func (c *Conn) Write(b []byte) (int, error) {
|
||||
return c.MockWrite(b)
|
||||
}
|
||||
|
||||
// Close calls MockClose.
|
||||
func (c *Conn) Close() error {
|
||||
return c.MockClose()
|
||||
}
|
||||
|
||||
// LocalAddr calls MockLocalAddr.
|
||||
func (c *Conn) LocalAddr() net.Addr {
|
||||
return c.MockLocalAddr()
|
||||
}
|
||||
|
||||
// RemoteAddr calls MockRemoteAddr.
|
||||
func (c *Conn) RemoteAddr() net.Addr {
|
||||
return c.MockRemoteAddr()
|
||||
}
|
||||
|
||||
// SetDeadline calls MockSetDeadline.
|
||||
func (c *Conn) SetDeadline(t time.Time) error {
|
||||
return c.MockSetDeadline(t)
|
||||
}
|
||||
|
||||
// SetReadDeadline calls MockSetReadDeadline.
|
||||
func (c *Conn) SetReadDeadline(t time.Time) error {
|
||||
return c.MockSetReadDeadline(t)
|
||||
}
|
||||
|
||||
// SetWriteDeadline calls MockSetWriteDeadline.
|
||||
func (c *Conn) SetWriteDeadline(t time.Time) error {
|
||||
return c.MockSetWriteDeadline(t)
|
||||
}
|
||||
|
||||
var _ net.Conn = &Conn{}
|
||||
@@ -0,0 +1,126 @@
|
||||
package mocks
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
)
|
||||
|
||||
func TestConnReadWorks(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
c := &Conn{
|
||||
MockRead: func(b []byte) (int, error) {
|
||||
return 0, expected
|
||||
},
|
||||
}
|
||||
count, err := c.Read(make([]byte, 128))
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected")
|
||||
}
|
||||
if count != 0 {
|
||||
t.Fatal("expected 0 bytes")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConnWriteWorks(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
c := &Conn{
|
||||
MockWrite: func(b []byte) (int, error) {
|
||||
return 0, expected
|
||||
},
|
||||
}
|
||||
count, err := c.Write(make([]byte, 128))
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected")
|
||||
}
|
||||
if count != 0 {
|
||||
t.Fatal("expected 0 bytes")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConnCloseWorks(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
c := &Conn{
|
||||
MockClose: func() error {
|
||||
return expected
|
||||
},
|
||||
}
|
||||
err := c.Close()
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConnLocalAddrWorks(t *testing.T) {
|
||||
expected := &net.TCPAddr{
|
||||
IP: net.IPv6loopback,
|
||||
Port: 1234,
|
||||
}
|
||||
c := &Conn{
|
||||
MockLocalAddr: func() net.Addr {
|
||||
return expected
|
||||
},
|
||||
}
|
||||
out := c.LocalAddr()
|
||||
if diff := cmp.Diff(expected, out); diff != "" {
|
||||
t.Fatal(diff)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConnRemoteAddrWorks(t *testing.T) {
|
||||
expected := &net.TCPAddr{
|
||||
IP: net.IPv6loopback,
|
||||
Port: 1234,
|
||||
}
|
||||
c := &Conn{
|
||||
MockRemoteAddr: func() net.Addr {
|
||||
return expected
|
||||
},
|
||||
}
|
||||
out := c.RemoteAddr()
|
||||
if diff := cmp.Diff(expected, out); diff != "" {
|
||||
t.Fatal(diff)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConnSetDeadline(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
c := &Conn{
|
||||
MockSetDeadline: func(t time.Time) error {
|
||||
return expected
|
||||
},
|
||||
}
|
||||
err := c.SetDeadline(time.Time{})
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConnSetReadDeadline(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
c := &Conn{
|
||||
MockSetReadDeadline: func(t time.Time) error {
|
||||
return expected
|
||||
},
|
||||
}
|
||||
err := c.SetReadDeadline(time.Time{})
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConnSetWriteDeadline(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
c := &Conn{
|
||||
MockSetWriteDeadline: func(t time.Time) error {
|
||||
return expected
|
||||
},
|
||||
}
|
||||
err := c.SetWriteDeadline(time.Time{})
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package mocks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
)
|
||||
|
||||
// Dialer is a mockable Dialer.
|
||||
type Dialer struct {
|
||||
MockDialContext func(ctx context.Context, network, address string) (net.Conn, error)
|
||||
}
|
||||
|
||||
// DialContext calls MockDialContext.
|
||||
func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
return d.MockDialContext(ctx, network, address)
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package mocks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDialerWorks(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
d := Dialer{
|
||||
MockDialContext: func(ctx context.Context, network string, address string) (net.Conn, error) {
|
||||
return nil, expected
|
||||
},
|
||||
}
|
||||
ctx := context.Background()
|
||||
conn, err := d.DialContext(ctx, "tcp", "8.8.8.8:53")
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected")
|
||||
}
|
||||
if conn != nil {
|
||||
t.Fatal("expected nil conn")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
// Package mocks contains mocks for netx types.
|
||||
package mocks
|
||||
@@ -0,0 +1,19 @@
|
||||
package mocks
|
||||
|
||||
import "net/http"
|
||||
|
||||
// HTTPTransport mocks netxlite.HTTPTransport.
|
||||
type HTTPTransport struct {
|
||||
MockRoundTrip func(req *http.Request) (*http.Response, error)
|
||||
MockCloseIdleConnections func()
|
||||
}
|
||||
|
||||
// RoundTrip calls MockRoundTrip.
|
||||
func (txp *HTTPTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
return txp.MockRoundTrip(req)
|
||||
}
|
||||
|
||||
// CloseIdleConnections calls MockCloseIdleConnections.
|
||||
func (txp *HTTPTransport) CloseIdleConnections() {
|
||||
txp.MockCloseIdleConnections()
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package mocks
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/atomicx"
|
||||
)
|
||||
|
||||
func TestHTTPTransportRoundTrip(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
txp := &HTTPTransport{
|
||||
MockRoundTrip: func(req *http.Request) (*http.Response, error) {
|
||||
return nil, expected
|
||||
},
|
||||
}
|
||||
resp, err := txp.RoundTrip(&http.Request{})
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
if resp != nil {
|
||||
t.Fatal("expected nil response here")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPTransportCloseIdleConnections(t *testing.T) {
|
||||
called := &atomicx.Int64{}
|
||||
txp := &HTTPTransport{
|
||||
MockCloseIdleConnections: func() {
|
||||
called.Add(1)
|
||||
},
|
||||
}
|
||||
txp.CloseIdleConnections()
|
||||
if called.Load() != 1 {
|
||||
t.Fatal("not called")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
package mocks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite/quicx"
|
||||
)
|
||||
|
||||
// QUICListener is a mockable netxlite.QUICListener.
|
||||
type QUICListener struct {
|
||||
MockListen func(addr *net.UDPAddr) (quicx.UDPLikeConn, error)
|
||||
}
|
||||
|
||||
// Listen calls MockListen.
|
||||
func (ql *QUICListener) Listen(addr *net.UDPAddr) (quicx.UDPLikeConn, error) {
|
||||
return ql.MockListen(addr)
|
||||
}
|
||||
|
||||
// QUICContextDialer is a mockable netxlite.QUICContextDialer.
|
||||
type QUICContextDialer struct {
|
||||
MockDialContext func(ctx context.Context, network, address string,
|
||||
tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlySession, error)
|
||||
}
|
||||
|
||||
// DialContext calls MockDialContext.
|
||||
func (qcd *QUICContextDialer) DialContext(ctx context.Context, network, address string,
|
||||
tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlySession, error) {
|
||||
return qcd.MockDialContext(ctx, network, address, tlsConfig, quicConfig)
|
||||
}
|
||||
|
||||
// QUICEarlySession is a mockable quic.EarlySession.
|
||||
type QUICEarlySession struct {
|
||||
MockAcceptStream func(context.Context) (quic.Stream, error)
|
||||
MockAcceptUniStream func(context.Context) (quic.ReceiveStream, error)
|
||||
MockOpenStream func() (quic.Stream, error)
|
||||
MockOpenStreamSync func(ctx context.Context) (quic.Stream, error)
|
||||
MockOpenUniStream func() (quic.SendStream, error)
|
||||
MockOpenUniStreamSync func(ctx context.Context) (quic.SendStream, error)
|
||||
MockLocalAddr func() net.Addr
|
||||
MockRemoteAddr func() net.Addr
|
||||
MockCloseWithError func(code quic.ApplicationErrorCode, reason string) error
|
||||
MockContext func() context.Context
|
||||
MockConnectionState func() quic.ConnectionState
|
||||
MockHandshakeComplete func() context.Context
|
||||
MockNextSession func() quic.Session
|
||||
MockSendMessage func(b []byte) error
|
||||
MockReceiveMessage func() ([]byte, error)
|
||||
}
|
||||
|
||||
var _ quic.EarlySession = &QUICEarlySession{}
|
||||
|
||||
// AcceptStream calls MockAcceptStream.
|
||||
func (s *QUICEarlySession) AcceptStream(ctx context.Context) (quic.Stream, error) {
|
||||
return s.MockAcceptStream(ctx)
|
||||
}
|
||||
|
||||
// AcceptUniStream calls MockAcceptUniStream.
|
||||
func (s *QUICEarlySession) AcceptUniStream(ctx context.Context) (quic.ReceiveStream, error) {
|
||||
return s.MockAcceptUniStream(ctx)
|
||||
}
|
||||
|
||||
// OpenStream calls MockOpenStream.
|
||||
func (s *QUICEarlySession) OpenStream() (quic.Stream, error) {
|
||||
return s.MockOpenStream()
|
||||
}
|
||||
|
||||
// OpenStreamSync calls MockOpenStreamSync.
|
||||
func (s *QUICEarlySession) OpenStreamSync(ctx context.Context) (quic.Stream, error) {
|
||||
return s.MockOpenStreamSync(ctx)
|
||||
}
|
||||
|
||||
// OpenUniStream calls MockOpenUniStream.
|
||||
func (s *QUICEarlySession) OpenUniStream() (quic.SendStream, error) {
|
||||
return s.MockOpenUniStream()
|
||||
}
|
||||
|
||||
// OpenUniStreamSync calls MockOpenUniStreamSync.
|
||||
func (s *QUICEarlySession) OpenUniStreamSync(ctx context.Context) (quic.SendStream, error) {
|
||||
return s.MockOpenUniStreamSync(ctx)
|
||||
}
|
||||
|
||||
// LocalAddr class MockLocalAddr.
|
||||
func (c *QUICEarlySession) LocalAddr() net.Addr {
|
||||
return c.MockLocalAddr()
|
||||
}
|
||||
|
||||
// RemoteAddr calls MockRemoteAddr.
|
||||
func (c *QUICEarlySession) RemoteAddr() net.Addr {
|
||||
return c.MockRemoteAddr()
|
||||
}
|
||||
|
||||
// CloseWithError calls MockCloseWithError.
|
||||
func (c *QUICEarlySession) CloseWithError(
|
||||
code quic.ApplicationErrorCode, reason string) error {
|
||||
return c.MockCloseWithError(code, reason)
|
||||
}
|
||||
|
||||
// Context calls MockContext.
|
||||
func (s *QUICEarlySession) Context() context.Context {
|
||||
return s.MockContext()
|
||||
}
|
||||
|
||||
// ConnectionState calls MockConnectionState.
|
||||
func (s *QUICEarlySession) ConnectionState() quic.ConnectionState {
|
||||
return s.MockConnectionState()
|
||||
}
|
||||
|
||||
// HandshakeComplete calls MockHandshakeComplete.
|
||||
func (s *QUICEarlySession) HandshakeComplete() context.Context {
|
||||
return s.MockHandshakeComplete()
|
||||
}
|
||||
|
||||
// NextSession calls MockNextSession.
|
||||
func (s *QUICEarlySession) NextSession() quic.Session {
|
||||
return s.MockNextSession()
|
||||
}
|
||||
|
||||
// SendMessage calls MockSendMessage.
|
||||
func (s *QUICEarlySession) SendMessage(b []byte) error {
|
||||
return s.MockSendMessage(b)
|
||||
}
|
||||
|
||||
// ReceiveMessage calls MockReceiveMessage.
|
||||
func (s *QUICEarlySession) ReceiveMessage() ([]byte, error) {
|
||||
return s.MockReceiveMessage()
|
||||
}
|
||||
|
||||
// QUICUDPConn is an UDP conn used by QUIC.
|
||||
type QUICUDPConn struct {
|
||||
MockWriteTo func(p []byte, addr net.Addr) (int, error)
|
||||
MockClose func() error
|
||||
MockLocalAddr func() net.Addr
|
||||
MockRemoteAddr func() net.Addr
|
||||
MockSetDeadline func(t time.Time) error
|
||||
MockSetReadDeadline func(t time.Time) error
|
||||
MockSetWriteDeadline func(t time.Time) error
|
||||
MockReadFrom func(p []byte) (n int, addr net.Addr, err error)
|
||||
MockSyscallConn func() (syscall.RawConn, error)
|
||||
MockSetReadBuffer func(n int) error
|
||||
}
|
||||
|
||||
var _ quicx.UDPLikeConn = &QUICUDPConn{}
|
||||
|
||||
// WriteTo calls MockWriteTo.
|
||||
func (c *QUICUDPConn) WriteTo(p []byte, addr net.Addr) (int, error) {
|
||||
return c.MockWriteTo(p, addr)
|
||||
}
|
||||
|
||||
// Close calls MockClose.
|
||||
func (c *QUICUDPConn) Close() error {
|
||||
return c.MockClose()
|
||||
}
|
||||
|
||||
// LocalAddr calls MockLocalAddr.
|
||||
func (c *QUICUDPConn) LocalAddr() net.Addr {
|
||||
return c.MockLocalAddr()
|
||||
}
|
||||
|
||||
// RemoteAddr calls MockRemoteAddr.
|
||||
func (c *QUICUDPConn) RemoteAddr() net.Addr {
|
||||
return c.MockRemoteAddr()
|
||||
}
|
||||
|
||||
// SetDeadline calls MockSetDeadline.
|
||||
func (c *QUICUDPConn) SetDeadline(t time.Time) error {
|
||||
return c.MockSetDeadline(t)
|
||||
}
|
||||
|
||||
// SetReadDeadline calls MockSetReadDeadline.
|
||||
func (c *QUICUDPConn) SetReadDeadline(t time.Time) error {
|
||||
return c.MockSetReadDeadline(t)
|
||||
}
|
||||
|
||||
// SetWriteDeadline calls MockSetWriteDeadline.
|
||||
func (c *QUICUDPConn) SetWriteDeadline(t time.Time) error {
|
||||
return c.MockSetWriteDeadline(t)
|
||||
}
|
||||
|
||||
// ReadFrom calls MockReadFrom.
|
||||
func (c *QUICUDPConn) ReadFrom(b []byte) (int, net.Addr, error) {
|
||||
return c.MockReadFrom(b)
|
||||
}
|
||||
|
||||
// SyscallConn calls MockSyscallConn.
|
||||
func (c *QUICUDPConn) SyscallConn() (syscall.RawConn, error) {
|
||||
return c.MockSyscallConn()
|
||||
}
|
||||
|
||||
// SetReadBuffer calls MockSetReadBuffer.
|
||||
func (c *QUICUDPConn) SetReadBuffer(n int) error {
|
||||
return c.MockSetReadBuffer(n)
|
||||
}
|
||||
@@ -0,0 +1,422 @@
|
||||
package mocks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"net"
|
||||
"reflect"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite/quicx"
|
||||
)
|
||||
|
||||
func TestQUICListenerListen(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
ql := &QUICListener{
|
||||
MockListen: func(addr *net.UDPAddr) (quicx.UDPLikeConn, error) {
|
||||
return nil, expected
|
||||
},
|
||||
}
|
||||
pconn, err := ql.Listen(&net.UDPAddr{})
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected", expected)
|
||||
}
|
||||
if pconn != nil {
|
||||
t.Fatal("expected nil conn here")
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICContextDialerDialContext(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
qcd := &QUICContextDialer{
|
||||
MockDialContext: func(ctx context.Context, network string, address string, tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlySession, error) {
|
||||
return nil, expected
|
||||
},
|
||||
}
|
||||
ctx := context.Background()
|
||||
tlsConfig := &tls.Config{}
|
||||
quicConfig := &quic.Config{}
|
||||
sess, err := qcd.DialContext(ctx, "udp", "dns.google:443", tlsConfig, quicConfig)
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected")
|
||||
}
|
||||
if sess != nil {
|
||||
t.Fatal("expected nil session")
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICEarlySessionAcceptStream(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
sess := &QUICEarlySession{
|
||||
MockAcceptStream: func(ctx context.Context) (quic.Stream, error) {
|
||||
return nil, expected
|
||||
},
|
||||
}
|
||||
ctx := context.Background()
|
||||
stream, err := sess.AcceptStream(ctx)
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
if stream != nil {
|
||||
t.Fatal("expected nil stream here")
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICEarlySessionAcceptUniStream(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
sess := &QUICEarlySession{
|
||||
MockAcceptUniStream: func(ctx context.Context) (quic.ReceiveStream, error) {
|
||||
return nil, expected
|
||||
},
|
||||
}
|
||||
ctx := context.Background()
|
||||
stream, err := sess.AcceptUniStream(ctx)
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
if stream != nil {
|
||||
t.Fatal("expected nil stream here")
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICEarlySessionOpenStream(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
sess := &QUICEarlySession{
|
||||
MockOpenStream: func() (quic.Stream, error) {
|
||||
return nil, expected
|
||||
},
|
||||
}
|
||||
stream, err := sess.OpenStream()
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
if stream != nil {
|
||||
t.Fatal("expected nil stream here")
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICEarlySessionOpenStreamSync(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
sess := &QUICEarlySession{
|
||||
MockOpenStreamSync: func(ctx context.Context) (quic.Stream, error) {
|
||||
return nil, expected
|
||||
},
|
||||
}
|
||||
ctx := context.Background()
|
||||
stream, err := sess.OpenStreamSync(ctx)
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
if stream != nil {
|
||||
t.Fatal("expected nil stream here")
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICEarlySessionOpenUniStream(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
sess := &QUICEarlySession{
|
||||
MockOpenUniStream: func() (quic.SendStream, error) {
|
||||
return nil, expected
|
||||
},
|
||||
}
|
||||
stream, err := sess.OpenUniStream()
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
if stream != nil {
|
||||
t.Fatal("expected nil stream here")
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICEarlySessionOpenUniStreamSync(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
sess := &QUICEarlySession{
|
||||
MockOpenUniStreamSync: func(ctx context.Context) (quic.SendStream, error) {
|
||||
return nil, expected
|
||||
},
|
||||
}
|
||||
ctx := context.Background()
|
||||
stream, err := sess.OpenUniStreamSync(ctx)
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
if stream != nil {
|
||||
t.Fatal("expected nil stream here")
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICEarlySessionLocalAddr(t *testing.T) {
|
||||
sess := &QUICEarlySession{
|
||||
MockLocalAddr: func() net.Addr {
|
||||
return &net.UDPAddr{}
|
||||
},
|
||||
}
|
||||
addr := sess.LocalAddr()
|
||||
if !reflect.ValueOf(addr).Elem().IsZero() {
|
||||
t.Fatal("expected a zero address here")
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICEarlySessionRemoteAddr(t *testing.T) {
|
||||
sess := &QUICEarlySession{
|
||||
MockRemoteAddr: func() net.Addr {
|
||||
return &net.UDPAddr{}
|
||||
},
|
||||
}
|
||||
addr := sess.RemoteAddr()
|
||||
if !reflect.ValueOf(addr).Elem().IsZero() {
|
||||
t.Fatal("expected a zero address here")
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICEarlySessionCloseWithError(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
sess := &QUICEarlySession{
|
||||
MockCloseWithError: func(
|
||||
code quic.ApplicationErrorCode, reason string) error {
|
||||
return expected
|
||||
},
|
||||
}
|
||||
err := sess.CloseWithError(0, "")
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICEarlySessionContext(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
sess := &QUICEarlySession{
|
||||
MockContext: func() context.Context {
|
||||
return ctx
|
||||
},
|
||||
}
|
||||
out := sess.Context()
|
||||
if !reflect.DeepEqual(ctx, out) {
|
||||
t.Fatal("not the context we expected")
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICEarlySessionConnectionState(t *testing.T) {
|
||||
state := quic.ConnectionState{SupportsDatagrams: true}
|
||||
sess := &QUICEarlySession{
|
||||
MockConnectionState: func() quic.ConnectionState {
|
||||
return state
|
||||
},
|
||||
}
|
||||
out := sess.ConnectionState()
|
||||
if !reflect.DeepEqual(state, out) {
|
||||
t.Fatal("not the context we expected")
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICEarlySessionHandshakeComplete(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
sess := &QUICEarlySession{
|
||||
MockHandshakeComplete: func() context.Context {
|
||||
return ctx
|
||||
},
|
||||
}
|
||||
out := sess.HandshakeComplete()
|
||||
if !reflect.DeepEqual(ctx, out) {
|
||||
t.Fatal("not the context we expected")
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICEarlySessionNextSession(t *testing.T) {
|
||||
next := &QUICEarlySession{}
|
||||
sess := &QUICEarlySession{
|
||||
MockNextSession: func() quic.Session {
|
||||
return next
|
||||
},
|
||||
}
|
||||
out := sess.NextSession()
|
||||
if !reflect.DeepEqual(next, out) {
|
||||
t.Fatal("not the context we expected")
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICEarlySessionSendMessage(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
sess := &QUICEarlySession{
|
||||
MockSendMessage: func(b []byte) error {
|
||||
return expected
|
||||
},
|
||||
}
|
||||
b := make([]byte, 17)
|
||||
err := sess.SendMessage(b)
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICEarlySessionReceiveMessage(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
sess := &QUICEarlySession{
|
||||
MockReceiveMessage: func() ([]byte, error) {
|
||||
return nil, expected
|
||||
},
|
||||
}
|
||||
b, err := sess.ReceiveMessage()
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
if b != nil {
|
||||
t.Fatal("expected nil buffer here")
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICUDPConnWriteTo(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
quc := &QUICUDPConn{
|
||||
MockWriteTo: func(p []byte, addr net.Addr) (int, error) {
|
||||
return 0, expected
|
||||
},
|
||||
}
|
||||
pkt := make([]byte, 128)
|
||||
addr := &net.UDPAddr{}
|
||||
cnt, err := quc.WriteTo(pkt, addr)
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
if cnt != 0 {
|
||||
t.Fatal("expected zero here")
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICUDPConnClose(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
quc := &QUICUDPConn{
|
||||
MockClose: func() error {
|
||||
return expected
|
||||
},
|
||||
}
|
||||
err := quc.Close()
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICUDPConnLocalAddrWorks(t *testing.T) {
|
||||
expected := &net.TCPAddr{
|
||||
IP: net.IPv6loopback,
|
||||
Port: 1234,
|
||||
}
|
||||
c := &QUICUDPConn{
|
||||
MockLocalAddr: func() net.Addr {
|
||||
return expected
|
||||
},
|
||||
}
|
||||
out := c.LocalAddr()
|
||||
if diff := cmp.Diff(expected, out); diff != "" {
|
||||
t.Fatal(diff)
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICUDPConnRemoteAddrWorks(t *testing.T) {
|
||||
expected := &net.TCPAddr{
|
||||
IP: net.IPv6loopback,
|
||||
Port: 1234,
|
||||
}
|
||||
c := &QUICUDPConn{
|
||||
MockRemoteAddr: func() net.Addr {
|
||||
return expected
|
||||
},
|
||||
}
|
||||
out := c.RemoteAddr()
|
||||
if diff := cmp.Diff(expected, out); diff != "" {
|
||||
t.Fatal(diff)
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICUDPConnSetDeadline(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
c := &QUICUDPConn{
|
||||
MockSetDeadline: func(t time.Time) error {
|
||||
return expected
|
||||
},
|
||||
}
|
||||
err := c.SetDeadline(time.Time{})
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICUDPConnSetReadDeadline(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
c := &QUICUDPConn{
|
||||
MockSetReadDeadline: func(t time.Time) error {
|
||||
return expected
|
||||
},
|
||||
}
|
||||
err := c.SetReadDeadline(time.Time{})
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICUDPConnSetWriteDeadline(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
c := &QUICUDPConn{
|
||||
MockSetWriteDeadline: func(t time.Time) error {
|
||||
return expected
|
||||
},
|
||||
}
|
||||
err := c.SetWriteDeadline(time.Time{})
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICUDPConnReadFrom(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
quc := &QUICUDPConn{
|
||||
MockReadFrom: func(b []byte) (int, net.Addr, error) {
|
||||
return 0, nil, expected
|
||||
},
|
||||
}
|
||||
b := make([]byte, 128)
|
||||
n, addr, err := quc.ReadFrom(b)
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
if n != 0 {
|
||||
t.Fatal("expected zero here")
|
||||
}
|
||||
if addr != nil {
|
||||
t.Fatal("expected nil here")
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICUDPConnSyscallConn(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
quc := &QUICUDPConn{
|
||||
MockSyscallConn: func() (syscall.RawConn, error) {
|
||||
return nil, expected
|
||||
},
|
||||
}
|
||||
conn, err := quc.SyscallConn()
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
if conn != nil {
|
||||
t.Fatal("expected nil here")
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICUDPConnSetReadBuffer(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
quc := &QUICUDPConn{
|
||||
MockSetReadBuffer: func(n int) error {
|
||||
return expected
|
||||
},
|
||||
}
|
||||
err := quc.SetReadBuffer(1 << 10)
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package mocks
|
||||
|
||||
import "io"
|
||||
|
||||
// Reader allows to mock any io.Reader.
|
||||
type Reader struct {
|
||||
MockRead func(b []byte) (int, error)
|
||||
}
|
||||
|
||||
// MockableReader implements an io.Reader.
|
||||
var _ io.Reader = &Reader{}
|
||||
|
||||
// Read implements io.Reader.Read.
|
||||
func (r *Reader) Read(b []byte) (int, error) {
|
||||
return r.MockRead(b)
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package mocks
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestReaderRead(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
r := &Reader{
|
||||
MockRead: func(b []byte) (int, error) {
|
||||
return 0, expected
|
||||
},
|
||||
}
|
||||
b := make([]byte, 128)
|
||||
count, err := r.Read(b)
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("unexpected error", err)
|
||||
}
|
||||
if count != 0 {
|
||||
t.Fatal("unexpected count", count)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package mocks
|
||||
|
||||
import "context"
|
||||
|
||||
// Resolver is a mockable Resolver.
|
||||
type Resolver struct {
|
||||
MockLookupHost func(ctx context.Context, domain string) ([]string, error)
|
||||
MockNetwork func() string
|
||||
MockAddress func() string
|
||||
}
|
||||
|
||||
// LookupHost calls MockLookupHost.
|
||||
func (r *Resolver) LookupHost(ctx context.Context, domain string) ([]string, error) {
|
||||
return r.MockLookupHost(ctx, domain)
|
||||
}
|
||||
|
||||
// Address calls MockAddress.
|
||||
func (r *Resolver) Address() string {
|
||||
return r.MockAddress()
|
||||
}
|
||||
|
||||
// Network calls MockNetwork.
|
||||
func (r *Resolver) Network() string {
|
||||
return r.MockNetwork()
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package mocks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestResolverLookupHost(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
r := &Resolver{
|
||||
MockLookupHost: func(ctx context.Context, domain string) ([]string, error) {
|
||||
return nil, expected
|
||||
},
|
||||
}
|
||||
ctx := context.Background()
|
||||
addrs, err := r.LookupHost(ctx, "dns.google")
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("unexpected error", err)
|
||||
}
|
||||
if addrs != nil {
|
||||
t.Fatal("expected nil addr")
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolverNetwork(t *testing.T) {
|
||||
r := &Resolver{
|
||||
MockNetwork: func() string {
|
||||
return "antani"
|
||||
},
|
||||
}
|
||||
if v := r.Network(); v != "antani" {
|
||||
t.Fatal("unexpected network", v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolverAddress(t *testing.T) {
|
||||
r := &Resolver{
|
||||
MockAddress: func() string {
|
||||
return "1.1.1.1"
|
||||
},
|
||||
}
|
||||
if v := r.Address(); v != "1.1.1.1" {
|
||||
t.Fatal("unexpected address", v)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package mocks
|
||||
|
||||
import "crypto/tls"
|
||||
|
||||
// TLSConn allows to mock netxlite.TLSConn.
|
||||
type TLSConn struct {
|
||||
// Conn is the embedded mockable Conn.
|
||||
Conn
|
||||
|
||||
// MockConnectionState allows to mock the ConnectionState method.
|
||||
MockConnectionState func() tls.ConnectionState
|
||||
|
||||
// MockHandshake allows to mock the Handshake method.
|
||||
MockHandshake func() error
|
||||
}
|
||||
|
||||
// ConnectionState calls MockConnectionState.
|
||||
func (c *TLSConn) ConnectionState() tls.ConnectionState {
|
||||
return c.MockConnectionState()
|
||||
}
|
||||
|
||||
// Handshake calls MockHandshake.
|
||||
func (c *TLSConn) Handshake() error {
|
||||
return c.MockHandshake()
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package mocks
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTLSConnConnectionState(t *testing.T) {
|
||||
state := tls.ConnectionState{Version: tls.VersionTLS12}
|
||||
c := &TLSConn{
|
||||
MockConnectionState: func() tls.ConnectionState {
|
||||
return state
|
||||
},
|
||||
}
|
||||
out := c.ConnectionState()
|
||||
if !reflect.DeepEqual(out, state) {
|
||||
t.Fatal("not the result we expected")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTLSConnHandshake(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
c := &TLSConn{
|
||||
MockHandshake: func() error {
|
||||
return expected
|
||||
},
|
||||
}
|
||||
err := c.Handshake()
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package mocks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net"
|
||||
)
|
||||
|
||||
// TLSHandshaker is a mockable TLS handshaker.
|
||||
type TLSHandshaker struct {
|
||||
MockHandshake func(ctx context.Context, conn net.Conn, config *tls.Config) (
|
||||
net.Conn, tls.ConnectionState, error)
|
||||
}
|
||||
|
||||
// Handshake calls MockHandshake.
|
||||
func (th *TLSHandshaker) Handshake(ctx context.Context, conn net.Conn, config *tls.Config) (
|
||||
net.Conn, tls.ConnectionState, error) {
|
||||
return th.MockHandshake(ctx, conn, config)
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package mocks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTLSHandshakerHandshake(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
conn := &Conn{}
|
||||
ctx := context.Background()
|
||||
config := &tls.Config{}
|
||||
th := &TLSHandshaker{
|
||||
MockHandshake: func(ctx context.Context, conn net.Conn,
|
||||
config *tls.Config) (net.Conn, tls.ConnectionState, error) {
|
||||
return nil, tls.ConnectionState{}, expected
|
||||
},
|
||||
}
|
||||
tlsConn, connState, err := th.Handshake(ctx, conn, config)
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
if !reflect.ValueOf(connState).IsZero() {
|
||||
t.Fatal("expected zero ConnectionState here")
|
||||
}
|
||||
if tlsConn != nil {
|
||||
t.Fatal("expected nil conn here")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user