difference =
+ Sets.difference(expectedTokens, actualTokens).stream().sorted().collect(toImmutableList());
+
+ // ensure all permutations are accounted for, reporting any that haven't been and providing
+ // a stub which can be used to easily define them.
+ assertWithMessage("Missing mappings for tokens").that(difference).isEmpty();
+
+ // wrap our case in an array for ultimate passing to the constructor
+ return cases.stream().map(c -> new Object[] {c}).collect(toImmutableList());
+ }
+
+ /**
+ * Generate a token which represents a permutation for which a {@link Case} must be defined.
+ *
+ * If a case is not defined, this value will be reported and functions as a stub to easily
+ * define a new {@code Case}.
+ */
+ private static String token(ThrowableCategory t, HandlerCategory h) {
+ return String.format(
+ "new Case(ThrowableCategory.%s, HandlerCategory.%s, /*TODO*/ null, /*TODO*/ null)",
+ t.name(), h.name());
+ }
+
+ /**
+ * An individual case we want to validate.
+ *
+ *
Given a {@link HandlerCategory} and {@link ThrowableCategory} validate the retryability and
+ * behavior between default and legacy handlers.
+ */
+ static final class Case {
+
+ private final HandlerCategory handlerCategory;
+ private final ThrowableCategory throwableCategory;
+ private final ExpectRetry expectRetry;
+ private final Behavior expectedBehavior;
+
+ Case(
+ ThrowableCategory throwableCategory,
+ HandlerCategory handlerCategory,
+ ExpectRetry expectRetry,
+ Behavior expectedBehavior) {
+ this.handlerCategory = handlerCategory;
+ this.throwableCategory = throwableCategory;
+ this.expectRetry = expectRetry;
+ this.expectedBehavior = expectedBehavior;
+ }
+
+ Throwable getThrowable() {
+ return throwableCategory.throwable;
+ }
+
+ public ExpectRetry getExpectRetry() {
+ return expectRetry;
+ }
+
+ @Override
+ public String toString() {
+ return "Case{"
+ + "handlerCategory="
+ + handlerCategory
+ + ", throwableCategory="
+ + throwableCategory
+ + ", expectRetry="
+ + expectRetry
+ + ", expectedBehavior="
+ + expectedBehavior
+ + '}';
+ }
+ }
+
+ /** Whether to expect a retry to happen or not */
+ enum ExpectRetry {
+ YES(true),
+ NO(false);
+
+ private final boolean shouldRetry;
+
+ ExpectRetry(boolean shouldRetry) {
+ this.shouldRetry = shouldRetry;
+ }
+ }
+
+ /**
+ * A category of handler type, and the ability to resolve the {@link ResultRetryAlgorithm} given a
+ * {@link StorageRetryStrategy}
+ */
+ enum HandlerCategory implements Function> {
+ IDEMPOTENT,
+ NONIDEMPOTENT;
+
+ @Override
+ public ResultRetryAlgorithm> apply(StorageRetryStrategy storageRetryStrategy) {
+ switch (this) {
+ case IDEMPOTENT:
+ return storageRetryStrategy.getIdempotentHandler();
+ case NONIDEMPOTENT:
+ return storageRetryStrategy.getNonidempotentHandler();
+ default:
+ throw new IllegalStateException("Unmappable HandlerCategory: " + this.name());
+ }
+ }
+ }
+
+ /** Some states comparing behavior between default and legacy */
+ enum Behavior {
+ DEFAULT_MORE_PERMISSIBLE,
+ SAME,
+ DEFAULT_MORE_STRICT
+ }
+
+ /**
+ * A set of exceptions we want to validate behavior for.
+ *
+ * This class is an enum for convenience of specifying a closed set, along with providing easy
+ * to read names in code thereby forgoing the need to maintain a separate set of strings.
+ */
+ enum ThrowableCategory {
+ SOCKET_TIMEOUT_EXCEPTION(C.SOCKET_TIMEOUT_EXCEPTION),
+ SOCKET_EXCEPTION(C.SOCKET_EXCEPTION),
+ SSL_EXCEPTION(C.SSL_EXCEPTION),
+ SSL_EXCEPTION_CONNECTION_SHUTDOWN(C.SSL_EXCEPTION_CONNECTION_SHUTDOWN),
+ SSL_HANDSHAKE_EXCEPTION(C.SSL_HANDSHAKE_EXCEPTION),
+ SSL_HANDSHAKE_EXCEPTION_CAUSED_BY_CERTIFICATE_EXCEPTION(
+ C.SSL_HANDSHAKE_EXCEPTION_CERTIFICATE_EXCEPTION),
+ INSUFFICIENT_DATA(C.INSUFFICIENT_DATA_WRITTEN),
+ ERROR_WRITING_REQUEST_BODY(C.ERROR_WRITING_REQUEST_BODY),
+ HTTP_RESPONSE_EXCEPTION_401(C.HTTP_401),
+ HTTP_RESPONSE_EXCEPTION_403(C.HTTP_403),
+ HTTP_RESPONSE_EXCEPTION_404(C.HTTP_404),
+ HTTP_RESPONSE_EXCEPTION_408(C.HTTP_409),
+ HTTP_RESPONSE_EXCEPTION_429(C.HTTP_429),
+ HTTP_RESPONSE_EXCEPTION_500(C.HTTP_500),
+ HTTP_RESPONSE_EXCEPTION_502(C.HTTP_502),
+ HTTP_RESPONSE_EXCEPTION_503(C.HTTP_503),
+ HTTP_RESPONSE_EXCEPTION_504(C.HTTP_504),
+ STORAGE_EXCEPTION_HTTP_RESPONSE_EXCEPTION_401(new StorageException(C.HTTP_401)),
+ STORAGE_EXCEPTION_HTTP_RESPONSE_EXCEPTION_403(new StorageException(C.HTTP_403)),
+ STORAGE_EXCEPTION_HTTP_RESPONSE_EXCEPTION_404(new StorageException(C.HTTP_404)),
+ STORAGE_EXCEPTION_HTTP_RESPONSE_EXCEPTION_408(new StorageException(C.HTTP_409)),
+ STORAGE_EXCEPTION_HTTP_RESPONSE_EXCEPTION_429(new StorageException(C.HTTP_429)),
+ STORAGE_EXCEPTION_HTTP_RESPONSE_EXCEPTION_500(new StorageException(C.HTTP_500)),
+ STORAGE_EXCEPTION_HTTP_RESPONSE_EXCEPTION_502(new StorageException(C.HTTP_502)),
+ STORAGE_EXCEPTION_HTTP_RESPONSE_EXCEPTION_503(new StorageException(C.HTTP_503)),
+ STORAGE_EXCEPTION_HTTP_RESPONSE_EXCEPTION_504(new StorageException(C.HTTP_504)),
+ STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_401(new StorageException(C.JSON_401)),
+ STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_403(new StorageException(C.JSON_403)),
+ STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_404(new StorageException(C.JSON_404)),
+ STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_408(new StorageException(C.JSON_408)),
+ STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_429(new StorageException(C.JSON_429)),
+ STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_500(new StorageException(C.JSON_500)),
+ STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_502(new StorageException(C.JSON_502)),
+ STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_503(new StorageException(C.JSON_503)),
+ STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_504(new StorageException(C.JSON_504)),
+ STORAGE_EXCEPTION_SOCKET_TIMEOUT_EXCEPTION(new StorageException(C.SOCKET_TIMEOUT_EXCEPTION)),
+ STORAGE_EXCEPTION_SOCKET_EXCEPTION(new StorageException(C.SOCKET_EXCEPTION)),
+ STORAGE_EXCEPTION_SSL_EXCEPTION(new StorageException(C.SSL_EXCEPTION)),
+ STORAGE_EXCEPTION_SSL_EXCEPTION_CONNECTION_SHUTDOWN(
+ new StorageException(C.SSL_EXCEPTION_CONNECTION_SHUTDOWN)),
+ STORAGE_EXCEPTION_SSL_HANDSHAKE_EXCEPTION(new StorageException(C.SSL_HANDSHAKE_EXCEPTION)),
+ STORAGE_EXCEPTION_SSL_HANDSHAKE_EXCEPTION_CAUSED_BY_CERTIFICATE_EXCEPTION(
+ new StorageException(C.SSL_HANDSHAKE_EXCEPTION_CERTIFICATE_EXCEPTION)),
+ STORAGE_EXCEPTION_INSUFFICIENT_DATA(new StorageException(C.INSUFFICIENT_DATA_WRITTEN)),
+ STORAGE_EXCEPTION_ERROR_WRITING_REQUEST_BODY(
+ new StorageException(C.ERROR_WRITING_REQUEST_BODY)),
+ ILLEGAL_ARGUMENT_EXCEPTION(C.ILLEGAL_ARGUMENT_EXCEPTION),
+ STORAGE_EXCEPTION_ILLEGAL_ARGUMENT_EXCEPTION(
+ StorageException.coalesce(C.ILLEGAL_ARGUMENT_EXCEPTION)),
+ STORAGE_EXCEPTION_0_INTERNAL_ERROR(
+ new StorageException(0, "internalError", "internalError", null)),
+ STORAGE_EXCEPTION_0_CONNECTION_CLOSED_PREMATURELY(
+ new StorageException(
+ 0, "connectionClosedPrematurely", "connectionClosedPrematurely", null)),
+ STORAGE_EXCEPTION_0_CONNECTION_CLOSED_PREMATURELY_IO_CAUSE(
+ new StorageException(
+ 0,
+ "connectionClosedPrematurely",
+ "connectionClosedPrematurely",
+ C.CONNECTION_CLOSED_PREMATURELY)),
+ ;
+
+ private final Throwable throwable;
+
+ ThrowableCategory(Throwable throwable) {
+ this.throwable = throwable;
+ }
+
+ public Throwable getThrowable() {
+ return throwable;
+ }
+
+ /**
+ * A class of constants for use by the containing enum.
+ *
+ *
Enums can't have static fields, so we use this class to hold constants which are used by
+ * the enum values.
+ */
+ private static final class C {
+ private static final SocketTimeoutException SOCKET_TIMEOUT_EXCEPTION =
+ new SocketTimeoutException();
+ private static final SocketException SOCKET_EXCEPTION = new SocketException();
+ private static final SSLException SSL_EXCEPTION = new SSLException("unknown");
+ private static final SSLException SSL_EXCEPTION_CONNECTION_SHUTDOWN =
+ new SSLException("Connection has been shutdown: asdf");
+ private static final SSLHandshakeException SSL_HANDSHAKE_EXCEPTION =
+ newSslHandshakeExceptionWithCause(new SSLProtocolException(DEFAULT_MESSAGE));
+ private static final SSLHandshakeException SSL_HANDSHAKE_EXCEPTION_CERTIFICATE_EXCEPTION =
+ newSslHandshakeExceptionWithCause(new CertificateException());
+ private static final IOException INSUFFICIENT_DATA_WRITTEN =
+ new IOException("insufficient data written");
+ private static final IOException ERROR_WRITING_REQUEST_BODY =
+ new IOException("Error writing request body to server");
+ private static final HttpResponseException HTTP_401 =
+ newHttpResponseException(401, "Unauthorized");
+ private static final HttpResponseException HTTP_403 =
+ newHttpResponseException(403, "Forbidden");
+ private static final HttpResponseException HTTP_404 =
+ newHttpResponseException(404, "Not Found");
+ private static final HttpResponseException HTTP_409 =
+ newHttpResponseException(408, "Request Timeout");
+ private static final HttpResponseException HTTP_429 =
+ newHttpResponseException(429, "Too Many Requests");
+ private static final HttpResponseException HTTP_500 =
+ newHttpResponseException(500, "Internal Server Error");
+ private static final HttpResponseException HTTP_502 =
+ newHttpResponseException(502, "Bad Gateway");
+ private static final HttpResponseException HTTP_503 =
+ newHttpResponseException(503, "Service Unavailable");
+ private static final HttpResponseException HTTP_504 =
+ newHttpResponseException(504, "Gateway Timeout");
+ private static final GoogleJsonError JSON_401 = newGoogleJsonError(401, "Unauthorized");
+ private static final GoogleJsonError JSON_403 = newGoogleJsonError(403, "Forbidden");
+ private static final GoogleJsonError JSON_404 = newGoogleJsonError(404, "Not Found");
+ private static final GoogleJsonError JSON_408 = newGoogleJsonError(408, "Request Timeout");
+ private static final GoogleJsonError JSON_429 = newGoogleJsonError(429, "Too Many Requests");
+ private static final GoogleJsonError JSON_500 =
+ newGoogleJsonError(500, "Internal Server Error");
+ private static final GoogleJsonError JSON_502 = newGoogleJsonError(502, "Bad Gateway");
+ private static final GoogleJsonError JSON_503 =
+ newGoogleJsonError(503, "Service Unavailable");
+ private static final GoogleJsonError JSON_504 = newGoogleJsonError(504, "Gateway Timeout");
+ private static final IllegalArgumentException ILLEGAL_ARGUMENT_EXCEPTION =
+ new IllegalArgumentException("illegal argument");
+ private static final IOException CONNECTION_CLOSED_PREMATURELY =
+ new IOException("simulated Connection closed prematurely");
+
+ private static HttpResponseException newHttpResponseException(
+ int httpStatusCode, String name) {
+ return new HttpResponseException.Builder(httpStatusCode, name, new HttpHeaders()).build();
+ }
+
+ private static GoogleJsonError newGoogleJsonError(int code, String message) {
+ GoogleJsonError error = new GoogleJsonError();
+ error.setCode(code);
+ error.setMessage(message);
+ return error;
+ }
+
+ private static SSLHandshakeException newSslHandshakeExceptionWithCause(Throwable cause) {
+ SSLHandshakeException sslHandshakeException = new SSLHandshakeException(DEFAULT_MESSAGE);
+ Throwable throwable = sslHandshakeException.initCause(cause);
+ return (SSLHandshakeException) throwable;
+ }
+ }
+ }
+
+ /**
+ * A corralled method which allows us to move the individual cases away from the rest of the code
+ * since our code formatter is very strict and seems to feel 475 lines of code at 100 columns is
+ * better than 90 lines at 200 columns.
+ *
+ *
this method returns a list that essentially is a table of where each row is an individual
+ * test case
+ *
+ *
+ *
+ * {@link ThrowableCategory throwable category} |
+ * {@link HandlerCategory handler category} |
+ * {@link ExpectRetry whether retry is expected} |
+ * {@link Behavior what the expected behavior comparison is} |
+ *
+ *
+ * {@link ThrowableCategory#STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_500 STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_500} |
+ * {@link HandlerCategory#NONIDEMPOTENT NONIDEMPOTENT} |
+ * {@link ExpectRetry#NO NO} |
+ * {@link Behavior#DEFAULT_MORE_STRICT DEFAULT_MORE_STRICT} |
+ *
+ *
+ */
+ private static ImmutableList getAllCases() {
+ return ImmutableList.builder()
+ .add(
+ new Case(
+ ThrowableCategory.ERROR_WRITING_REQUEST_BODY,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.DEFAULT_MORE_PERMISSIBLE),
+ new Case(
+ ThrowableCategory.ERROR_WRITING_REQUEST_BODY,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.HTTP_RESPONSE_EXCEPTION_401,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.HTTP_RESPONSE_EXCEPTION_401,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.HTTP_RESPONSE_EXCEPTION_403,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.HTTP_RESPONSE_EXCEPTION_403,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.HTTP_RESPONSE_EXCEPTION_404,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.HTTP_RESPONSE_EXCEPTION_404,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.HTTP_RESPONSE_EXCEPTION_408,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.DEFAULT_MORE_PERMISSIBLE),
+ new Case(
+ ThrowableCategory.HTTP_RESPONSE_EXCEPTION_408,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.HTTP_RESPONSE_EXCEPTION_429,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.DEFAULT_MORE_PERMISSIBLE),
+ new Case(
+ ThrowableCategory.HTTP_RESPONSE_EXCEPTION_429,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.HTTP_RESPONSE_EXCEPTION_500,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.DEFAULT_MORE_PERMISSIBLE),
+ new Case(
+ ThrowableCategory.HTTP_RESPONSE_EXCEPTION_500,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.HTTP_RESPONSE_EXCEPTION_502,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.DEFAULT_MORE_PERMISSIBLE),
+ new Case(
+ ThrowableCategory.HTTP_RESPONSE_EXCEPTION_502,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.HTTP_RESPONSE_EXCEPTION_503,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.DEFAULT_MORE_PERMISSIBLE),
+ new Case(
+ ThrowableCategory.HTTP_RESPONSE_EXCEPTION_503,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.HTTP_RESPONSE_EXCEPTION_504,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.DEFAULT_MORE_PERMISSIBLE),
+ new Case(
+ ThrowableCategory.HTTP_RESPONSE_EXCEPTION_504,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.ILLEGAL_ARGUMENT_EXCEPTION,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.ILLEGAL_ARGUMENT_EXCEPTION,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.INSUFFICIENT_DATA,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.DEFAULT_MORE_PERMISSIBLE),
+ new Case(
+ ThrowableCategory.INSUFFICIENT_DATA,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.SOCKET_EXCEPTION,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.DEFAULT_MORE_PERMISSIBLE),
+ new Case(
+ ThrowableCategory.SOCKET_EXCEPTION,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.SOCKET_TIMEOUT_EXCEPTION,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.DEFAULT_MORE_PERMISSIBLE),
+ new Case(
+ ThrowableCategory.SOCKET_TIMEOUT_EXCEPTION,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.SSL_EXCEPTION,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.SSL_EXCEPTION,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.SSL_EXCEPTION_CONNECTION_SHUTDOWN,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.DEFAULT_MORE_PERMISSIBLE),
+ new Case(
+ ThrowableCategory.SSL_EXCEPTION_CONNECTION_SHUTDOWN,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.SSL_HANDSHAKE_EXCEPTION,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.DEFAULT_MORE_PERMISSIBLE),
+ new Case(
+ ThrowableCategory.SSL_HANDSHAKE_EXCEPTION,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.SSL_HANDSHAKE_EXCEPTION_CAUSED_BY_CERTIFICATE_EXCEPTION,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.SSL_HANDSHAKE_EXCEPTION_CAUSED_BY_CERTIFICATE_EXCEPTION,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_ERROR_WRITING_REQUEST_BODY,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_ERROR_WRITING_REQUEST_BODY,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.DEFAULT_MORE_STRICT),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_401,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_401,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_403,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_403,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_404,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_404,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_408,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_408,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.DEFAULT_MORE_STRICT),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_429,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_429,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.DEFAULT_MORE_STRICT),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_500,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_500,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.DEFAULT_MORE_STRICT),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_502,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_502,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.DEFAULT_MORE_STRICT),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_503,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_503,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.DEFAULT_MORE_STRICT),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_504,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_GOOGLE_JSON_ERROR_504,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.DEFAULT_MORE_STRICT),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_HTTP_RESPONSE_EXCEPTION_401,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_HTTP_RESPONSE_EXCEPTION_401,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_HTTP_RESPONSE_EXCEPTION_403,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_HTTP_RESPONSE_EXCEPTION_403,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_HTTP_RESPONSE_EXCEPTION_404,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_HTTP_RESPONSE_EXCEPTION_404,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_HTTP_RESPONSE_EXCEPTION_408,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_HTTP_RESPONSE_EXCEPTION_408,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.DEFAULT_MORE_STRICT),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_HTTP_RESPONSE_EXCEPTION_429,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_HTTP_RESPONSE_EXCEPTION_429,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.DEFAULT_MORE_STRICT),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_HTTP_RESPONSE_EXCEPTION_500,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_HTTP_RESPONSE_EXCEPTION_500,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.DEFAULT_MORE_STRICT),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_HTTP_RESPONSE_EXCEPTION_502,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_HTTP_RESPONSE_EXCEPTION_502,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.DEFAULT_MORE_STRICT),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_HTTP_RESPONSE_EXCEPTION_503,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_HTTP_RESPONSE_EXCEPTION_503,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.DEFAULT_MORE_STRICT),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_HTTP_RESPONSE_EXCEPTION_504,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_HTTP_RESPONSE_EXCEPTION_504,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.DEFAULT_MORE_STRICT),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_ILLEGAL_ARGUMENT_EXCEPTION,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_ILLEGAL_ARGUMENT_EXCEPTION,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_INSUFFICIENT_DATA,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_INSUFFICIENT_DATA,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.DEFAULT_MORE_STRICT),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_SOCKET_EXCEPTION,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_SOCKET_EXCEPTION,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.DEFAULT_MORE_STRICT),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_SOCKET_TIMEOUT_EXCEPTION,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_SOCKET_TIMEOUT_EXCEPTION,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.DEFAULT_MORE_STRICT),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_SSL_EXCEPTION,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_SSL_EXCEPTION,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_SSL_EXCEPTION_CONNECTION_SHUTDOWN,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_SSL_EXCEPTION_CONNECTION_SHUTDOWN,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.DEFAULT_MORE_STRICT),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_SSL_HANDSHAKE_EXCEPTION,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_SSL_HANDSHAKE_EXCEPTION,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.DEFAULT_MORE_STRICT),
+ new Case(
+ ThrowableCategory
+ .STORAGE_EXCEPTION_SSL_HANDSHAKE_EXCEPTION_CAUSED_BY_CERTIFICATE_EXCEPTION,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory
+ .STORAGE_EXCEPTION_SSL_HANDSHAKE_EXCEPTION_CAUSED_BY_CERTIFICATE_EXCEPTION,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_0_CONNECTION_CLOSED_PREMATURELY,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_0_CONNECTION_CLOSED_PREMATURELY,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.DEFAULT_MORE_STRICT),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_0_CONNECTION_CLOSED_PREMATURELY_IO_CAUSE,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_0_CONNECTION_CLOSED_PREMATURELY_IO_CAUSE,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.DEFAULT_MORE_STRICT),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_0_INTERNAL_ERROR,
+ HandlerCategory.IDEMPOTENT,
+ ExpectRetry.YES,
+ Behavior.SAME),
+ new Case(
+ ThrowableCategory.STORAGE_EXCEPTION_0_INTERNAL_ERROR,
+ HandlerCategory.NONIDEMPOTENT,
+ ExpectRetry.NO,
+ Behavior.DEFAULT_MORE_STRICT))
+ .build();
+ }
+}