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. | // 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 | package errorsx | ||||||
| 
 | 
 | ||||||
| @ -10,6 +10,42 @@ import ( | |||||||
| 	"syscall" | 	"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 | // toSyscallErr converts a syscall error to the | ||||||
| // proper OONI error. Returns the OONI error string | // proper OONI error. Returns the OONI error string | ||||||
| // on success, an empty string otherwise. | // on success, an empty string otherwise. | ||||||
| @ -23,7 +59,7 @@ func toSyscallErr(err error) string { | |||||||
| 	} | 	} | ||||||
| 	switch errno { | 	switch errno { | ||||||
| 	case ECANCELED: | 	case ECANCELED: | ||||||
| 		return FailureInterrupted | 		return FailureOperationCanceled | ||||||
| 	case ECONNREFUSED: | 	case ECONNREFUSED: | ||||||
| 		return FailureConnectionRefused | 		return FailureConnectionRefused | ||||||
| 	case ECONNRESET: | 	case ECONNRESET: | ||||||
| @ -31,7 +67,53 @@ func toSyscallErr(err error) string { | |||||||
| 	case EHOSTUNREACH: | 	case EHOSTUNREACH: | ||||||
| 		return FailureHostUnreachable | 		return FailureHostUnreachable | ||||||
| 	case ETIMEDOUT: | 	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 "" | 	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. | // 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 | package errorsx | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| // Code generated by go generate; DO NOT EDIT. | // 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 | package errorsx | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -54,7 +54,7 @@ func TestToFailureString(t *testing.T) { | |||||||
| 		} | 		} | ||||||
| 	}) | 	}) | ||||||
| 	t.Run("for canceled", func(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") | 			t.Fatal("unexpected results") | ||||||
| 		} | 		} | ||||||
| 	}) | 	}) | ||||||
| @ -74,7 +74,7 @@ func TestToFailureString(t *testing.T) { | |||||||
| 		} | 		} | ||||||
| 	}) | 	}) | ||||||
| 	t.Run("for system timeout", func(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") | 			t.Fatal("unexpected results") | ||||||
| 		} | 		} | ||||||
| 	}) | 	}) | ||||||
|  | |||||||
| @ -1,14 +1,11 @@ | |||||||
| package errorsx | 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 | // 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 ( | const ( | ||||||
| 	// FailureConnectionRefused means ECONNREFUSED. |  | ||||||
| 	FailureConnectionRefused = "connection_refused" |  | ||||||
| 
 |  | ||||||
| 	// FailureConnectionReset means ECONNRESET. |  | ||||||
| 	FailureConnectionReset = "connection_reset" |  | ||||||
| 
 |  | ||||||
| 	// FailureDNSBogonError means we detected bogon in DNS reply. | 	// FailureDNSBogonError means we detected bogon in DNS reply. | ||||||
| 	FailureDNSBogonError = "dns_bogon_error" | 	FailureDNSBogonError = "dns_bogon_error" | ||||||
| 
 | 
 | ||||||
| @ -21,12 +18,6 @@ const ( | |||||||
| 	// FailureGenericTimeoutError means we got some timer has expired. | 	// FailureGenericTimeoutError means we got some timer has expired. | ||||||
| 	FailureGenericTimeoutError = "generic_timeout_error" | 	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 means that the server does not support the proposed QUIC version | ||||||
| 	FailureNoCompatibleQUICVersion = "quic_incompatible_version" | 	FailureNoCompatibleQUICVersion = "quic_incompatible_version" | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ import ( | |||||||
| 	"os" | 	"os" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/iancoleman/strcase" | ||||||
| 	"golang.org/x/sys/execabs" | 	"golang.org/x/sys/execabs" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @ -18,13 +19,10 @@ type ErrorSpec struct { | |||||||
| 	Failure string | 	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. | // Specs contains all the error specs. | ||||||
| var Specs = []ErrorSpec{{ | var Specs = []ErrorSpec{{ | ||||||
| 	Errno:   "ECANCELED", | 	Errno:   "ECANCELED", | ||||||
| 	Failure: "Interrupted", | 	Failure: "OperationCanceled", | ||||||
| }, { | }, { | ||||||
| 	Errno:   "ECONNREFUSED", | 	Errno:   "ECONNREFUSED", | ||||||
| 	Failure: "ConnectionRefused", | 	Failure: "ConnectionRefused", | ||||||
| @ -36,53 +34,76 @@ var Specs = []ErrorSpec{{ | |||||||
| 	Failure: "HostUnreachable", | 	Failure: "HostUnreachable", | ||||||
| }, { | }, { | ||||||
| 	Errno:   "ETIMEDOUT", | 	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 { | func fileCreate(filename string) *os.File { | ||||||
| @ -143,6 +164,19 @@ func writeGenericFile() { | |||||||
| 	fileWrite(filep, "\t\"errors\"\n") | 	fileWrite(filep, "\t\"errors\"\n") | ||||||
| 	fileWrite(filep, "\t\"syscall\"\n") | 	fileWrite(filep, "\t\"syscall\"\n") | ||||||
| 	fileWrite(filep, ")\n\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, "// toSyscallErr converts a syscall error to the\n") | ||||||
| 	fileWrite(filep, "// proper OONI error. Returns the OONI error string\n") | 	fileWrite(filep, "// proper OONI error. Returns the OONI error string\n") | ||||||
| 	fileWrite(filep, "// on success, an empty string otherwise.\n") | 	fileWrite(filep, "// on success, an empty string otherwise.\n") | ||||||
| @ -164,6 +198,40 @@ func writeGenericFile() { | |||||||
| 	fileWrite(filep, "\t}\n") | 	fileWrite(filep, "\t}\n") | ||||||
| 	fileWrite(filep, "\treturn \"\"\n") | 	fileWrite(filep, "\treturn \"\"\n") | ||||||
| 	fileWrite(filep, "}\n\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) | 	fileClose(filep) | ||||||
| 	gofmt(filename) | 	gofmt(filename) | ||||||
| } | } | ||||||
| @ -172,4 +240,5 @@ func main() { | |||||||
| 	writeSystemSpecificFile("unix") | 	writeSystemSpecificFile("unix") | ||||||
| 	writeSystemSpecificFile("windows") | 	writeSystemSpecificFile("windows") | ||||||
| 	writeGenericFile() | 	writeGenericFile() | ||||||
|  | 	writeGenericTestFile() | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user