From 5c217594d7ca71e2edc0f70c8395ef023834773a Mon Sep 17 00:00:00 2001 From: Simone Basso Date: Tue, 7 Sep 2021 14:50:38 +0200 Subject: [PATCH] refactor(errorsx): autogenerate all failure names (#474) Part of https://github.com/ooni/probe/issues/1591 --- internal/errorsx/errno.go | 24 +++++++++++---- internal/errorsx/errno_test.go | 2 +- internal/errorsx/errno_unix.go | 2 +- internal/errorsx/errno_windows.go | 2 +- internal/errorsx/errorsx_test.go | 4 +-- internal/errorsx/failures.go | 39 ------------------------ internal/errorsx/generator/main.go | 48 ++++++++++++++++++++++++++---- internal/errorsx/quic.go | 4 +-- 8 files changed, 69 insertions(+), 56 deletions(-) delete mode 100644 internal/errorsx/failures.go diff --git a/internal/errorsx/errno.go b/internal/errorsx/errno.go index e69dbf6..5a2e4b7 100644 --- a/internal/errorsx/errno.go +++ b/internal/errorsx/errno.go @@ -1,5 +1,5 @@ // Code generated by go generate; DO NOT EDIT. -// Generated: 2021-09-07 13:05:58.447943 +0200 CEST m=+0.137110292 +// Generated: 2021-09-07 14:38:45.497503 +0200 CEST m=+0.144277376 package errorsx @@ -10,12 +10,12 @@ import ( "syscall" ) -// This enumeration lists the syscall-derived failures defined at +// This enumeration lists the 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 ( + // + // System errors + // FailureOperationCanceled = "operation_canceled" FailureConnectionRefused = "connection_refused" FailureConnectionReset = "connection_reset" @@ -44,6 +44,20 @@ const ( FailurePermissionDenied = "permission_denied" FailureProtocolNotSupported = "protocol_not_supported" FailureWrongProtocolType = "wrong_protocol_type" + + // + // Library errors + // + FailureDNSBogonError = "dns_bogon_error" + FailureDNSNXDOMAINError = "dns_nxdomain_error" + FailureEOFError = "eof_error" + FailureGenericTimeoutError = "generic_timeout_error" + FailureQUICIncompatibleVersion = "quic_incompatible_version" + FailureSSLFailedHandshake = "ssl_failed_handshake" + FailureSSLInvalidHostname = "ssl_invalid_hostname" + FailureSSLUnknownAuthority = "ssl_unknown_authority" + FailureSSLInvalidCertificate = "ssl_invalid_certificate" + FailureJSONParseError = "json_parse_error" ) // toSyscallErr converts a syscall error to the diff --git a/internal/errorsx/errno_test.go b/internal/errorsx/errno_test.go index 861b774..8ba73c6 100644 --- a/internal/errorsx/errno_test.go +++ b/internal/errorsx/errno_test.go @@ -1,5 +1,5 @@ // Code generated by go generate; DO NOT EDIT. -// Generated: 2021-09-07 13:05:58.496075 +0200 CEST m=+0.185240417 +// Generated: 2021-09-07 14:38:45.5818 +0200 CEST m=+0.228575418 package errorsx diff --git a/internal/errorsx/errno_unix.go b/internal/errorsx/errno_unix.go index c6df23f..6e5f2ba 100644 --- a/internal/errorsx/errno_unix.go +++ b/internal/errorsx/errno_unix.go @@ -1,5 +1,5 @@ // Code generated by go generate; DO NOT EDIT. -// Generated: 2021-09-07 13:05:58.31181 +0200 CEST m=+0.000981501 +// Generated: 2021-09-07 14:38:45.354514 +0200 CEST m=+0.001286668 package errorsx diff --git a/internal/errorsx/errno_windows.go b/internal/errorsx/errno_windows.go index 425505c..56811e0 100644 --- a/internal/errorsx/errno_windows.go +++ b/internal/errorsx/errno_windows.go @@ -1,5 +1,5 @@ // Code generated by go generate; DO NOT EDIT. -// Generated: 2021-09-07 13:05:58.421578 +0200 CEST m=+0.110745959 +// Generated: 2021-09-07 14:38:45.459702 +0200 CEST m=+0.106475584 package errorsx diff --git a/internal/errorsx/errorsx_test.go b/internal/errorsx/errorsx_test.go index c60ebc2..a9ff882 100644 --- a/internal/errorsx/errorsx_test.go +++ b/internal/errorsx/errorsx_test.go @@ -162,7 +162,7 @@ func TestClassifyQUICFailure(t *testing.T) { } }) t.Run("for incompatible quic version", func(t *testing.T) { - if classifyQUICFailure(&quic.VersionNegotiationError{}) != FailureNoCompatibleQUICVersion { + if classifyQUICFailure(&quic.VersionNegotiationError{}) != FailureQUICIncompatibleVersion { t.Fatal("unexpected results") } }) @@ -183,7 +183,7 @@ func TestClassifyQUICFailure(t *testing.T) { }) t.Run("for QUIC CRYPTO Handshake", func(t *testing.T) { var err quic.TransportErrorCode = quicTLSAlertHandshakeFailure - if classifyQUICFailure(&quic.TransportError{ErrorCode: err}) != FailureSSLHandshake { + if classifyQUICFailure(&quic.TransportError{ErrorCode: err}) != FailureSSLFailedHandshake { t.Fatal("unexpected results") } }) diff --git a/internal/errorsx/failures.go b/internal/errorsx/failures.go deleted file mode 100644 index 84a7103..0000000 --- a/internal/errorsx/failures.go +++ /dev/null @@ -1,39 +0,0 @@ -package errorsx - -// 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 ( - // FailureDNSBogonError means we detected bogon in DNS reply. - FailureDNSBogonError = "dns_bogon_error" - - // FailureDNSNXDOMAINError means we got NXDOMAIN in DNS reply. - FailureDNSNXDOMAINError = "dns_nxdomain_error" - - // FailureEOFError means we got unexpected EOF on connection. - FailureEOFError = "eof_error" - - // FailureGenericTimeoutError means we got some timer has expired. - FailureGenericTimeoutError = "generic_timeout_error" - - // FailureNoCompatibleQUICVersion means that the server does not support the proposed QUIC version - FailureNoCompatibleQUICVersion = "quic_incompatible_version" - - // FailureSSLHandshake means that the negotiation of cryptographic parameters failed - FailureSSLHandshake = "ssl_failed_handshake" - - // FailureSSLInvalidHostname means we got certificate is not valid for SNI. - FailureSSLInvalidHostname = "ssl_invalid_hostname" - - // FailureSSLUnknownAuthority means we cannot find CA validating certificate. - FailureSSLUnknownAuthority = "ssl_unknown_authority" - - // FailureSSLInvalidCertificate means certificate experired or other - // sort of errors causing it to be invalid. - FailureSSLInvalidCertificate = "ssl_invalid_certificate" - - // FailureJSONParseError indicates that we couldn't parse a JSON - FailureJSONParseError = "json_parse_error" -) diff --git a/internal/errorsx/generator/main.go b/internal/errorsx/generator/main.go index 21ff537..72652b2 100644 --- a/internal/errorsx/generator/main.go +++ b/internal/errorsx/generator/main.go @@ -35,7 +35,7 @@ func (es *ErrorSpec) AsFailureVar() string { // AsFailureString returns the OONI failure string. func (es *ErrorSpec) AsFailureString() string { - return es.failure + return strcase.ToSnake(es.failure) } // NewSystemError constructs a new ErrorSpec representing a system @@ -87,6 +87,20 @@ var Specs = []*ErrorSpec{ NewSystemError("EACCES", "permission_denied"), NewSystemError("EPROTONOSUPPORT", "protocol_not_supported"), NewSystemError("EPROTOTYPE", "wrong_protocol_type"), + + // Implementation note: we need to specify acronyms we + // want to be upper case in uppercase here. For example, + // we must write "DNS" rather than writing "dns". + NewLibraryError("DNS_bogon_error"), + NewLibraryError("DNS_NXDOMAIN_error"), + NewLibraryError("EOF_error"), + NewLibraryError("generic_timeout_error"), + NewLibraryError("QUIC_incompatible_version"), + NewLibraryError("SSL_failed_handshake"), + NewLibraryError("SSL_invalid_hostname"), + NewLibraryError("SSL_unknown_authority"), + NewLibraryError("SSL_invalid_certificate"), + NewLibraryError("JSON_parse_error"), } func fileCreate(filename string) *os.File { @@ -129,6 +143,9 @@ func writeSystemSpecificFile(kind string) { filePrintf(filep, "import \"golang.org/x/sys/%s\"\n\n", kind) fileWrite(filep, "const (\n") for _, spec := range Specs { + if !spec.IsSystemError() { + continue + } filePrintf(filep, "\t%s = %s.%s\n", spec.AsErrnoName(), kind, spec.AsErrnoName()) } @@ -149,13 +166,28 @@ func writeGenericFile() { fileWrite(filep, "\t\"syscall\"\n") fileWrite(filep, ")\n\n") - fileWrite(filep, "// This enumeration lists the syscall-derived failures defined at\n") + fileWrite(filep, "// This enumeration lists the 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") + fileWrite(filep, "//\n") + fileWrite(filep, "// System errors\n") + fileWrite(filep, "//\n") for _, spec := range Specs { + if !spec.IsSystemError() { + continue + } + filePrintf(filep, "\t%s = \"%s\"\n", + spec.AsFailureVar(), + spec.AsFailureString()) + } + fileWrite(filep, "\n") + fileWrite(filep, "//\n") + fileWrite(filep, "// Library errors\n") + fileWrite(filep, "//\n") + for _, spec := range Specs { + if spec.IsSystemError() { + continue + } filePrintf(filep, "\t%s = \"%s\"\n", spec.AsFailureVar(), spec.AsFailureString()) @@ -175,6 +207,9 @@ func writeGenericFile() { fileWrite(filep, "\t}\n") fileWrite(filep, "\tswitch errno {\n") for _, spec := range Specs { + if !spec.IsSystemError() { + continue + } filePrintf(filep, "\tcase %s:\n", spec.AsErrnoName()) filePrintf(filep, "\t\treturn %s\n", spec.AsFailureVar()) } @@ -205,6 +240,9 @@ func writeGenericTestFile() { fileWrite(filep, "\t}\n") for _, spec := range Specs { + if !spec.IsSystemError() { + continue + } filePrintf(filep, "\tif v := toSyscallErr(%s); v != %s {\n", spec.AsErrnoName(), spec.AsFailureVar()) filePrintf(filep, "\t\tt.Fatalf(\"expected '%%s', got '%%s'\", %s, v)\n", diff --git a/internal/errorsx/quic.go b/internal/errorsx/quic.go index 4fb6ab7..a0c0740 100644 --- a/internal/errorsx/quic.go +++ b/internal/errorsx/quic.go @@ -107,7 +107,7 @@ func classifyQUICFailure(err error) string { var transportError *quic.TransportError if errors.As(err, &versionNegotiation) { - return FailureNoCompatibleQUICVersion + return FailureQUICIncompatibleVersion } if errors.As(err, &statelessReset) { return FailureConnectionReset @@ -130,7 +130,7 @@ func classifyQUICFailure(err error) string { // TLSAlertDecryptError and TLSAlertHandshakeFailure are summarized to a FailureSSLHandshake error because both // alerts are caused by a failed or corrupted parameter negotiation during the TLS handshake. if errCode == quicTLSAlertDecryptError || errCode == quicTLSAlertHandshakeFailure { - return FailureSSLHandshake + return FailureSSLFailedHandshake } if errCode == quicTLSAlertUnknownCA { return FailureSSLUnknownAuthority