fix(oohelperd): reduce errors to what the old TH would emit (#543)

Reducing the errors is not done in a perfect way.

We have documented the most striking differences inside
https://github.com/ooni/probe/issues/1707#issuecomment-942283746 and
some attempts to improve the situation further inside
https://github.com/ooni/probe/issues/1707#issuecomment-942341255.

A better strategy for the future would be to introduce more
specific timeout errors, such as dns_timeout_error, etc.

More testing may be needed to further validate and compare the
old and the new TH, but this requires Jafar improvements to
more precisely simulate more complex censorship.
This commit is contained in:
Simone Basso 2021-10-13 16:37:02 +02:00 committed by GitHub
commit 4b8cae692b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 315 additions and 8 deletions

View file

@ -4,9 +4,11 @@ import (
"context"
"errors"
"net/http"
"strings"
"sync"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/ooni/probe-cli/v3/internal/netxlite"
)
func TestHTTPDoWithInvalidURL(t *testing.T) {
@ -25,7 +27,7 @@ func TestHTTPDoWithInvalidURL(t *testing.T) {
// wait for measurement steps to complete
wg.Wait()
resp := <-httpch
if resp.Failure == nil || !strings.HasSuffix(*resp.Failure, `invalid port "aaaa" after host`) {
if resp.Failure == nil || *resp.Failure != "unknown_error" {
t.Fatal("not the failure we expected")
}
}
@ -51,7 +53,79 @@ func TestHTTPDoWithHTTPTransportFailure(t *testing.T) {
// wait for measurement steps to complete
wg.Wait()
resp := <-httpch
if resp.Failure == nil || !strings.HasSuffix(*resp.Failure, "mocked error") {
if resp.Failure == nil || *resp.Failure != "unknown_error" {
t.Fatal("not the error we expected")
}
}
func newErrWrapper(failure, operation string) error {
return &netxlite.ErrWrapper{
Failure: failure,
Operation: operation,
WrappedErr: nil, // should not matter
}
}
func newErrWrapperTopLevel(failure string) error {
return newErrWrapper(failure, netxlite.TopLevelOperation)
}
func Test_httpMapFailure(t *testing.T) {
tests := []struct {
name string
failure error
want *string
}{{
name: "nil",
failure: nil,
want: nil,
}, {
name: "nxdomain",
failure: newErrWrapperTopLevel(netxlite.FailureDNSNXDOMAINError),
want: stringPointerForString("dns_lookup_error"),
}, {
name: "no answer",
failure: newErrWrapperTopLevel(netxlite.FailureDNSNoAnswer),
want: stringPointerForString("dns_lookup_error"),
}, {
name: "non recoverable failure",
failure: newErrWrapperTopLevel(netxlite.FailureDNSNonRecoverableFailure),
want: stringPointerForString("dns_lookup_error"),
}, {
name: "refused",
failure: newErrWrapperTopLevel(netxlite.FailureDNSRefusedError),
want: stringPointerForString("dns_lookup_error"),
}, {
name: "server misbehaving",
failure: newErrWrapperTopLevel(netxlite.FailureDNSServerMisbehaving),
want: stringPointerForString("dns_lookup_error"),
}, {
name: "temporary failure",
failure: newErrWrapperTopLevel(netxlite.FailureDNSTemporaryFailure),
want: stringPointerForString("dns_lookup_error"),
}, {
name: "timeout outside of dns lookup",
failure: newErrWrapperTopLevel(netxlite.FailureGenericTimeoutError),
want: stringPointerForString(netxlite.FailureGenericTimeoutError),
}, {
name: "timeout inside of dns lookup",
failure: newErrWrapper(netxlite.FailureGenericTimeoutError, netxlite.ResolveOperation),
want: stringPointerForString("dns_lookup_error"),
}, {
name: "connection refused",
failure: newErrWrapperTopLevel(netxlite.FailureConnectionRefused),
want: stringPointerForString("connection_refused_error"),
}, {
name: "anything else",
failure: newErrWrapperTopLevel(netxlite.FailureEOFError),
want: stringPointerForString("unknown_error"),
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := httpMapFailure(tt.failure)
if diff := cmp.Diff(tt.want, got); diff != "" {
t.Fatal(diff)
}
})
}
}