feat(errorsx): cover more syscall errors and add tests (#430)
* feat(errorsx): cover more syscall errors and add tests Part of https://github.com/ooni/probe/issues/1505 * fix tests
This commit is contained in:
parent
3747598b4a
commit
14c1640f7f
|
@ -1,5 +1,5 @@
|
|||
// Code generated by go generate; DO NOT EDIT.
|
||||
// Generated: 2021-07-02 15:15:17.997258 +0200 CEST m=+0.110031584
|
||||
// Generated: 2021-07-02 17:54:06.182341 +0200 CEST m=+0.120124584
|
||||
|
||||
package errorsx
|
||||
|
||||
|
@ -10,6 +10,42 @@ import (
|
|||
"syscall"
|
||||
)
|
||||
|
||||
// This enumeration lists the syscall-derived failures defined at
|
||||
// https://github.com/ooni/spec/blob/master/data-formats/df-007-errors.md
|
||||
//
|
||||
// See also the enumeration at failures.go for the failures that
|
||||
// DO NOT derive from system call errors.
|
||||
const (
|
||||
FailureOperationCanceled = "operation_canceled"
|
||||
FailureConnectionRefused = "connection_refused"
|
||||
FailureConnectionReset = "connection_reset"
|
||||
FailureHostUnreachable = "host_unreachable"
|
||||
FailureTimedOut = "timed_out"
|
||||
FailureAddressFamilyNotSupported = "address_family_not_supported"
|
||||
FailureAddressInUse = "address_in_use"
|
||||
FailureAddressNotAvailable = "address_not_available"
|
||||
FailureAlreadyConnected = "already_connected"
|
||||
FailureBadAddress = "bad_address"
|
||||
FailureBadFileDescriptor = "bad_file_descriptor"
|
||||
FailureConnectionAborted = "connection_aborted"
|
||||
FailureConnectionAlreadyInProgress = "connection_already_in_progress"
|
||||
FailureDestinationAddressRequired = "destination_address_required"
|
||||
FailureInterrupted = "interrupted"
|
||||
FailureInvalidArgument = "invalid_argument"
|
||||
FailureMessageSize = "message_size"
|
||||
FailureNetworkDown = "network_down"
|
||||
FailureNetworkReset = "network_reset"
|
||||
FailureNetworkUnreachable = "network_unreachable"
|
||||
FailureNoBufferSpace = "no_buffer_space"
|
||||
FailureNoProtocolOption = "no_protocol_option"
|
||||
FailureNotASocket = "not_a_socket"
|
||||
FailureNotConnected = "not_connected"
|
||||
FailureOperationWouldBlock = "operation_would_block"
|
||||
FailurePermissionDenied = "permission_denied"
|
||||
FailureProtocolNotSupported = "protocol_not_supported"
|
||||
FailureWrongProtocolType = "wrong_protocol_type"
|
||||
)
|
||||
|
||||
// toSyscallErr converts a syscall error to the
|
||||
// proper OONI error. Returns the OONI error string
|
||||
// on success, an empty string otherwise.
|
||||
|
@ -23,7 +59,7 @@ func toSyscallErr(err error) string {
|
|||
}
|
||||
switch errno {
|
||||
case ECANCELED:
|
||||
return FailureInterrupted
|
||||
return FailureOperationCanceled
|
||||
case ECONNREFUSED:
|
||||
return FailureConnectionRefused
|
||||
case ECONNRESET:
|
||||
|
@ -31,7 +67,53 @@ func toSyscallErr(err error) string {
|
|||
case EHOSTUNREACH:
|
||||
return FailureHostUnreachable
|
||||
case ETIMEDOUT:
|
||||
return FailureGenericTimeoutError
|
||||
return FailureTimedOut
|
||||
case EAFNOSUPPORT:
|
||||
return FailureAddressFamilyNotSupported
|
||||
case EADDRINUSE:
|
||||
return FailureAddressInUse
|
||||
case EADDRNOTAVAIL:
|
||||
return FailureAddressNotAvailable
|
||||
case EISCONN:
|
||||
return FailureAlreadyConnected
|
||||
case EFAULT:
|
||||
return FailureBadAddress
|
||||
case EBADF:
|
||||
return FailureBadFileDescriptor
|
||||
case ECONNABORTED:
|
||||
return FailureConnectionAborted
|
||||
case EALREADY:
|
||||
return FailureConnectionAlreadyInProgress
|
||||
case EDESTADDRREQ:
|
||||
return FailureDestinationAddressRequired
|
||||
case EINTR:
|
||||
return FailureInterrupted
|
||||
case EINVAL:
|
||||
return FailureInvalidArgument
|
||||
case EMSGSIZE:
|
||||
return FailureMessageSize
|
||||
case ENETDOWN:
|
||||
return FailureNetworkDown
|
||||
case ENETRESET:
|
||||
return FailureNetworkReset
|
||||
case ENETUNREACH:
|
||||
return FailureNetworkUnreachable
|
||||
case ENOBUFS:
|
||||
return FailureNoBufferSpace
|
||||
case ENOPROTOOPT:
|
||||
return FailureNoProtocolOption
|
||||
case ENOTSOCK:
|
||||
return FailureNotASocket
|
||||
case ENOTCONN:
|
||||
return FailureNotConnected
|
||||
case EWOULDBLOCK:
|
||||
return FailureOperationWouldBlock
|
||||
case EACCES:
|
||||
return FailurePermissionDenied
|
||||
case EPROTONOSUPPORT:
|
||||
return FailureProtocolNotSupported
|
||||
case EPROTOTYPE:
|
||||
return FailureWrongProtocolType
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
|
103
internal/errorsx/errno_test.go
Normal file
103
internal/errorsx/errno_test.go
Normal file
|
@ -0,0 +1,103 @@
|
|||
// Code generated by go generate; DO NOT EDIT.
|
||||
// Generated: 2021-07-02 17:54:06.226224 +0200 CEST m=+0.164008293
|
||||
|
||||
package errorsx
|
||||
|
||||
import (
|
||||
"io"
|
||||
"syscall"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestToSyscallErr(t *testing.T) {
|
||||
if v := toSyscallErr(io.EOF); v != "" {
|
||||
t.Fatalf("expected empty string, got '%s'", v)
|
||||
}
|
||||
if v := toSyscallErr(ECANCELED); v != FailureOperationCanceled {
|
||||
t.Fatalf("expected '%s', got '%s'", FailureOperationCanceled, v)
|
||||
}
|
||||
if v := toSyscallErr(ECONNREFUSED); v != FailureConnectionRefused {
|
||||
t.Fatalf("expected '%s', got '%s'", FailureConnectionRefused, v)
|
||||
}
|
||||
if v := toSyscallErr(ECONNRESET); v != FailureConnectionReset {
|
||||
t.Fatalf("expected '%s', got '%s'", FailureConnectionReset, v)
|
||||
}
|
||||
if v := toSyscallErr(EHOSTUNREACH); v != FailureHostUnreachable {
|
||||
t.Fatalf("expected '%s', got '%s'", FailureHostUnreachable, v)
|
||||
}
|
||||
if v := toSyscallErr(ETIMEDOUT); v != FailureTimedOut {
|
||||
t.Fatalf("expected '%s', got '%s'", FailureTimedOut, v)
|
||||
}
|
||||
if v := toSyscallErr(EAFNOSUPPORT); v != FailureAddressFamilyNotSupported {
|
||||
t.Fatalf("expected '%s', got '%s'", FailureAddressFamilyNotSupported, v)
|
||||
}
|
||||
if v := toSyscallErr(EADDRINUSE); v != FailureAddressInUse {
|
||||
t.Fatalf("expected '%s', got '%s'", FailureAddressInUse, v)
|
||||
}
|
||||
if v := toSyscallErr(EADDRNOTAVAIL); v != FailureAddressNotAvailable {
|
||||
t.Fatalf("expected '%s', got '%s'", FailureAddressNotAvailable, v)
|
||||
}
|
||||
if v := toSyscallErr(EISCONN); v != FailureAlreadyConnected {
|
||||
t.Fatalf("expected '%s', got '%s'", FailureAlreadyConnected, v)
|
||||
}
|
||||
if v := toSyscallErr(EFAULT); v != FailureBadAddress {
|
||||
t.Fatalf("expected '%s', got '%s'", FailureBadAddress, v)
|
||||
}
|
||||
if v := toSyscallErr(EBADF); v != FailureBadFileDescriptor {
|
||||
t.Fatalf("expected '%s', got '%s'", FailureBadFileDescriptor, v)
|
||||
}
|
||||
if v := toSyscallErr(ECONNABORTED); v != FailureConnectionAborted {
|
||||
t.Fatalf("expected '%s', got '%s'", FailureConnectionAborted, v)
|
||||
}
|
||||
if v := toSyscallErr(EALREADY); v != FailureConnectionAlreadyInProgress {
|
||||
t.Fatalf("expected '%s', got '%s'", FailureConnectionAlreadyInProgress, v)
|
||||
}
|
||||
if v := toSyscallErr(EDESTADDRREQ); v != FailureDestinationAddressRequired {
|
||||
t.Fatalf("expected '%s', got '%s'", FailureDestinationAddressRequired, v)
|
||||
}
|
||||
if v := toSyscallErr(EINTR); v != FailureInterrupted {
|
||||
t.Fatalf("expected '%s', got '%s'", FailureInterrupted, v)
|
||||
}
|
||||
if v := toSyscallErr(EINVAL); v != FailureInvalidArgument {
|
||||
t.Fatalf("expected '%s', got '%s'", FailureInvalidArgument, v)
|
||||
}
|
||||
if v := toSyscallErr(EMSGSIZE); v != FailureMessageSize {
|
||||
t.Fatalf("expected '%s', got '%s'", FailureMessageSize, v)
|
||||
}
|
||||
if v := toSyscallErr(ENETDOWN); v != FailureNetworkDown {
|
||||
t.Fatalf("expected '%s', got '%s'", FailureNetworkDown, v)
|
||||
}
|
||||
if v := toSyscallErr(ENETRESET); v != FailureNetworkReset {
|
||||
t.Fatalf("expected '%s', got '%s'", FailureNetworkReset, v)
|
||||
}
|
||||
if v := toSyscallErr(ENETUNREACH); v != FailureNetworkUnreachable {
|
||||
t.Fatalf("expected '%s', got '%s'", FailureNetworkUnreachable, v)
|
||||
}
|
||||
if v := toSyscallErr(ENOBUFS); v != FailureNoBufferSpace {
|
||||
t.Fatalf("expected '%s', got '%s'", FailureNoBufferSpace, v)
|
||||
}
|
||||
if v := toSyscallErr(ENOPROTOOPT); v != FailureNoProtocolOption {
|
||||
t.Fatalf("expected '%s', got '%s'", FailureNoProtocolOption, v)
|
||||
}
|
||||
if v := toSyscallErr(ENOTSOCK); v != FailureNotASocket {
|
||||
t.Fatalf("expected '%s', got '%s'", FailureNotASocket, v)
|
||||
}
|
||||
if v := toSyscallErr(ENOTCONN); v != FailureNotConnected {
|
||||
t.Fatalf("expected '%s', got '%s'", FailureNotConnected, v)
|
||||
}
|
||||
if v := toSyscallErr(EWOULDBLOCK); v != FailureOperationWouldBlock {
|
||||
t.Fatalf("expected '%s', got '%s'", FailureOperationWouldBlock, v)
|
||||
}
|
||||
if v := toSyscallErr(EACCES); v != FailurePermissionDenied {
|
||||
t.Fatalf("expected '%s', got '%s'", FailurePermissionDenied, v)
|
||||
}
|
||||
if v := toSyscallErr(EPROTONOSUPPORT); v != FailureProtocolNotSupported {
|
||||
t.Fatalf("expected '%s', got '%s'", FailureProtocolNotSupported, v)
|
||||
}
|
||||
if v := toSyscallErr(EPROTOTYPE); v != FailureWrongProtocolType {
|
||||
t.Fatalf("expected '%s', got '%s'", FailureWrongProtocolType, v)
|
||||
}
|
||||
if v := toSyscallErr(syscall.Errno(0)); v != "" {
|
||||
t.Fatalf("expected empty string, got '%s'", v)
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
// Code generated by go generate; DO NOT EDIT.
|
||||
// Generated: 2021-07-02 15:15:17.887594 +0200 CEST m=+0.000365001
|
||||
// Generated: 2021-07-02 17:54:06.062944 +0200 CEST m=+0.000724793
|
||||
|
||||
package errorsx
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Code generated by go generate; DO NOT EDIT.
|
||||
// Generated: 2021-07-02 15:15:17.971155 +0200 CEST m=+0.083928418
|
||||
// Generated: 2021-07-02 17:54:06.155868 +0200 CEST m=+0.093650376
|
||||
|
||||
package errorsx
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ func TestToFailureString(t *testing.T) {
|
|||
}
|
||||
})
|
||||
t.Run("for canceled", func(t *testing.T) {
|
||||
if toFailureString(syscall.ECANCELED) != FailureInterrupted {
|
||||
if toFailureString(syscall.ECANCELED) != FailureOperationCanceled {
|
||||
t.Fatal("unexpected results")
|
||||
}
|
||||
})
|
||||
|
@ -74,7 +74,7 @@ func TestToFailureString(t *testing.T) {
|
|||
}
|
||||
})
|
||||
t.Run("for system timeout", func(t *testing.T) {
|
||||
if toFailureString(syscall.ETIMEDOUT) != FailureGenericTimeoutError {
|
||||
if toFailureString(syscall.ETIMEDOUT) != FailureTimedOut {
|
||||
t.Fatal("unexpected results")
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
package errorsx
|
||||
|
||||
// This enumeration lists all the failures defined at
|
||||
// This enumeration lists the non-syscall-derived failures defined at
|
||||
// https://github.com/ooni/spec/blob/master/data-formats/df-007-errors.md
|
||||
//
|
||||
// See also the enumeration at errno.go for the failures that
|
||||
// derive directly from system call errors.
|
||||
const (
|
||||
// FailureConnectionRefused means ECONNREFUSED.
|
||||
FailureConnectionRefused = "connection_refused"
|
||||
|
||||
// FailureConnectionReset means ECONNRESET.
|
||||
FailureConnectionReset = "connection_reset"
|
||||
|
||||
// FailureDNSBogonError means we detected bogon in DNS reply.
|
||||
FailureDNSBogonError = "dns_bogon_error"
|
||||
|
||||
|
@ -21,12 +18,6 @@ const (
|
|||
// FailureGenericTimeoutError means we got some timer has expired.
|
||||
FailureGenericTimeoutError = "generic_timeout_error"
|
||||
|
||||
// FailureHostUnreachable means that there is "no route to host".
|
||||
FailureHostUnreachable = "host_unreachable"
|
||||
|
||||
// FailureInterrupted means that the user interrupted us.
|
||||
FailureInterrupted = "interrupted"
|
||||
|
||||
// FailureNoCompatibleQUICVersion means that the server does not support the proposed QUIC version
|
||||
FailureNoCompatibleQUICVersion = "quic_incompatible_version"
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/iancoleman/strcase"
|
||||
"golang.org/x/sys/execabs"
|
||||
)
|
||||
|
||||
|
@ -18,13 +19,10 @@ type ErrorSpec struct {
|
|||
Failure string
|
||||
}
|
||||
|
||||
// TODO(kelmenhorst): find out if we need more system errors here. Currently
|
||||
// the code does not generate any mapping if Failure is empty.
|
||||
|
||||
// Specs contains all the error specs.
|
||||
var Specs = []ErrorSpec{{
|
||||
Errno: "ECANCELED",
|
||||
Failure: "Interrupted",
|
||||
Failure: "OperationCanceled",
|
||||
}, {
|
||||
Errno: "ECONNREFUSED",
|
||||
Failure: "ConnectionRefused",
|
||||
|
@ -36,53 +34,76 @@ var Specs = []ErrorSpec{{
|
|||
Failure: "HostUnreachable",
|
||||
}, {
|
||||
Errno: "ETIMEDOUT",
|
||||
Failure: "GenericTimeoutError",
|
||||
Failure: "TimedOut",
|
||||
}, {
|
||||
Errno: "EAFNOSUPPORT",
|
||||
Errno: "EAFNOSUPPORT",
|
||||
Failure: "AddressFamilyNotSupported",
|
||||
}, {
|
||||
Errno: "EADDRINUSE",
|
||||
Errno: "EADDRINUSE",
|
||||
Failure: "AddressInUse",
|
||||
}, {
|
||||
Errno: "EADDRNOTAVAIL",
|
||||
Errno: "EADDRNOTAVAIL",
|
||||
Failure: "AddressNotAvailable",
|
||||
}, {
|
||||
Errno: "EISCONN",
|
||||
Errno: "EISCONN",
|
||||
Failure: "AlreadyConnected",
|
||||
}, {
|
||||
Errno: "EFAULT",
|
||||
Errno: "EFAULT",
|
||||
Failure: "BadAddress",
|
||||
}, {
|
||||
Errno: "EBADF",
|
||||
Errno: "EBADF",
|
||||
Failure: "BadFileDescriptor",
|
||||
}, {
|
||||
Errno: "ECONNABORTED",
|
||||
Errno: "ECONNABORTED",
|
||||
Failure: "ConnectionAborted",
|
||||
}, {
|
||||
Errno: "EALREADY",
|
||||
Errno: "EALREADY",
|
||||
Failure: "ConnectionAlreadyInProgress",
|
||||
}, {
|
||||
Errno: "EDESTADDRREQ",
|
||||
Errno: "EDESTADDRREQ",
|
||||
Failure: "DestinationAddressRequired",
|
||||
}, {
|
||||
Errno: "EINTR",
|
||||
Errno: "EINTR",
|
||||
Failure: "Interrupted",
|
||||
}, {
|
||||
Errno: "EINVAL",
|
||||
Errno: "EINVAL",
|
||||
Failure: "InvalidArgument",
|
||||
}, {
|
||||
Errno: "EMSGSIZE",
|
||||
Errno: "EMSGSIZE",
|
||||
Failure: "MessageSize",
|
||||
}, {
|
||||
Errno: "ENETDOWN",
|
||||
Errno: "ENETDOWN",
|
||||
Failure: "NetworkDown",
|
||||
}, {
|
||||
Errno: "ENETRESET",
|
||||
Errno: "ENETRESET",
|
||||
Failure: "NetworkReset",
|
||||
}, {
|
||||
Errno: "ENETUNREACH",
|
||||
Errno: "ENETUNREACH",
|
||||
Failure: "NetworkUnreachable",
|
||||
}, {
|
||||
Errno: "ENOBUFS",
|
||||
Errno: "ENOBUFS",
|
||||
Failure: "NoBufferSpace",
|
||||
}, {
|
||||
Errno: "ENOPROTOOPT",
|
||||
Errno: "ENOPROTOOPT",
|
||||
Failure: "NoProtocolOption",
|
||||
}, {
|
||||
Errno: "ENOTSOCK",
|
||||
Errno: "ENOTSOCK",
|
||||
Failure: "NotASocket",
|
||||
}, {
|
||||
Errno: "ENOTCONN",
|
||||
Errno: "ENOTCONN",
|
||||
Failure: "NotConnected",
|
||||
}, {
|
||||
Errno: "EWOULDBLOCK",
|
||||
Errno: "EWOULDBLOCK",
|
||||
Failure: "OperationWouldBlock",
|
||||
}, {
|
||||
Errno: "EACCES",
|
||||
Errno: "EACCES",
|
||||
Failure: "PermissionDenied",
|
||||
}, {
|
||||
Errno: "EPROTONOSUPPORT",
|
||||
Errno: "EPROTONOSUPPORT",
|
||||
Failure: "ProtocolNotSupported",
|
||||
}, {
|
||||
Errno: "EPROTOTYPE",
|
||||
Errno: "EPROTOTYPE",
|
||||
Failure: "WrongProtocolType",
|
||||
}}
|
||||
|
||||
func fileCreate(filename string) *os.File {
|
||||
|
@ -143,6 +164,19 @@ func writeGenericFile() {
|
|||
fileWrite(filep, "\t\"errors\"\n")
|
||||
fileWrite(filep, "\t\"syscall\"\n")
|
||||
fileWrite(filep, ")\n\n")
|
||||
|
||||
fileWrite(filep, "// This enumeration lists the syscall-derived failures defined at\n")
|
||||
fileWrite(filep, "// https://github.com/ooni/spec/blob/master/data-formats/df-007-errors.md\n")
|
||||
fileWrite(filep, "//\n")
|
||||
fileWrite(filep, "// See also the enumeration at failures.go for the failures that\n")
|
||||
fileWrite(filep, "// DO NOT derive from system call errors.\n")
|
||||
fileWrite(filep, "const (\n")
|
||||
for _, spec := range Specs {
|
||||
filePrintf(filep, "\tFailure%s = \"%s\"\n", spec.Failure,
|
||||
strcase.ToSnake(spec.Failure))
|
||||
}
|
||||
fileWrite(filep, ")\n\n")
|
||||
|
||||
fileWrite(filep, "// toSyscallErr converts a syscall error to the\n")
|
||||
fileWrite(filep, "// proper OONI error. Returns the OONI error string\n")
|
||||
fileWrite(filep, "// on success, an empty string otherwise.\n")
|
||||
|
@ -164,6 +198,40 @@ func writeGenericFile() {
|
|||
fileWrite(filep, "\t}\n")
|
||||
fileWrite(filep, "\treturn \"\"\n")
|
||||
fileWrite(filep, "}\n\n")
|
||||
|
||||
fileClose(filep)
|
||||
gofmt(filename)
|
||||
}
|
||||
|
||||
func writeGenericTestFile() {
|
||||
filename := "errno_test.go"
|
||||
filep := fileCreate(filename)
|
||||
|
||||
fileWrite(filep, "// Code generated by go generate; DO NOT EDIT.\n")
|
||||
filePrintf(filep, "// Generated: %+v\n\n", time.Now())
|
||||
fileWrite(filep, "package errorsx\n\n")
|
||||
fileWrite(filep, "import (\n")
|
||||
fileWrite(filep, "\t\"io\"\n")
|
||||
fileWrite(filep, "\t\"syscall\"\n")
|
||||
fileWrite(filep, "\t\"testing\"\n")
|
||||
fileWrite(filep, ")\n\n")
|
||||
|
||||
fileWrite(filep, "func TestToSyscallErr(t *testing.T) {\n")
|
||||
fileWrite(filep, "\tif v := toSyscallErr(io.EOF); v != \"\" {\n")
|
||||
fileWrite(filep, "\t\tt.Fatalf(\"expected empty string, got '%s'\", v)\n")
|
||||
fileWrite(filep, "\t}\n")
|
||||
|
||||
for _, spec := range Specs {
|
||||
filePrintf(filep, "\tif v := toSyscallErr(%s); v != Failure%s {\n", spec.Errno, spec.Failure)
|
||||
filePrintf(filep, "\t\tt.Fatalf(\"expected '%%s', got '%%s'\", Failure%s, v)\n", spec.Failure)
|
||||
fileWrite(filep, "\t}\n")
|
||||
}
|
||||
|
||||
fileWrite(filep, "\tif v := toSyscallErr(syscall.Errno(0)); v != \"\" {\n")
|
||||
fileWrite(filep, "\t\tt.Fatalf(\"expected empty string, got '%s'\", v)\n")
|
||||
fileWrite(filep, "\t}\n")
|
||||
fileWrite(filep, "}\n")
|
||||
|
||||
fileClose(filep)
|
||||
gofmt(filename)
|
||||
}
|
||||
|
@ -172,4 +240,5 @@ func main() {
|
|||
writeSystemSpecificFile("unix")
|
||||
writeSystemSpecificFile("windows")
|
||||
writeGenericFile()
|
||||
writeGenericTestFile()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user