From ce125da4aab47afa8348f7422c7de19bf52615a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20K=C3=B6rber?= Date: Fri, 16 Dec 2016 01:18:19 +0100 Subject: [PATCH] Refactor HTTP response handling --- .../org/shredzone/acme4j/Authorization.java | 12 +-- .../org/shredzone/acme4j/Certificate.java | 19 ++-- .../org/shredzone/acme4j/Registration.java | 36 +++----- .../shredzone/acme4j/RegistrationBuilder.java | 6 +- .../shredzone/acme4j/challenge/Challenge.java | 18 ++-- .../acme4j/connector/Connection.java | 24 ++--- .../acme4j/connector/DefaultConnection.java | 89 +++++++++---------- .../acme4j/connector/ResourceIterator.java | 6 +- .../acme4j/provider/AbstractAcmeProvider.java | 6 +- .../shredzone/acme4j/AuthorizationTest.java | 35 ++++++-- .../org/shredzone/acme4j/CertificateTest.java | 39 ++++++-- .../acme4j/RegistrationBuilderTest.java | 10 ++- .../shredzone/acme4j/RegistrationTest.java | 76 ++++++++++++---- .../acme4j/challenge/ChallengeTest.java | 33 ++++++- .../connector/DefaultConnectionTest.java | 31 +++++-- .../acme4j/connector/DummyConnection.java | 14 +-- .../connector/ResourceIteratorTest.java | 9 +- .../provider/AbstractAcmeProviderTest.java | 3 +- .../org/shredzone/acme4j/util/TestUtils.java | 34 +++++++ 19 files changed, 323 insertions(+), 177 deletions(-) diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Authorization.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Authorization.java index a2b8f4c6..f26ca01b 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Authorization.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Authorization.java @@ -176,10 +176,8 @@ public class Authorization extends AcmeResource { public void update() throws AcmeException { LOG.debug("update"); try (Connection conn = getSession().provider().connect()) { - int rc = conn.sendRequest(getLocation(), getSession()); - if (rc != HttpURLConnection.HTTP_OK && rc != HttpURLConnection.HTTP_ACCEPTED) { - conn.throwAcmeException(); - } + conn.sendRequest(getLocation(), getSession()); + int rc = conn.accept(HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_ACCEPTED); Map result = conn.readJsonResponse(); unmarshalAuthorization(result); @@ -205,10 +203,8 @@ public class Authorization extends AcmeResource { claims.putResource("authz"); claims.put("status", "deactivated"); - int rc = conn.sendSignedRequest(getLocation(), claims, getSession()); - if (rc != HttpURLConnection.HTTP_OK && rc != HttpURLConnection.HTTP_ACCEPTED) { - conn.throwAcmeException(); - } + conn.sendSignedRequest(getLocation(), claims, getSession()); + conn.accept(HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_ACCEPTED); } } diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Certificate.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Certificate.java index fb66958f..0acbe2e0 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Certificate.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Certificate.java @@ -88,7 +88,8 @@ public class Certificate extends AcmeResource { if (cert == null) { LOG.debug("download"); try (Connection conn = getSession().provider().connect()) { - int rc = conn.sendRequest(getLocation(), getSession()); + conn.sendRequest(getLocation(), getSession()); + int rc = conn.accept(HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_ACCEPTED); if (rc == HttpURLConnection.HTTP_ACCEPTED) { Date retryAfter = conn.getRetryAfterHeader(); if (retryAfter != null) { @@ -98,10 +99,6 @@ public class Certificate extends AcmeResource { } } - if (rc != HttpURLConnection.HTTP_OK) { - conn.throwAcmeException(); - } - chainCertUri = conn.getLink("up"); cert = conn.readCertificate(); } @@ -135,10 +132,8 @@ public class Certificate extends AcmeResource { URI link = chainCertUri; while (link != null && certChain.size() < MAX_CHAIN_LENGTH) { try (Connection conn = getSession().provider().connect()) { - int rc = conn.sendRequest(chainCertUri, getSession()); - if (rc != HttpURLConnection.HTTP_OK) { - conn.throwAcmeException(); - } + conn.sendRequest(chainCertUri, getSession()); + conn.accept(HttpURLConnection.HTTP_OK); certChain.add(conn.readCertificate()); link = conn.getLink("up"); @@ -188,10 +183,8 @@ public class Certificate extends AcmeResource { claims.put("reason", reason.getReasonCode()); } - int rc = conn.sendSignedRequest(resUri, claims, getSession()); - if (rc != HttpURLConnection.HTTP_OK) { - conn.throwAcmeException(); - } + conn.sendSignedRequest(resUri, claims, getSession()); + conn.accept(HttpURLConnection.HTTP_OK); } catch (CertificateEncodingException ex) { throw new AcmeProtocolException("Invalid certificate", ex); } diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Registration.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Registration.java index 1479dcd0..89873ba9 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Registration.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Registration.java @@ -158,10 +158,8 @@ public class Registration extends AcmeResource { ClaimBuilder claims = new ClaimBuilder(); claims.putResource("reg"); - int rc = conn.sendSignedRequest(getLocation(), claims, getSession()); - if (rc != HttpURLConnection.HTTP_CREATED && rc != HttpURLConnection.HTTP_ACCEPTED) { - conn.throwAcmeException(); - } + conn.sendSignedRequest(getLocation(), claims, getSession()); + conn.accept(HttpURLConnection.HTTP_CREATED, HttpURLConnection.HTTP_ACCEPTED); Map json = conn.readJsonResponse(); unmarshal(json, conn); @@ -190,10 +188,8 @@ public class Registration extends AcmeResource { .put("type", "dns") .put("value", DomainUtils.toAce(domain)); - int rc = conn.sendSignedRequest(getSession().resourceUri(Resource.NEW_AUTHZ), claims, getSession()); - if (rc != HttpURLConnection.HTTP_CREATED) { - conn.throwAcmeException(); - } + conn.sendSignedRequest(getSession().resourceUri(Resource.NEW_AUTHZ), claims, getSession()); + conn.accept(HttpURLConnection.HTTP_CREATED); Map json = conn.readJsonResponse(); @@ -249,10 +245,8 @@ public class Registration extends AcmeResource { claims.put("notAfter", notAfter); } - int rc = conn.sendSignedRequest(getSession().resourceUri(Resource.NEW_CERT), claims, getSession()); - if (rc != HttpURLConnection.HTTP_CREATED && rc != HttpURLConnection.HTTP_ACCEPTED) { - conn.throwAcmeException(); - } + conn.sendSignedRequest(getSession().resourceUri(Resource.NEW_CERT), claims, getSession()); + int rc = conn.accept(HttpURLConnection.HTTP_CREATED, HttpURLConnection.HTTP_ACCEPTED); X509Certificate cert = null; if (rc == HttpURLConnection.HTTP_CREATED) { @@ -307,10 +301,8 @@ public class Registration extends AcmeResource { outerClaim.put("signature", innerJws.getEncodedSignature()); outerClaim.put("payload", innerJws.getEncodedPayload()); - int rc = conn.sendSignedRequest(keyChangeUri, outerClaim, getSession()); - if (rc != HttpURLConnection.HTTP_OK) { - conn.throwAcmeException(); - } + conn.sendSignedRequest(keyChangeUri, outerClaim, getSession()); + conn.accept(HttpURLConnection.HTTP_OK); getSession().setKeyPair(newKeyPair); } catch (JoseException ex) { @@ -331,10 +323,8 @@ public class Registration extends AcmeResource { claims.putResource("reg"); claims.put("status", "deactivated"); - int rc = conn.sendSignedRequest(getLocation(), claims, getSession()); - if (rc != HttpURLConnection.HTTP_OK && rc != HttpURLConnection.HTTP_ACCEPTED) { - conn.throwAcmeException(); - } + conn.sendSignedRequest(getLocation(), claims, getSession()); + conn.accept(HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_ACCEPTED); } } @@ -498,10 +488,8 @@ public class Registration extends AcmeResource { claims.put("agreement", editAgreement); } - int rc = conn.sendSignedRequest(getLocation(), claims, getSession()); - if (rc != HttpURLConnection.HTTP_ACCEPTED) { - conn.throwAcmeException(); - } + conn.sendSignedRequest(getLocation(), claims, getSession()); + conn.accept(HttpURLConnection.HTTP_ACCEPTED); Map json = conn.readJsonResponse(); unmarshal(json, conn); diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/RegistrationBuilder.java b/acme4j-client/src/main/java/org/shredzone/acme4j/RegistrationBuilder.java index 5143a85c..e64beb75 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/RegistrationBuilder.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/RegistrationBuilder.java @@ -81,10 +81,8 @@ public class RegistrationBuilder { claims.put("contact", contacts); } - int rc = conn.sendSignedRequest(session.resourceUri(Resource.NEW_REG), claims, session); - if (rc != HttpURLConnection.HTTP_CREATED) { - conn.throwAcmeException(); - } + conn.sendSignedRequest(session.resourceUri(Resource.NEW_REG), claims, session); + conn.accept(HttpURLConnection.HTTP_CREATED); URI location = conn.getLocation(); URI tos = conn.getLink("terms-of-service"); diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Challenge.java b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Challenge.java index cef8cdc6..2672b203 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Challenge.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Challenge.java @@ -76,10 +76,8 @@ public class Challenge extends AcmeResource { LOG.debug("bind"); try (Connection conn = session.provider().connect()) { - int rc = conn.sendRequest(location, session); - if (rc != HttpURLConnection.HTTP_ACCEPTED) { - conn.throwAcmeException(); - } + conn.sendRequest(location, session); + conn.accept(HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_ACCEPTED); Map json = conn.readJsonResponse(); if (!(json.containsKey("type"))) { @@ -211,10 +209,8 @@ public class Challenge extends AcmeResource { claims.putResource("challenge"); respond(claims); - int rc = conn.sendSignedRequest(getLocation(), claims, getSession()); - if (rc != HttpURLConnection.HTTP_OK && rc != HttpURLConnection.HTTP_ACCEPTED) { - conn.throwAcmeException(); - } + conn.sendSignedRequest(getLocation(), claims, getSession()); + conn.accept(HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_ACCEPTED); unmarshall(conn.readJsonResponse()); } @@ -233,10 +229,8 @@ public class Challenge extends AcmeResource { public void update() throws AcmeException { LOG.debug("update"); try (Connection conn = getSession().provider().connect()) { - int rc = conn.sendRequest(getLocation(), getSession()); - if (rc != HttpURLConnection.HTTP_OK && rc != HttpURLConnection.HTTP_ACCEPTED) { - conn.throwAcmeException(); - } + conn.sendRequest(getLocation(), getSession()); + int rc = conn.accept(HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_ACCEPTED); unmarshall(conn.readJsonResponse()); diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/Connection.java b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/Connection.java index 5ac1f487..c5151306 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/Connection.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/Connection.java @@ -21,7 +21,6 @@ import java.util.Map; import org.shredzone.acme4j.Session; import org.shredzone.acme4j.exception.AcmeException; -import org.shredzone.acme4j.exception.AcmeServerException; import org.shredzone.acme4j.util.ClaimBuilder; /** @@ -36,9 +35,8 @@ public interface Connection extends AutoCloseable { * {@link URI} to send the request to. * @param session * {@link Session} instance to be used for tracking - * @return HTTP response code */ - int sendRequest(URI uri, Session session) throws AcmeException; + void sendRequest(URI uri, Session session) throws AcmeException; /** * Sends a signed POST request. @@ -49,9 +47,18 @@ public interface Connection extends AutoCloseable { * {@link ClaimBuilder} containing claims. Must not be {@code null}. * @param session * {@link Session} instance to be used for signing and tracking - * @return HTTP response code */ - int sendSignedRequest(URI uri, ClaimBuilder claims, Session session) throws AcmeException; + void sendSignedRequest(URI uri, ClaimBuilder claims, Session session) throws AcmeException; + + /** + * Checks if the HTTP response status is in the given list of acceptable HTTP states, + * otherwise raises an {@link AcmeException} matching the error. + * + * @param httpStatus + * Acceptable HTTP states + * @return Actual HTTP status that was accepted + */ + int accept(int... httpStatus) throws AcmeException; /** * Reads a server response as JSON data. @@ -114,13 +121,6 @@ public interface Connection extends AutoCloseable { */ Date getRetryAfterHeader(); - /** - * Handles a problem by throwing an exception. If a JSON problem was returned, an - * {@link AcmeServerException} will be thrown. Otherwise a generic - * {@link AcmeException} is thrown. - */ - void throwAcmeException() throws AcmeException; - /** * Closes the {@link Connection}, releasing all resources. */ diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/DefaultConnection.java b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/DefaultConnection.java index c4737ff1..76c21c77 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/DefaultConnection.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/DefaultConnection.java @@ -79,7 +79,7 @@ public class DefaultConnection implements Connection { } @Override - public int sendRequest(URI uri, Session session) throws AcmeException { + public void sendRequest(URI uri, Session session) throws AcmeException { if (uri == null) { throw new NullPointerException("uri must not be null"); } @@ -100,15 +100,13 @@ public class DefaultConnection implements Connection { conn.connect(); logHeaders(); - - return conn.getResponseCode(); } catch (IOException ex) { throw new AcmeNetworkException(ex); } } @Override - public int sendSignedRequest(URI uri, ClaimBuilder claims, Session session) throws AcmeException { + public void sendSignedRequest(URI uri, ClaimBuilder claims, Session session) throws AcmeException { if (uri == null) { throw new NullPointerException("uri must not be null"); } @@ -168,8 +166,6 @@ public class DefaultConnection implements Connection { logHeaders(); updateSession(session); - - return conn.getResponseCode(); } catch (IOException ex) { throw new AcmeNetworkException(ex); } catch (JoseException ex) { @@ -177,6 +173,29 @@ public class DefaultConnection implements Connection { } } + @Override + public int accept(int... httpStatus) throws AcmeException { + assertConnectionIsOpen(); + + try { + int rc = conn.getResponseCode(); + for (int s : httpStatus) { + if (s == rc) { + return rc; + } + } + + if (!"application/problem+json".equals(conn.getHeaderField("Content-Type"))) { + throw new AcmeException("HTTP " + rc + ": " + conn.getResponseMessage()); + } + + Map map = readJsonResponse(); + throw createAcmeException(rc, map); + } catch (IOException ex) { + throw new AcmeNetworkException(ex); + } + } + @Override public Map readJsonResponse() throws AcmeException { assertConnectionIsOpen(); @@ -334,15 +353,16 @@ public class DefaultConnection implements Connection { } @Override - public void throwAcmeException() throws AcmeException { - assertConnectionIsOpen(); - - if (!"application/problem+json".equals(conn.getHeaderField("Content-Type"))) { - throw new AcmeException("HTTP " + getResponseCode() + ": " + getResponseMessage()); - } - - Map map = readJsonResponse(); + public void close() { + conn = null; + } + /** + * Handles a problem by throwing an exception. If a JSON problem was returned, an + * {@link AcmeServerException} will be thrown. Otherwise a generic + * {@link AcmeException} is thrown. + */ + private AcmeException createAcmeException(int rc, Map map) { String type = (String) map.get("type"); String detail = (String) map.get("detail"); @@ -350,41 +370,36 @@ public class DefaultConnection implements Connection { detail = "general problem"; } - if (getResponseCode() == HttpURLConnection.HTTP_CONFLICT) { - throw new AcmeConflictException(detail, getLocation()); + if (rc == HttpURLConnection.HTTP_CONFLICT) { + return new AcmeConflictException(detail, getLocation()); } if (type == null) { - throw new AcmeException(detail); + return new AcmeException(detail); } switch (type) { case ACME_ERROR_PREFIX + "unauthorized": case ACME_ERROR_PREFIX_DEPRECATED + "unauthorized": - throw new AcmeUnauthorizedException(type, detail); + return new AcmeUnauthorizedException(type, detail); case ACME_ERROR_PREFIX + "agreementRequired": case ACME_ERROR_PREFIX_DEPRECATED + "agreementRequired": String instance = (String) map.get("instance"); - throw new AcmeAgreementRequiredException( + return new AcmeAgreementRequiredException( type, detail, getLink("terms-of-service"), instance != null ? resolveRelative(instance) : null); case ACME_ERROR_PREFIX + "rateLimited": case ACME_ERROR_PREFIX_DEPRECATED + "rateLimited": - throw new AcmeRateLimitExceededException( + return new AcmeRateLimitExceededException( type, detail, getRetryAfterHeader(), getLinks("rate-limit")); default: - throw new AcmeServerException(type, detail); + return new AcmeServerException(type, detail); } } - @Override - public void close() { - conn = null; - } - /** * Asserts that the connection is currently open. Throws an exception if not. */ @@ -403,28 +418,6 @@ public class DefaultConnection implements Connection { } } - /** - * Returns the last response code. - */ - private int getResponseCode() throws AcmeException { - try { - return conn.getResponseCode(); - } catch (IOException ex) { - throw new AcmeNetworkException(ex); - } - } - - /** - * Returns the last response message. - */ - private String getResponseMessage() throws AcmeException { - try { - return conn.getResponseMessage(); - } catch (IOException ex) { - throw new AcmeNetworkException(ex); - } - } - /** * Log all HTTP headers in debug mode. */ diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/ResourceIterator.java b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/ResourceIterator.java index b1c33ef5..6123a55b 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/ResourceIterator.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/ResourceIterator.java @@ -144,10 +144,8 @@ public abstract class ResourceIterator implements Iterat */ private void readAndQueue() throws AcmeException { try (Connection conn = session.provider().connect()) { - int rc = conn.sendRequest(nextUri, session); - if (rc != HttpURLConnection.HTTP_OK) { - conn.throwAcmeException(); - } + conn.sendRequest(nextUri, session); + conn.accept(HttpURLConnection.HTTP_OK); Map json = conn.readJsonResponse(); fillUriList(json); diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/AbstractAcmeProvider.java b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/AbstractAcmeProvider.java index 55e764b7..e3bebd4c 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/AbstractAcmeProvider.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/AbstractAcmeProvider.java @@ -45,10 +45,8 @@ public abstract class AbstractAcmeProvider implements AcmeProvider { @Override public Map directory(Session session, URI serverUri) throws AcmeException { try (Connection conn = connect()) { - int rc = conn.sendRequest(resolve(serverUri), session); - if (rc != HttpURLConnection.HTTP_OK) { - conn.throwAcmeException(); - } + conn.sendRequest(resolve(serverUri), session); + conn.accept(HttpURLConnection.HTTP_OK); // use nonce header if there is one, saves a HEAD request... conn.updateSession(session); diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/AuthorizationTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/AuthorizationTest.java index 592be0bb..ff2ab6cc 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/AuthorizationTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/AuthorizationTest.java @@ -15,7 +15,7 @@ package org.shredzone.acme4j; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; -import static org.shredzone.acme4j.util.TestUtils.getJsonAsMap; +import static org.shredzone.acme4j.util.TestUtils.*; import java.io.IOException; import java.net.HttpURLConnection; @@ -30,6 +30,7 @@ import org.shredzone.acme4j.challenge.Challenge; import org.shredzone.acme4j.challenge.Dns01Challenge; import org.shredzone.acme4j.challenge.Http01Challenge; import org.shredzone.acme4j.challenge.TlsSni02Challenge; +import org.shredzone.acme4j.exception.AcmeException; import org.shredzone.acme4j.exception.AcmeRetryAfterException; import org.shredzone.acme4j.provider.TestableConnectionProvider; import org.shredzone.acme4j.util.ClaimBuilder; @@ -119,8 +120,14 @@ public class AuthorizationTest { public void testUpdate() throws Exception { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public int sendRequest(URI uri, Session session) { + public void sendRequest(URI uri, Session session) { assertThat(uri, is(locationUri)); + } + + @Override + public int accept(int... httpStatus) throws AcmeException { + assertThat(httpStatus, isIntArrayContainingInAnyOrder( + HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_ACCEPTED)); return HttpURLConnection.HTTP_OK; } @@ -166,9 +173,15 @@ public class AuthorizationTest { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public int sendRequest(URI uri, Session session) { + public void sendRequest(URI uri, Session session) { requestWasSent.set(true); assertThat(uri, is(locationUri)); + } + + @Override + public int accept(int... httpStatus) throws AcmeException { + assertThat(httpStatus, isIntArrayContainingInAnyOrder( + HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_ACCEPTED)); return HttpURLConnection.HTTP_OK; } @@ -209,8 +222,14 @@ public class AuthorizationTest { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public int sendRequest(URI uri, Session session) { + public void sendRequest(URI uri, Session session) { assertThat(uri, is(locationUri)); + } + + @Override + public int accept(int... httpStatus) throws AcmeException { + assertThat(httpStatus, isIntArrayContainingInAnyOrder( + HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_ACCEPTED)); return HttpURLConnection.HTTP_ACCEPTED; } @@ -265,12 +284,18 @@ public class AuthorizationTest { public void testDeactivate() throws Exception { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public int sendSignedRequest(URI uri, ClaimBuilder claims, Session session) { + public void sendSignedRequest(URI uri, ClaimBuilder claims, Session session) { Map claimMap = claims.toMap(); assertThat(claimMap.get("resource"), is((Object) "authz")); assertThat(claimMap.get("status"), is((Object) "deactivated")); assertThat(uri, is(locationUri)); assertThat(session, is(notNullValue())); + } + + @Override + public int accept(int... httpStatus) throws AcmeException { + assertThat(httpStatus, isIntArrayContainingInAnyOrder( + HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_ACCEPTED)); return HttpURLConnection.HTTP_ACCEPTED; } }; diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/CertificateTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/CertificateTest.java index b7f37fcf..b39a9c7d 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/CertificateTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/CertificateTest.java @@ -15,7 +15,7 @@ package org.shredzone.acme4j; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; -import static org.shredzone.acme4j.util.TestUtils.getJson; +import static org.shredzone.acme4j.util.TestUtils.*; import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs; import java.io.IOException; @@ -52,9 +52,22 @@ public class CertificateTest { private boolean isLocationUri; @Override - public int sendRequest(URI uri, Session session) { + public void sendRequest(URI uri, Session session) { assertThat(uri, isOneOf(locationUri, chainUri)); isLocationUri = uri.equals(locationUri); + } + + @Override + public int accept(int... httpStatus) throws AcmeException { + if (isLocationUri) { + // The leaf certificate, might be asynchronous + assertThat(httpStatus, isIntArrayContainingInAnyOrder( + HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_ACCEPTED)); + } else { + // The root certificate chain, always OK + assertThat(httpStatus, isIntArrayContainingInAnyOrder( + HttpURLConnection.HTTP_OK)); + } return HttpURLConnection.HTTP_OK; } @@ -93,8 +106,14 @@ public class CertificateTest { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public int sendRequest(URI uri, Session session) { + public void sendRequest(URI uri, Session session) { assertThat(uri, is(locationUri)); + } + + @Override + public int accept(int... httpStatus) throws AcmeException { + assertThat(httpStatus, isIntArrayContainingInAnyOrder( + HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_ACCEPTED)); return HttpURLConnection.HTTP_ACCEPTED; } @@ -125,10 +144,15 @@ public class CertificateTest { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public int sendSignedRequest(URI uri, ClaimBuilder claims, Session session) { + public void sendSignedRequest(URI uri, ClaimBuilder claims, Session session) { assertThat(uri, is(resourceUri)); assertThat(claims.toString(), sameJSONAs(getJson("revokeCertificateRequest"))); assertThat(session, is(notNullValue())); + } + + @Override + public int accept(int... httpStatus) throws AcmeException { + assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK)); return HttpURLConnection.HTTP_OK; } }; @@ -150,10 +174,15 @@ public class CertificateTest { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public int sendSignedRequest(URI uri, ClaimBuilder claims, Session session) { + public void sendSignedRequest(URI uri, ClaimBuilder claims, Session session) { assertThat(uri, is(resourceUri)); assertThat(claims.toString(), sameJSONAs(getJson("revokeCertificateWithReasonRequest"))); assertThat(session, is(notNullValue())); + } + + @Override + public int accept(int... httpStatus) throws AcmeException { + assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK)); return HttpURLConnection.HTTP_OK; } }; diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/RegistrationBuilderTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/RegistrationBuilderTest.java index 219ba6e8..4a2d79e9 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/RegistrationBuilderTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/RegistrationBuilderTest.java @@ -15,7 +15,7 @@ package org.shredzone.acme4j; import static org.hamcrest.Matchers.*; import static org.junit.Assert.assertThat; -import static org.shredzone.acme4j.util.TestUtils.getJson; +import static org.shredzone.acme4j.util.TestUtils.*; import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs; import java.net.HttpURLConnection; @@ -23,6 +23,7 @@ import java.net.URI; import org.junit.Test; import org.shredzone.acme4j.connector.Resource; +import org.shredzone.acme4j.exception.AcmeException; import org.shredzone.acme4j.provider.TestableConnectionProvider; import org.shredzone.acme4j.util.ClaimBuilder; @@ -42,10 +43,15 @@ public class RegistrationBuilderTest { public void testRegistration() throws Exception { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public int sendSignedRequest(URI uri, ClaimBuilder claims, Session session) { + public void sendSignedRequest(URI uri, ClaimBuilder claims, Session session) { assertThat(uri, is(resourceUri)); assertThat(claims.toString(), sameJSONAs(getJson("newRegistration"))); assertThat(session, is(notNullValue())); + } + + @Override + public int accept(int... httpStatus) throws AcmeException { + assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_CREATED)); return HttpURLConnection.HTTP_CREATED; } diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/RegistrationTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/RegistrationTest.java index 09b9f8b6..d919d953 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/RegistrationTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/RegistrationTest.java @@ -62,33 +62,42 @@ public class RegistrationTest { public void testUpdateRegistration() throws AcmeException, IOException { TestableConnectionProvider provider = new TestableConnectionProvider() { private Map jsonResponse; + private Integer response; @Override - public int sendSignedRequest(URI uri, ClaimBuilder claims, Session session) { + public void sendSignedRequest(URI uri, ClaimBuilder claims, Session session) { assertThat(uri, is(locationUri)); assertThat(claims.toString(), sameJSONAs(getJson("updateRegistration"))); assertThat(session, is(notNullValue())); jsonResponse = getJsonAsMap("updateRegistrationResponse"); - return HttpURLConnection.HTTP_ACCEPTED; + response = HttpURLConnection.HTTP_ACCEPTED; } @Override - public int sendRequest(URI uri, Session session) { + public void sendRequest(URI uri, Session session) { if (URI.create("https://example.com/acme/reg/1/authz").equals(uri)) { jsonResponse = new HashMap<>(); jsonResponse.put("authorizations", Arrays.asList("https://example.com/acme/auth/1")); - return HttpURLConnection.HTTP_OK; + response = HttpURLConnection.HTTP_OK; + return; } if (URI.create("https://example.com/acme/reg/1/cert").equals(uri)) { jsonResponse = new HashMap<>(); jsonResponse.put("certificates", Arrays.asList("https://example.com/acme/cert/1")); - return HttpURLConnection.HTTP_OK; + response = HttpURLConnection.HTTP_OK; + return; } - return HttpURLConnection.HTTP_NOT_FOUND; + response = HttpURLConnection.HTTP_NOT_FOUND; + } + + @Override + public int accept(int... httpStatus) throws AcmeException { + assertThat(response, not(nullValue())); + return response; } @Override @@ -144,9 +153,15 @@ public class RegistrationTest { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public int sendSignedRequest(URI uri, ClaimBuilder claims, Session session) { + public void sendSignedRequest(URI uri, ClaimBuilder claims, Session session) { requestWasSent.set(true); assertThat(uri, is(locationUri)); + } + + @Override + public int accept(int... httpStatus) throws AcmeException { + assertThat(httpStatus, isIntArrayContainingInAnyOrder( + HttpURLConnection.HTTP_CREATED, HttpURLConnection.HTTP_ACCEPTED)); return HttpURLConnection.HTTP_ACCEPTED; } @@ -192,10 +207,15 @@ public class RegistrationTest { public void testAuthorizeDomain() throws Exception { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public int sendSignedRequest(URI uri, ClaimBuilder claims, Session session) { + public void sendSignedRequest(URI uri, ClaimBuilder claims, Session session) { assertThat(uri, is(resourceUri)); assertThat(claims.toString(), sameJSONAs(getJson("newAuthorizationRequest"))); assertThat(session, is(notNullValue())); + } + + @Override + public int accept(int... httpStatus) throws AcmeException { + assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_CREATED)); return HttpURLConnection.HTTP_CREATED; } @@ -250,16 +270,21 @@ public class RegistrationTest { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public int sendRequest(URI uri, Session session) { + public void sendRequest(URI uri, Session session) { fail("Attempted to download the certificate. Should be downloaded already!"); - return HttpURLConnection.HTTP_OK; } @Override - public int sendSignedRequest(URI uri, ClaimBuilder claims, Session session) { + public void sendSignedRequest(URI uri, ClaimBuilder claims, Session session) { assertThat(uri, is(resourceUri)); assertThat(claims.toString(), sameJSONAs(getJson("requestCertificateRequestWithDate"))); assertThat(session, is(notNullValue())); + } + + @Override + public int accept(int... httpStatus) throws AcmeException { + assertThat(httpStatus, isIntArrayContainingInAnyOrder( + HttpURLConnection.HTTP_CREATED, HttpURLConnection.HTTP_ACCEPTED)); return HttpURLConnection.HTTP_CREATED; } @@ -309,10 +334,16 @@ public class RegistrationTest { public void testRequestCertificateAsync() throws AcmeException, IOException { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public int sendSignedRequest(URI uri, ClaimBuilder claims, Session session) { + public void sendSignedRequest(URI uri, ClaimBuilder claims, Session session) { assertThat(uri, is(resourceUri)); assertThat(claims.toString(), sameJSONAs(getJson("requestCertificateRequest"))); assertThat(session, is(notNullValue())); + } + + @Override + public int accept(int... httpStatus) throws AcmeException { + assertThat(httpStatus, isIntArrayContainingInAnyOrder( + HttpURLConnection.HTTP_CREATED, HttpURLConnection.HTTP_ACCEPTED)); return HttpURLConnection.HTTP_ACCEPTED; } @@ -353,7 +384,7 @@ public class RegistrationTest { final TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public int sendSignedRequest(URI uri, ClaimBuilder payload, Session session) { + public void sendSignedRequest(URI uri, ClaimBuilder payload, Session session) { try { assertThat(uri, is(locationUri)); assertThat(session, is(notNullValue())); @@ -386,7 +417,11 @@ public class RegistrationTest { } catch (JoseException ex) { fail("decoding inner payload failed"); } + } + @Override + public int accept(int... httpStatus) throws AcmeException { + assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK)); return HttpURLConnection.HTTP_OK; } @@ -434,12 +469,18 @@ public class RegistrationTest { public void testDeactivate() throws Exception { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public int sendSignedRequest(URI uri, ClaimBuilder claims, Session session) { + public void sendSignedRequest(URI uri, ClaimBuilder claims, Session session) { Map claimMap = claims.toMap(); assertThat(claimMap.get("resource"), is((Object) "reg")); assertThat(claimMap.get("status"), is((Object) "deactivated")); assertThat(uri, is(locationUri)); assertThat(session, is(notNullValue())); + } + + @Override + public int accept(int... httpStatus) throws AcmeException { + assertThat(httpStatus, isIntArrayContainingInAnyOrder( + HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_ACCEPTED)); return HttpURLConnection.HTTP_ACCEPTED; } }; @@ -459,10 +500,15 @@ public class RegistrationTest { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public int sendSignedRequest(URI uri, ClaimBuilder claims, Session session) { + public void sendSignedRequest(URI uri, ClaimBuilder claims, Session session) { assertThat(uri, is(locationUri)); assertThat(claims.toString(), sameJSONAs(getJson("modifyRegistration"))); assertThat(session, is(notNullValue())); + } + + @Override + public int accept(int... httpStatus) throws AcmeException { + assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_ACCEPTED)); return HttpURLConnection.HTTP_ACCEPTED; } diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/ChallengeTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/ChallengeTest.java index 92e53dfd..478f6ba1 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/ChallengeTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/ChallengeTest.java @@ -35,6 +35,7 @@ import org.junit.Before; import org.junit.Test; import org.shredzone.acme4j.Session; import org.shredzone.acme4j.Status; +import org.shredzone.acme4j.exception.AcmeException; import org.shredzone.acme4j.exception.AcmeProtocolException; import org.shredzone.acme4j.exception.AcmeRetryAfterException; import org.shredzone.acme4j.provider.TestableConnectionProvider; @@ -62,8 +63,14 @@ public class ChallengeTest { public void testChallenge() throws Exception { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public int sendRequest(URI uri, Session session) { + public void sendRequest(URI uri, Session session) { assertThat(uri, is(locationUri)); + } + + @Override + public int accept(int... httpStatus) throws AcmeException { + assertThat(httpStatus, isIntArrayContainingInAnyOrder( + HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_ACCEPTED)); return HttpURLConnection.HTTP_ACCEPTED; } @@ -142,10 +149,16 @@ public class ChallengeTest { public void testTrigger() throws Exception { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public int sendSignedRequest(URI uri, ClaimBuilder claims, Session session) { + public void sendSignedRequest(URI uri, ClaimBuilder claims, Session session) { assertThat(uri, is(resourceUri)); assertThat(claims.toString(), sameJSONAs(getJson("triggerHttpChallengeRequest"))); assertThat(session, is(notNullValue())); + } + + @Override + public int accept(int... httpStatus) throws AcmeException { + assertThat(httpStatus, isIntArrayContainingInAnyOrder( + HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_ACCEPTED)); return HttpURLConnection.HTTP_ACCEPTED; } @@ -175,8 +188,14 @@ public class ChallengeTest { public void testUpdate() throws Exception { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public int sendRequest(URI uri, Session session) { + public void sendRequest(URI uri, Session session) { assertThat(uri, is(locationUri)); + } + + @Override + public int accept(int... httpStatus) throws AcmeException { + assertThat(httpStatus, isIntArrayContainingInAnyOrder( + HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_ACCEPTED)); return HttpURLConnection.HTTP_OK; } @@ -208,8 +227,14 @@ public class ChallengeTest { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public int sendRequest(URI uri, Session session) { + public void sendRequest(URI uri, Session session) { assertThat(uri, is(locationUri)); + } + + @Override + public int accept(int... httpStatus) throws AcmeException { + assertThat(httpStatus, isIntArrayContainingInAnyOrder( + HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_ACCEPTED)); return HttpURLConnection.HTTP_ACCEPTED; } diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/connector/DefaultConnectionTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/connector/DefaultConnectionTest.java index fd4f2cda..11040356 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/connector/DefaultConnectionTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/connector/DefaultConnectionTest.java @@ -308,7 +308,24 @@ public class DefaultConnectionTest { * Test if an {@link AcmeServerException} is thrown on an acme problem. */ @Test - public void testThrowException() throws Exception { + public void testAccept() throws Exception { + when(mockUrlConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK); + + try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) { + conn.conn = mockUrlConnection; + int rc = conn.accept(HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_ACCEPTED); + assertThat(rc, is(HttpURLConnection.HTTP_OK)); + } + + verify(mockUrlConnection).getResponseCode(); + verifyNoMoreInteractions(mockUrlConnection); + } + + /** + * Test if an {@link AcmeServerException} is thrown on an acme problem. + */ + @Test + public void testAcceptThrowsException() throws Exception { String jsonData = "{\"type\":\"urn:ietf:params:acme:error:unauthorized\",\"detail\":\"Invalid response: 404\"}"; when(mockUrlConnection.getHeaderField("Content-Type")).thenReturn("application/problem+json"); @@ -317,7 +334,7 @@ public class DefaultConnectionTest { try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) { conn.conn = mockUrlConnection; - conn.throwAcmeException(); + conn.accept(HttpURLConnection.HTTP_OK); fail("Expected to fail"); } catch (AcmeServerException ex) { assertThat(ex.getType(), is("urn:ietf:params:acme:error:unauthorized")); @@ -337,7 +354,7 @@ public class DefaultConnectionTest { * Test if an {@link AcmeServerException} is thrown on another problem. */ @Test - public void testOtherThrowException() throws IOException { + public void testAcceptThrowsOtherException() throws IOException { when(mockUrlConnection.getHeaderField("Content-Type")) .thenReturn("application/problem+json"); when(mockUrlConnection.getResponseCode()) @@ -353,7 +370,7 @@ public class DefaultConnectionTest { }; }) { conn.conn = mockUrlConnection; - conn.throwAcmeException(); + conn.accept(HttpURLConnection.HTTP_OK); fail("Expected to fail"); } catch (AcmeServerException ex) { assertThat(ex.getType(), is("urn:zombie:error:apocalypse")); @@ -372,7 +389,7 @@ public class DefaultConnectionTest { * Test if an {@link AcmeException} is thrown if there is no error type. */ @Test - public void testNoTypeThrowException() throws IOException { + public void testAcceptThrowsNoTypeException() throws IOException { when(mockUrlConnection.getHeaderField("Content-Type")) .thenReturn("application/problem+json"); when(mockUrlConnection.getResponseCode()) @@ -385,7 +402,7 @@ public class DefaultConnectionTest { }; }) { conn.conn = mockUrlConnection; - conn.throwAcmeException(); + conn.accept(HttpURLConnection.HTTP_OK); fail("Expected to fail"); } catch (AcmeNetworkException ex) { fail("Did not expect an AcmeNetworkException"); @@ -412,7 +429,6 @@ public class DefaultConnectionTest { verify(mockUrlConnection).setRequestProperty("Accept-Language", "ja-JP"); verify(mockUrlConnection).setDoOutput(false); verify(mockUrlConnection).connect(); - verify(mockUrlConnection).getResponseCode(); verify(mockUrlConnection, atLeast(0)).getHeaderFields(); verifyNoMoreInteractions(mockUrlConnection); } @@ -457,7 +473,6 @@ public class DefaultConnectionTest { verify(mockUrlConnection).setDoOutput(true); verify(mockUrlConnection).setFixedLengthStreamingMode(outputStream.toByteArray().length); verify(mockUrlConnection).getOutputStream(); - verify(mockUrlConnection).getResponseCode(); verify(mockUrlConnection, atLeast(0)).getHeaderFields(); verifyNoMoreInteractions(mockUrlConnection); diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/connector/DummyConnection.java b/acme4j-client/src/test/java/org/shredzone/acme4j/connector/DummyConnection.java index 4bf5bdd5..26e3a238 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/connector/DummyConnection.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/connector/DummyConnection.java @@ -30,12 +30,17 @@ import org.shredzone.acme4j.util.ClaimBuilder; public class DummyConnection implements Connection { @Override - public int sendRequest(URI uri, Session session) { + public void sendRequest(URI uri, Session session) { throw new UnsupportedOperationException(); } @Override - public int sendSignedRequest(URI uri, ClaimBuilder claims, Session session) { + public void sendSignedRequest(URI uri, ClaimBuilder claims, Session session) { + throw new UnsupportedOperationException(); + } + + @Override + public int accept(int... httpStatus) throws AcmeException { throw new UnsupportedOperationException(); } @@ -74,11 +79,6 @@ public class DummyConnection implements Connection { throw new UnsupportedOperationException(); } - @Override - public void throwAcmeException() throws AcmeException { - throw new UnsupportedOperationException(); - } - @Override public void close() { // closing is always safe diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/connector/ResourceIteratorTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/connector/ResourceIteratorTest.java index 5fe5b9c3..07c07540 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/connector/ResourceIteratorTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/connector/ResourceIteratorTest.java @@ -15,6 +15,7 @@ package org.shredzone.acme4j.connector; import static org.hamcrest.Matchers.*; import static org.junit.Assert.assertThat; +import static org.shredzone.acme4j.util.TestUtils.isIntArrayContainingInAnyOrder; import java.io.IOException; import java.net.HttpURLConnection; @@ -31,6 +32,7 @@ import org.junit.Before; import org.junit.Test; import org.shredzone.acme4j.Authorization; import org.shredzone.acme4j.Session; +import org.shredzone.acme4j.exception.AcmeException; import org.shredzone.acme4j.exception.AcmeProtocolException; import org.shredzone.acme4j.provider.TestableConnectionProvider; import org.shredzone.acme4j.util.ClaimBuilder; @@ -133,9 +135,14 @@ public class ResourceIteratorTest { private int ix; @Override - public int sendRequest(URI uri, Session session) { + public void sendRequest(URI uri, Session session) { ix = pageURIs.indexOf(uri); assertThat(ix, is(greaterThanOrEqualTo(0))); + } + + @Override + public int accept(int... httpStatus) throws AcmeException { + assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK)); return HttpURLConnection.HTTP_OK; } diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/provider/AbstractAcmeProviderTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/provider/AbstractAcmeProviderTest.java index 6c3da5d4..dc589787 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/provider/AbstractAcmeProviderTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/provider/AbstractAcmeProviderTest.java @@ -83,7 +83,7 @@ public class AbstractAcmeProviderTest { final Connection connection = mock(Connection.class); final Session session = mock(Session.class); - when(connection.sendRequest(testResolvedUri, session)).thenReturn(HttpURLConnection.HTTP_OK); + when(connection.accept(any(Integer.class))).thenReturn(HttpURLConnection.HTTP_OK); when(connection.readJsonResponse()).thenReturn(TestUtils.getJsonAsMap("directory")); AbstractAcmeProvider provider = new AbstractAcmeProvider() { @@ -109,6 +109,7 @@ public class AbstractAcmeProviderTest { assertThat(JsonUtil.toJson(map), sameJSONAs(TestUtils.getJson("directory"))); verify(connection).sendRequest(testResolvedUri, session); + verify(connection).accept(any(Integer.class)); verify(connection).updateSession(any(Session.class)); verify(connection).readJsonResponse(); verify(connection).close(); diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/util/TestUtils.java b/acme4j-client/src/test/java/org/shredzone/acme4j/util/TestUtils.java index dc2e1793..10d9f469 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/util/TestUtils.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/util/TestUtils.java @@ -34,10 +34,14 @@ import java.security.spec.ECGenParameterSpec; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; +import java.util.Arrays; import java.util.Map; import java.util.ResourceBundle; import java.util.TreeMap; +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.hamcrest.Matcher; import org.jose4j.base64url.Base64Url; import org.jose4j.json.JsonUtil; import org.jose4j.jwk.JsonWebKey; @@ -224,6 +228,36 @@ public final class TestUtils { } } + /** + * Creates a matcher that matches an array of int primitives. The array must contain + * exactly all of the given values, in any order. + * + * @param values + * Values to test against + * @return {@link Matcher} + */ + public static Matcher isIntArrayContainingInAnyOrder(int... values) { + final int[] reference = values; + Arrays.sort(reference); + + return new BaseMatcher() { + @Override + public boolean matches(Object item) { + if (!(item instanceof int[])) { + return false; + } + int[] items = (int[]) item; + Arrays.sort(items); + return Arrays.equals(items, reference); + } + + @Override + public void describeTo(Description description) { + description.appendValue(Arrays.toString(reference)); + } + }; + } + /** * Generates a new keypair for unit tests, and return its N, E, KTY and THUMBPRINT * parameters to be set in the {@link TestUtils} class.