refactor: move ErrorWrapperQUICDialer to errorsx (#420)
I needed to add some tests as integration tests due to circular imports, but this is ~fine because we quite likely want many integration tests in the errorsx package anyway. Part of https://github.com/ooni/probe/issues/1505.
This commit is contained in:
parent
5c52d99d57
commit
ec350cba1a
|
@ -171,7 +171,7 @@ func NewQUICDialer(config Config) QUICDialer {
|
||||||
var d quicdialer.ContextDialer = &netxlite.QUICDialerQUICGo{
|
var d quicdialer.ContextDialer = &netxlite.QUICDialerQUICGo{
|
||||||
QUICListener: ql,
|
QUICListener: ql,
|
||||||
}
|
}
|
||||||
d = quicdialer.ErrorWrapperDialer{Dialer: d}
|
d = &errorsx.ErrorWrapperQUICDialer{Dialer: d}
|
||||||
if config.TLSSaver != nil {
|
if config.TLSSaver != nil {
|
||||||
d = quicdialer.HandshakeSaver{Saver: config.TLSSaver, Dialer: d}
|
d = quicdialer.HandshakeSaver{Saver: config.TLSSaver, Dialer: d}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
package quicdialer
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
|
||||||
|
|
||||||
"github.com/lucas-clemente/quic-go"
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/errorsx"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ErrorWrapperDialer is a dialer that performs quic err wrapping
|
|
||||||
type ErrorWrapperDialer struct {
|
|
||||||
Dialer ContextDialer
|
|
||||||
}
|
|
||||||
|
|
||||||
// DialContext implements ContextDialer.DialContext
|
|
||||||
func (d ErrorWrapperDialer) DialContext(
|
|
||||||
ctx context.Context, network string, host string,
|
|
||||||
tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlySession, error) {
|
|
||||||
sess, err := d.Dialer.DialContext(ctx, network, host, tlsCfg, cfg)
|
|
||||||
err = errorsx.SafeErrWrapperBuilder{
|
|
||||||
Classifier: errorsx.ClassifyQUICFailure,
|
|
||||||
Error: err,
|
|
||||||
Operation: errorsx.QUICHandshakeOperation,
|
|
||||||
}.MaybeBuild()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return sess, nil
|
|
||||||
}
|
|
|
@ -1,85 +0,0 @@
|
||||||
package quicdialer_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/lucas-clemente/quic-go"
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/quicdialer"
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/errorsx"
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestErrorWrapperFailure(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
d := quicdialer.ErrorWrapperDialer{
|
|
||||||
Dialer: MockDialer{Sess: nil, Err: io.EOF}}
|
|
||||||
sess, err := d.DialContext(
|
|
||||||
ctx, "udp", "www.google.com:443", &tls.Config{}, &quic.Config{})
|
|
||||||
if sess != nil {
|
|
||||||
t.Fatal("expected a nil sess here")
|
|
||||||
}
|
|
||||||
errorWrapperCheckErr(t, err, errorsx.QUICHandshakeOperation)
|
|
||||||
}
|
|
||||||
|
|
||||||
func errorWrapperCheckErr(t *testing.T, err error, op string) {
|
|
||||||
if !errors.Is(err, io.EOF) {
|
|
||||||
t.Fatal("expected another error here")
|
|
||||||
}
|
|
||||||
var errWrapper *errorsx.ErrWrapper
|
|
||||||
if !errors.As(err, &errWrapper) {
|
|
||||||
t.Fatal("cannot cast to ErrWrapper")
|
|
||||||
}
|
|
||||||
if errWrapper.Operation != op {
|
|
||||||
t.Fatal("unexpected Operation")
|
|
||||||
}
|
|
||||||
if errWrapper.Failure != errorsx.FailureEOFError {
|
|
||||||
t.Fatal("unexpected failure")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestErrorWrapperInvalidCertificate(t *testing.T) {
|
|
||||||
nextprotos := []string{"h3"}
|
|
||||||
servername := "example.com"
|
|
||||||
tlsConf := &tls.Config{
|
|
||||||
NextProtos: nextprotos,
|
|
||||||
ServerName: servername,
|
|
||||||
}
|
|
||||||
|
|
||||||
dlr := quicdialer.ErrorWrapperDialer{Dialer: &netxlite.QUICDialerQUICGo{
|
|
||||||
QUICListener: &netxlite.QUICListenerStdlib{},
|
|
||||||
}}
|
|
||||||
// use Google IP
|
|
||||||
sess, err := dlr.DialContext(context.Background(), "udp",
|
|
||||||
"216.58.212.164:443", tlsConf, &quic.Config{})
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("expected an error here")
|
|
||||||
}
|
|
||||||
if sess != nil {
|
|
||||||
t.Fatal("expected nil sess here")
|
|
||||||
}
|
|
||||||
if err.Error() != errorsx.FailureSSLInvalidCertificate {
|
|
||||||
t.Fatal("unexpected failure")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestErrorWrapperSuccess(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
tlsConf := &tls.Config{
|
|
||||||
NextProtos: []string{"h3"},
|
|
||||||
ServerName: "www.google.com",
|
|
||||||
}
|
|
||||||
d := quicdialer.ErrorWrapperDialer{Dialer: &netxlite.QUICDialerQUICGo{
|
|
||||||
QUICListener: &netxlite.QUICListenerStdlib{},
|
|
||||||
}}
|
|
||||||
sess, err := d.DialContext(ctx, "udp", "216.58.212.164:443", tlsConf, &quic.Config{})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if sess == nil {
|
|
||||||
t.Fatal("expected non-nil sess here")
|
|
||||||
}
|
|
||||||
}
|
|
54
internal/errorsx/integration_test.go
Normal file
54
internal/errorsx/integration_test.go
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
package errorsx_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/lucas-clemente/quic-go"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/errorsx"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestErrorWrapperQUICDialerInvalidCertificate(t *testing.T) {
|
||||||
|
nextprotos := []string{"h3"}
|
||||||
|
servername := "example.com"
|
||||||
|
tlsConf := &tls.Config{
|
||||||
|
NextProtos: nextprotos,
|
||||||
|
ServerName: servername,
|
||||||
|
}
|
||||||
|
|
||||||
|
dlr := &errorsx.ErrorWrapperQUICDialer{Dialer: &netxlite.QUICDialerQUICGo{
|
||||||
|
QUICListener: &netxlite.QUICListenerStdlib{},
|
||||||
|
}}
|
||||||
|
// use Google IP
|
||||||
|
sess, err := dlr.DialContext(context.Background(), "udp",
|
||||||
|
"216.58.212.164:443", tlsConf, &quic.Config{})
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected an error here")
|
||||||
|
}
|
||||||
|
if sess != nil {
|
||||||
|
t.Fatal("expected nil sess here")
|
||||||
|
}
|
||||||
|
if err.Error() != errorsx.FailureSSLInvalidCertificate {
|
||||||
|
t.Fatal("unexpected failure")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestErrorWrapperQUICDialerSuccess(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
tlsConf := &tls.Config{
|
||||||
|
NextProtos: []string{"h3"},
|
||||||
|
ServerName: "www.google.com",
|
||||||
|
}
|
||||||
|
d := &errorsx.ErrorWrapperQUICDialer{Dialer: &netxlite.QUICDialerQUICGo{
|
||||||
|
QUICListener: &netxlite.QUICListenerStdlib{},
|
||||||
|
}}
|
||||||
|
sess, err := d.DialContext(ctx, "udp", "216.58.212.164:443", tlsConf, &quic.Config{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if sess == nil {
|
||||||
|
t.Fatal("expected non-nil sess here")
|
||||||
|
}
|
||||||
|
}
|
38
internal/errorsx/quic.go
Normal file
38
internal/errorsx/quic.go
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
package errorsx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
|
|
||||||
|
"github.com/lucas-clemente/quic-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
// QUICContextDialer is a dialer for QUIC using Context.
|
||||||
|
type QUICContextDialer interface {
|
||||||
|
// DialContext establishes a new QUIC session using the given
|
||||||
|
// network and address. The tlsConfig and the quicConfig arguments
|
||||||
|
// MUST NOT be nil. Returns either the session or an error.
|
||||||
|
DialContext(ctx context.Context, network, address string,
|
||||||
|
tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlySession, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorWrapperQUICDialer is a dialer that performs quic err wrapping
|
||||||
|
type ErrorWrapperQUICDialer struct {
|
||||||
|
Dialer QUICContextDialer
|
||||||
|
}
|
||||||
|
|
||||||
|
// DialContext implements ContextDialer.DialContext
|
||||||
|
func (d *ErrorWrapperQUICDialer) DialContext(
|
||||||
|
ctx context.Context, network string, host string,
|
||||||
|
tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlySession, error) {
|
||||||
|
sess, err := d.Dialer.DialContext(ctx, network, host, tlsCfg, cfg)
|
||||||
|
err = SafeErrWrapperBuilder{
|
||||||
|
Classifier: ClassifyQUICFailure,
|
||||||
|
Error: err,
|
||||||
|
Operation: QUICHandshakeOperation,
|
||||||
|
}.MaybeBuild()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return sess, nil
|
||||||
|
}
|
39
internal/errorsx/quic_test.go
Normal file
39
internal/errorsx/quic_test.go
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
package errorsx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/lucas-clemente/quic-go"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/netxmocks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestErrorWrapperQUICDialerFailure(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
d := &ErrorWrapperQUICDialer{Dialer: &netxmocks.QUICContextDialer{
|
||||||
|
MockDialContext: func(ctx context.Context, network, address string, tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlySession, error) {
|
||||||
|
return nil, io.EOF
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
sess, err := d.DialContext(
|
||||||
|
ctx, "udp", "www.google.com:443", &tls.Config{}, &quic.Config{})
|
||||||
|
if sess != nil {
|
||||||
|
t.Fatal("expected a nil sess here")
|
||||||
|
}
|
||||||
|
if !errors.Is(err, io.EOF) {
|
||||||
|
t.Fatal("expected another error here")
|
||||||
|
}
|
||||||
|
var errWrapper *ErrWrapper
|
||||||
|
if !errors.As(err, &errWrapper) {
|
||||||
|
t.Fatal("cannot cast to ErrWrapper")
|
||||||
|
}
|
||||||
|
if errWrapper.Operation != QUICHandshakeOperation {
|
||||||
|
t.Fatal("unexpected Operation")
|
||||||
|
}
|
||||||
|
if errWrapper.Failure != FailureEOFError {
|
||||||
|
t.Fatal("unexpected failure")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user