From 03e9623073cb0aacfeffd886a6f3d1779f4fb309 Mon Sep 17 00:00:00 2001 From: Liam Newman Date: Mon, 11 Nov 2019 13:38:42 -0800 Subject: [PATCH] Updates based on review feedback Created GHRateLimit.Record Add the four rate limit records to GHRateLimit Moved getLimt(), getRemaining(), and so on to point to core record for ease of use. Fixed update check for header to not replace existing with older when remaining count is lower. NOTE: Did not expose records other than core and did not resolve header update behavior to respect non-core records. --- .../java/org/kohsuke/github/GHRateLimit.java | 419 +++++++++++++----- src/main/java/org/kohsuke/github/GitHub.java | 52 ++- .../org/kohsuke/github/JsonRateLimit.java | 4 +- .../java/org/kohsuke/github/Requester.java | 6 +- .../org/kohsuke/github/GHRateLimitTest.java | 55 ++- .../org/kohsuke/github/GitHubStaticTest.java | 62 +++ ...-4e2fc33b-fb25-4dfc-9d56-34f9b4d707be.json | 10 +- ...-a1f82a96-500c-4462-ae7b-e0159afa8208.json | 10 +- ...-f22b1cea-3679-481d-8b95-459b2c47bf98.json | 10 +- ...-4e2fc33b-fb25-4dfc-9d56-34f9b4d707be.json | 29 -- ...-a1f82a96-500c-4462-ae7b-e0159afa8208.json | 29 -- ...-f22b1cea-3679-481d-8b95-459b2c47bf98.json | 29 -- ...-a460fd69-99f3-46c7-aeb1-888c34085d4a.json | 45 -- .../mappings/rate_limit-2-f22b1c.json | 41 -- .../mappings/rate_limit-3-a1f82a.json | 41 -- .../mappings/rate_limit-5-4e2fc3.json | 40 -- .../mappings/user-1-a460fd.json | 43 -- ...-4e2fc33b-fb25-4dfc-9d56-34f9b4d707be.json | 10 +- ...-a1f82a96-500c-4462-ae7b-e0159afa8208.json | 10 +- ...-f22b1cea-3679-481d-8b95-459b2c47bf98.json | 10 +- ...-4e2fc33b-fb25-4dfc-9d56-34f9b4d707be.json | 10 +- ...-a1f82a96-500c-4462-ae7b-e0159afa8208.json | 10 +- ...-f22b1cea-3679-481d-8b95-459b2c47bf98.json | 10 +- 23 files changed, 477 insertions(+), 508 deletions(-) delete mode 100644 src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/__files/rate_limit-4e2fc33b-fb25-4dfc-9d56-34f9b4d707be.json delete mode 100644 src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/__files/rate_limit-a1f82a96-500c-4462-ae7b-e0159afa8208.json delete mode 100644 src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/__files/rate_limit-f22b1cea-3679-481d-8b95-459b2c47bf98.json delete mode 100644 src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/__files/user-a460fd69-99f3-46c7-aeb1-888c34085d4a.json delete mode 100644 src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/mappings/rate_limit-2-f22b1c.json delete mode 100644 src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/mappings/rate_limit-3-a1f82a.json delete mode 100644 src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/mappings/rate_limit-5-4e2fc3.json delete mode 100644 src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/mappings/user-1-a460fd.json diff --git a/src/main/java/org/kohsuke/github/GHRateLimit.java b/src/main/java/org/kohsuke/github/GHRateLimit.java index d917bdfbd..c0b21da81 100644 --- a/src/main/java/org/kohsuke/github/GHRateLimit.java +++ b/src/main/java/org/kohsuke/github/GHRateLimit.java @@ -20,6 +20,7 @@ import static java.util.logging.Level.FINEST; * * @author Kohsuke Kawaguchi */ +@SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD", justification = "JSON API") public class GHRateLimit { /** @@ -47,147 +48,149 @@ public class GHRateLimit { @Deprecated public Date reset; - /** - * Remaining calls that can be made. - */ - private final int remainingCount; - /** - * Allotted API call per hour. - */ - private final int limitCount; - - /** - * The time at which the current rate limit window resets in UTC epoch seconds. - */ - private final long resetEpochSeconds; - - /** - * EpochSeconds time (UTC) at which this instance was created. - */ - private final long createdAtEpochSeconds = System.currentTimeMillis() / 1000; - - /** - * The calculated time at which the rate limit will reset. - * Recalculated if {@link #recalculateResetDate} is called. - */ @Nonnull - private Date resetDate; + private final Record core; - /** - * Gets a placeholder instance that can be used when we fail to get one from the server. - * - * @return a GHRateLimit - */ - public static GHRateLimit getPlaceholder() { - final long oneHour = 60L * 60L; - // This placeholder limit does not expire for a while - // This make it so that calling rateLimit() multiple times does not result in multiple request - GHRateLimit r = new GHRateLimit(1000000, 1000000, System.currentTimeMillis() / 1000L + oneHour); - return r; + @Nonnull + private final Record search; + + @Nonnull + private final Record graphql; + + @Nonnull + private final Record integrationManifest; + + static GHRateLimit Unknown() { + return new GHRateLimit(new UnknownLimitRecord(), new UnknownLimitRecord(), new UnknownLimitRecord(), new UnknownLimitRecord()); + } + + static GHRateLimit fromHeaderRecord(Record header) { + return new GHRateLimit(header, new UnknownLimitRecord(), new UnknownLimitRecord(), new UnknownLimitRecord()); } @JsonCreator - public GHRateLimit(@JsonProperty("limit") int limit, - @JsonProperty("remaining") int remaining, - @JsonProperty("reset")long resetEpochSeconds) { - this(limit, remaining, resetEpochSeconds, null); - } - - @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD", - justification = "Deprecated") - public GHRateLimit(int limit, int remaining, long resetEpochSeconds, String updatedAt) { - this.limitCount = limit; - this.remainingCount = remaining; - this.resetEpochSeconds = resetEpochSeconds; - this.resetDate = recalculateResetDate(updatedAt); + GHRateLimit(@Nonnull @JsonProperty("core") Record core, + @Nonnull @JsonProperty("search") Record search, + @Nonnull @JsonProperty("graphql") Record graphql, + @Nonnull @JsonProperty("integration_manifest") Record integrationManifest) { + this.core = core; + this.search = search; + this.graphql = graphql; + this.integrationManifest = integrationManifest; // Deprecated fields - this.remaining = remaining; - this.limit = limit; - this.reset = new Date(resetEpochSeconds); + this.remaining = core.getRemaining(); + this.limit = core.getLimit(); + this.reset = new Date(core.getResetEpochSeconds()); } - /** - * - * @param updatedAt a string date in RFC 1123 - * @return reset date based on the passed date - */ - Date recalculateResetDate(String updatedAt) { - long updatedAtEpochSeconds = createdAtEpochSeconds; - if (!StringUtils.isBlank(updatedAt)) { - try { - // Get the server date and reset data, will always return a time in GMT - updatedAtEpochSeconds = ZonedDateTime.parse(updatedAt, DateTimeFormatter.RFC_1123_DATE_TIME).toEpochSecond(); - } catch (DateTimeParseException e) { - if (LOGGER.isLoggable(FINEST)) { - LOGGER.log(FINEST, "Malformed Date header value " + updatedAt, e); - } - } - } - - // This may seem odd but it results in an accurate or slightly pessimistic reset date - // based on system time rather than on the system being in sync with the server - long calculatedSecondsUntilReset = resetEpochSeconds - updatedAtEpochSeconds; - return resetDate = new Date((createdAtEpochSeconds + calculatedSecondsUntilReset) * 1000); - } /** - * Gets the remaining number of requests allowed before this connection will be throttled. - * - * @return an integer - */ - public int getRemaining() { - return remainingCount; - } - - /** - * Gets the total number of API calls per hour allotted for this connection. - * - * @return an integer - */ - public int getLimit() { - return limitCount; - } - - /** - * Gets the time in epoch seconds when the rate limit will reset. - * - * @return a long - */ - public long getResetEpochSeconds() { - return resetEpochSeconds; - } - - /** - * Whether the rate limit reset date indicated by this instance is in the - * - * @return true if the rate limit reset date has passed. Otherwise false. - */ - public boolean isExpired() { - return getResetDate().getTime() < System.currentTimeMillis(); - } - - /** - * Returns the date at which the rate limit will reset. + * Returns the date at which the Core API rate limit will reset. * * @return the calculated date at which the rate limit has or will reset. */ @Nonnull public Date getResetDate() { - return new Date(resetDate.getTime()); + return getCore().getResetDate(); + } + + /** + * Gets the remaining number of Core APIs requests allowed before this connection will be throttled. + * + * @return an integer + * @since 1.100 + */ + public int getRemaining() { + return getCore().getRemaining(); + } + + /** + * Gets the total number of Core API calls per hour allotted for this connection. + * + * @return an integer + * @since 1.100 + */ + public int getLimit() { + return getCore().getLimit(); + } + + + /** + * Gets the time in epoch seconds when the Core API rate limit will reset. + * + * @return a long + * @since 1.100 + */ + public long getResetEpochSeconds() { + return getCore().getResetEpochSeconds(); + } + + /** + * Whether the rate limit reset date for this instance has passed. + * + * @return true if the rate limit reset date has passed. Otherwise false. + * @since 1.100 + */ + public boolean isExpired() { + return getCore().isExpired(); + } + + /** + * The core object provides your rate limit status for all non-search-related resources in the REST API. + * + * @return a rate limit record + * @since 1.100 + */ + @Nonnull + public Record getCore() { + return core; + } + + /** + * The search object provides your rate limit status for the Search API. + * TODO: integrate with header limit updating. Issue #605. + * + * @return a rate limit record + */ + @Nonnull + Record getSearch() { + return search; + } + + /** + * The graphql object provides your rate limit status for the GraphQL API. + * TODO: integrate with header limit updating. Issue #605. + * + * @return a rate limit record + */ + @Nonnull + Record getGraphQL() { + return graphql; + } + + /** + * The integration_manifest object provides your rate limit status for the GitHub App Manifest code conversion endpoint. + * TODO: integrate with header limit updating. Issue #605. + * + * @return a rate limit record + */ + @Nonnull + Record getIntegrationManifest() { + return integrationManifest; } @Override public String toString() { - return "GHRateLimit{" + - "remaining=" + getRemaining() + - ", limit=" + getLimit() + - ", resetDate=" + getResetDate() + - '}'; + return "GHRateLimit {" + + "core " + getCore().toString() + + "search " + getSearch().toString() + + "graphql " + getGraphQL().toString() + + "integrationManifest " + getIntegrationManifest().toString() + + '}'; } - @Override public boolean equals(Object o) { if (this == o) { @@ -197,15 +200,185 @@ public class GHRateLimit { return false; } GHRateLimit rateLimit = (GHRateLimit) o; - return getRemaining() == rateLimit.getRemaining() && - getLimit() == rateLimit.getLimit() && - getResetEpochSeconds() == rateLimit.getResetEpochSeconds() && - getResetDate().equals(rateLimit.getResetDate()); + return getCore().equals(rateLimit.getCore()) && + getSearch().equals(rateLimit.getSearch()) && + getGraphQL().equals(rateLimit.getGraphQL()) && + getIntegrationManifest().equals(rateLimit.getIntegrationManifest()); } @Override public int hashCode() { - return Objects.hash(getRemaining(), getLimit(), getResetEpochSeconds(), getResetDate()); + return Objects.hash(getCore(), getSearch(), getGraphQL(), getIntegrationManifest()); + } + + /** + * A limit record used as a placeholder when the the actual limit is not known. + * + * Has a large limit and long duration so that it will doesn't expire too often. + * + * @since 1.100* + */ + public static class UnknownLimitRecord extends Record { + + // One hour + private static final long unknownLimitResetSeconds = 60L * 60L; + + static final int unknownLimit = 1000000; + static final int unknownRemaining = 999999; + + private UnknownLimitRecord() { + super(unknownLimit, unknownRemaining, System.currentTimeMillis() / 1000L + unknownLimitResetSeconds); + } + } + + /** + * A rate limit record. + * @since 1.100 + */ + public static class Record { + /** + * Remaining calls that can be made. + */ + private final int remaining; + + /** + * Allotted API call per hour. + */ + private final int limit; + + /** + * The time at which the current rate limit window resets in UTC epoch seconds. + */ + private final long resetEpochSeconds; + + /** + * EpochSeconds time (UTC) at which this instance was created. + */ + private final long createdAtEpochSeconds = System.currentTimeMillis() / 1000; + + /** + * The calculated time at which the rate limit will reset. + * Recalculated if {@link #recalculateResetDate} is called. + */ + @Nonnull + private Date resetDate; + + @JsonCreator + public Record(@JsonProperty("limit") int limit, + @JsonProperty("remaining") int remaining, + @JsonProperty("reset")long resetEpochSeconds) { + this(limit, remaining, resetEpochSeconds, null); + } + + @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD", + justification = "Deprecated") + public Record(int limit, int remaining, long resetEpochSeconds, String updatedAt) { + this.limit = limit; + this.remaining = remaining; + this.resetEpochSeconds = resetEpochSeconds; + this.resetDate = recalculateResetDate(updatedAt); + } + + /** + * Recalculates the reset date using the server response date to calculate a time duration + * and then add that to the local created time for this record. + * + * @param updatedAt a string date in RFC 1123 + * @return reset date based on the passed date + */ + Date recalculateResetDate(String updatedAt) { + long updatedAtEpochSeconds = createdAtEpochSeconds; + if (!StringUtils.isBlank(updatedAt)) { + try { + // Get the server date and reset data, will always return a time in GMT + updatedAtEpochSeconds = ZonedDateTime.parse(updatedAt, DateTimeFormatter.RFC_1123_DATE_TIME).toEpochSecond(); + } catch (DateTimeParseException e) { + if (LOGGER.isLoggable(FINEST)) { + LOGGER.log(FINEST, "Malformed Date header value " + updatedAt, e); + } + } + } + + // This may seem odd but it results in an accurate or slightly pessimistic reset date + // based on system time rather than on the system being in sync with the server + long calculatedSecondsUntilReset = resetEpochSeconds - updatedAtEpochSeconds; + return resetDate = new Date((createdAtEpochSeconds + calculatedSecondsUntilReset) * 1000); + } + + /** + * Gets the remaining number of requests allowed before this connection will be throttled. + * + * @return an integer + */ + public int getRemaining() { + return remaining; + } + + /** + * Gets the total number of API calls per hour allotted for this connection. + * + * @return an integer + */ + public int getLimit() { + return limit; + } + + /** + * Gets the time in epoch seconds when the rate limit will reset. + * + * @return a long + */ + public long getResetEpochSeconds() { + return resetEpochSeconds; + } + + /** + * Whether the rate limit reset date indicated by this instance is in the + * + * @return true if the rate limit reset date has passed. Otherwise false. + */ + public boolean isExpired() { + return getResetDate().getTime() < System.currentTimeMillis(); + } + + /** + * Returns the date at which the rate limit will reset. + * + * @return the calculated date at which the rate limit has or will reset. + */ + @Nonnull + public Date getResetDate() { + return new Date(resetDate.getTime()); + } + + @Override + public String toString() { + return "{" + + "remaining=" + getRemaining() + + ", limit=" + getLimit() + + ", resetDate=" + getResetDate() + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Record record = (Record) o; + return getRemaining() == record.getRemaining() && + getLimit() == record.getLimit() && + getResetEpochSeconds() == record.getResetEpochSeconds() && + getResetDate().equals(record.getResetDate()); + } + + @Override + public int hashCode() { + return Objects.hash(getRemaining(), getLimit(), getResetEpochSeconds(), getResetDate()); + } } private static final Logger LOGGER = Logger.getLogger(Requester.class.getName()); diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 12012420a..fcd4c171a 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -318,29 +318,59 @@ public class GitHub { public GHRateLimit getRateLimit() throws IOException { GHRateLimit rateLimit; try { - rateLimit = retrieve().to("/rate_limit", JsonRateLimit.class).rate; + rateLimit = retrieve().to("/rate_limit", JsonRateLimit.class).resources; } catch (FileNotFoundException e) { - // GitHub Enterprise doesn't have the rate limit, so in that case - // return some big number that's not too big. - // see issue #78 - rateLimit = GHRateLimit.getPlaceholder(); + // GitHub Enterprise doesn't have the rate limit + // return a default rate limit that + rateLimit = GHRateLimit.Unknown(); } return this.rateLimit = rateLimit; - } - /*package*/ void updateRateLimit(@Nonnull GHRateLimit observed) { + /** + * Update the Rate Limit with the latest info from response header. + * Due to multi-threading requests might complete out of order, we want to pick the one with the most recent info from the server. + * + * @param observed {@link GHRateLimit.Record} constructed from the response header information + */ + void updateCoreRateLimit(@Nonnull GHRateLimit.Record observed) { synchronized (headerRateLimitLock) { - if (headerRateLimit == null - || headerRateLimit.getRemaining() > observed.getRemaining() - || headerRateLimit.getResetEpochSeconds() < observed.getResetEpochSeconds()) { - headerRateLimit = observed; + if (headerRateLimit == null || shouldReplace(observed, headerRateLimit.getCore())) { + headerRateLimit = GHRateLimit.fromHeaderRecord(observed); LOGGER.log(FINE, "Rate limit now: {0}", headerRateLimit); } } } + /** + * Update the Rate Limit with the latest info from response header. + * Due to multi-threading requests might complete out of order, we want to pick the one with the most recent info from the server. + * Header date is only accurate to the second, so we look at the information in the record itself. + * + * {@link GHRateLimit.UnknownLimitRecord}s are always replaced by regular {@link GHRateLimit.Record}s. + * Regular {@link GHRateLimit.Record}s are never replaced by {@link GHRateLimit.UnknownLimitRecord}s. + * Candidates with resetEpochSeconds later than current record are more recent. + * Candidates with the same reset and a lower remaining count are more recent. + * Candidates with an earlier reset are older. + * + * @param candidate {@link GHRateLimit.Record} constructed from the response header information + * @param current the current {@link GHRateLimit.Record} record + */ + static boolean shouldReplace(@Nonnull GHRateLimit.Record candidate, @Nonnull GHRateLimit.Record current) { + if (candidate instanceof GHRateLimit.UnknownLimitRecord && !(current instanceof GHRateLimit.UnknownLimitRecord)) { + // Unknown candidate never replaces a regular record + return false; + } else if (current instanceof GHRateLimit.UnknownLimitRecord && !(candidate instanceof GHRateLimit.UnknownLimitRecord)) { + // Any real record should replace an unknown Record. + return true; + } else { + // records of the same type compare to each other as normal. + return current.getResetEpochSeconds() < candidate.getResetEpochSeconds() + || (current.getResetEpochSeconds() == candidate.getResetEpochSeconds() && current.getRemaining() > candidate.getRemaining()); + } + } + /** * Returns the most recently observed rate limit data or {@code null} if either there is no rate limit * (for example GitHub Enterprise) or if no requests have been made. diff --git a/src/main/java/org/kohsuke/github/JsonRateLimit.java b/src/main/java/org/kohsuke/github/JsonRateLimit.java index 6276ae9b8..6dbfcdb5e 100644 --- a/src/main/java/org/kohsuke/github/JsonRateLimit.java +++ b/src/main/java/org/kohsuke/github/JsonRateLimit.java @@ -4,5 +4,7 @@ package org.kohsuke.github; * @author Kohsuke Kawaguchi */ class JsonRateLimit { - GHRateLimit rate; + + GHRateLimit resources; + } diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 167cf3e2d..4078081cc 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -399,9 +399,9 @@ class Requester { return; } - GHRateLimit observed = new GHRateLimit(limit, remaining, reset, uc.getHeaderField("Date")); + GHRateLimit.Record observed = new GHRateLimit.Record(limit, remaining, reset, uc.getHeaderField("Date")); - root.updateRateLimit(observed); + root.updateCoreRateLimit(observed); } public String getResponseHeader(String header) { @@ -710,7 +710,7 @@ class Requester { setResponseHeaders((GHObject) readValue); } else if (readValue instanceof JsonRateLimit) { // if we're getting a GHRateLimit it needs the server date - ((JsonRateLimit)readValue).rate.recalculateResetDate(uc.getHeaderField("Date")); + ((JsonRateLimit)readValue).resources.getCore().recalculateResetDate(uc.getHeaderField("Date")); } return readValue; } diff --git a/src/test/java/org/kohsuke/github/GHRateLimitTest.java b/src/test/java/org/kohsuke/github/GHRateLimitTest.java index c47a46837..4206e86a2 100644 --- a/src/test/java/org/kohsuke/github/GHRateLimitTest.java +++ b/src/test/java/org/kohsuke/github/GHRateLimitTest.java @@ -166,8 +166,12 @@ public class GHRateLimitTest extends AbstractGitHubWireMockTest { // These are separate instances, but should be equal assertThat(gitHub.rateLimit(), not(sameInstance(rateLimit))); - // Verify different intstances can be compared - assertThat(gitHub.rateLimit(), equalTo(rateLimit)); + // Verify different record instances can be compared + assertThat(gitHub.rateLimit().getCore(), equalTo(rateLimit.getCore())); + + // Verify different instances can be compared + // TODO: This is not work currently because the header rate limit has unknowns for records other than core. + // assertThat(gitHub.rateLimit().getCore(), equalTo(rateLimit.getCore())); assertThat(gitHub.rateLimit(), not(sameInstance(headerRateLimit))); assertThat(gitHub.rateLimit(), sameInstance(gitHub.lastRateLimit())); @@ -195,11 +199,11 @@ public class GHRateLimitTest extends AbstractGitHubWireMockTest { assertThat(gitHub.lastRateLimit(), CoreMatchers.nullValue()); rateLimit = gitHub.rateLimit(); - assertThat(rateLimit, notNullValue()); - assertThat(rateLimit.limit, equalTo(1000000)); - assertThat(rateLimit.getLimit(), equalTo(1000000)); - assertThat(rateLimit.remaining, equalTo(1000000)); - assertThat(rateLimit.getRemaining(), equalTo(1000000)); + assertThat(rateLimit.getCore(), instanceOf(GHRateLimit.UnknownLimitRecord.class)); + assertThat(rateLimit.limit, equalTo(GHRateLimit.UnknownLimitRecord.unknownLimit)); + assertThat(rateLimit.getLimit(), equalTo(GHRateLimit.UnknownLimitRecord.unknownLimit)); + assertThat(rateLimit.remaining, equalTo(GHRateLimit.UnknownLimitRecord.unknownRemaining)); + assertThat(rateLimit.getRemaining(), equalTo(GHRateLimit.UnknownLimitRecord.unknownRemaining)); assertThat(rateLimit.getResetDate().compareTo(lastReset), equalTo(1)); lastReset = rateLimit.getResetDate(); @@ -222,11 +226,11 @@ public class GHRateLimitTest extends AbstractGitHubWireMockTest { assertThat(gitHub.lastRateLimit(), CoreMatchers.nullValue()); rateLimit = gitHub.rateLimit(); - assertThat(rateLimit, notNullValue()); - assertThat(rateLimit.limit, equalTo(1000000)); - assertThat(rateLimit.getLimit(), equalTo(1000000)); - assertThat(rateLimit.remaining, equalTo(1000000)); - assertThat(rateLimit.getRemaining(), equalTo(1000000)); + assertThat(rateLimit.getCore(), instanceOf(GHRateLimit.UnknownLimitRecord.class)); + assertThat(rateLimit.limit, equalTo(GHRateLimit.UnknownLimitRecord.unknownLimit)); + assertThat(rateLimit.getLimit(), equalTo(GHRateLimit.UnknownLimitRecord.unknownLimit)); + assertThat(rateLimit.remaining, equalTo(GHRateLimit.UnknownLimitRecord.unknownRemaining)); + assertThat(rateLimit.getRemaining(), equalTo(GHRateLimit.UnknownLimitRecord.unknownRemaining)); assertThat(rateLimit.getResetDate().compareTo(lastReset), equalTo(1)); lastReset = rateLimit.getResetDate(); @@ -239,11 +243,11 @@ public class GHRateLimitTest extends AbstractGitHubWireMockTest { rateLimit = gitHub.getRateLimit(); assertThat(mockGitHub.getRequestCount(), equalTo(4)); - assertThat(rateLimit, notNullValue()); - assertThat(rateLimit.limit, equalTo(1000000)); - assertThat(rateLimit.getLimit(), equalTo(1000000)); - assertThat(rateLimit.remaining, equalTo(1000000)); - assertThat(rateLimit.getRemaining(), equalTo(1000000)); + assertThat(rateLimit.getCore(), instanceOf(GHRateLimit.UnknownLimitRecord.class)); + assertThat(rateLimit.limit, equalTo(GHRateLimit.UnknownLimitRecord.unknownLimit)); + assertThat(rateLimit.getLimit(), equalTo(GHRateLimit.UnknownLimitRecord.unknownLimit)); + assertThat(rateLimit.remaining, equalTo(GHRateLimit.UnknownLimitRecord.unknownRemaining)); + assertThat(rateLimit.getRemaining(), equalTo(GHRateLimit.UnknownLimitRecord.unknownRemaining)); assertThat(rateLimit.getResetDate().compareTo(lastReset), equalTo(1)); // Give this a moment @@ -290,11 +294,11 @@ public class GHRateLimitTest extends AbstractGitHubWireMockTest { rateLimit = gitHub.getRateLimit(); assertThat(mockGitHub.getRequestCount(), equalTo(6)); - assertThat(rateLimit, notNullValue()); - assertThat(rateLimit.limit, equalTo(1000000)); - assertThat(rateLimit.getLimit(), equalTo(1000000)); - assertThat(rateLimit.remaining, equalTo(1000000)); - assertThat(rateLimit.getRemaining(), equalTo(1000000)); + assertThat(rateLimit.getCore(), instanceOf(GHRateLimit.UnknownLimitRecord.class)); + assertThat(rateLimit.limit, equalTo(GHRateLimit.UnknownLimitRecord.unknownLimit)); + assertThat(rateLimit.getLimit(), equalTo(GHRateLimit.UnknownLimitRecord.unknownLimit)); + assertThat(rateLimit.remaining, equalTo(GHRateLimit.UnknownLimitRecord.unknownRemaining)); + assertThat(rateLimit.getRemaining(), equalTo(GHRateLimit.UnknownLimitRecord.unknownRemaining)); assertThat(rateLimit.getResetDate().compareTo(lastReset), equalTo(1)); // ratelimit() should prefer headerRateLimit when getRateLimit fails and headerRateLimit is not expired @@ -307,12 +311,7 @@ public class GHRateLimitTest extends AbstractGitHubWireMockTest { } - // These three tests should be have the same, showing server time adjustment working - @Test - public void testGitHubRateLimitExpiration() throws Exception { - executeExpirationTest(); - } - + // These tests should behave the same, showing server time adjustment working @Test public void testGitHubRateLimitExpirationServerFiveMinutesAhead() throws Exception { executeExpirationTest(); diff --git a/src/test/java/org/kohsuke/github/GitHubStaticTest.java b/src/test/java/org/kohsuke/github/GitHubStaticTest.java index 9c03a3323..47e600aef 100644 --- a/src/test/java/org/kohsuke/github/GitHubStaticTest.java +++ b/src/test/java/org/kohsuke/github/GitHubStaticTest.java @@ -1,5 +1,7 @@ package org.kohsuke.github; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import org.eclipse.jgit.api.Git; import org.junit.Assert; import org.junit.Test; @@ -11,6 +13,7 @@ import java.util.TimeZone; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.core.Is.is; /** * Unit test for {@link GitHub} static helpers. @@ -68,6 +71,65 @@ public class GitHubStaticTest extends Assert { } catch (IllegalStateException e) { assertThat(e.getMessage(), equalTo("Unable to parse the timestamp: " + instantBadFormat)); } + } + + @Test + public void testGitHubRateLimitShouldReplaceRateLimit() throws Exception { + + GHRateLimit.Record unknown0 = GHRateLimit.Unknown().getCore(); + GHRateLimit.Record unknown1 = GHRateLimit.Unknown().getCore(); + + + + + GHRateLimit.Record record0 = new GHRateLimit.Record(10, 10, 10L); + GHRateLimit.Record record1 = new GHRateLimit.Record(10, 9, 10L); + GHRateLimit.Record record2 = new GHRateLimit.Record(10, 2, 10L); + GHRateLimit.Record record3 = new GHRateLimit.Record(10, 10, 20L); + GHRateLimit.Record record4 = new GHRateLimit.Record(10, 5, 20L); + + + Thread.sleep(2000); + + GHRateLimit.Record recordWorst = new GHRateLimit.Record(Integer.MAX_VALUE, Integer.MAX_VALUE, Long.MIN_VALUE); + GHRateLimit.Record record00 = new GHRateLimit.Record(10, 10, 10L); + GHRateLimit.Record unknown2 = GHRateLimit.Unknown().getCore(); + + // Rate-limit records maybe created and returned in different orders. + // We should update to the regular records over unknowns. + // After that, we should update to the candidate if its limit is lower or its reset is later. + + assertThat("Equivalent unknown should not replace", GitHub.shouldReplace(unknown0, unknown1), is(false)); + assertThat("Equivalent unknown should not replace", GitHub.shouldReplace(unknown1, unknown0), is(false)); + + assertThat("Later unknown should replace earlier", GitHub.shouldReplace(unknown2, unknown0), is(true)); + assertThat("Earlier unknown should not replace later", GitHub.shouldReplace(unknown0, unknown2), is(false)); + + assertThat("Worst record should replace later unknown", GitHub.shouldReplace(recordWorst, unknown1), is(true)); + assertThat("Unknown should not replace worst record", GitHub.shouldReplace(unknown1, recordWorst), is(false)); + + assertThat("Earlier record should replace later worst", GitHub.shouldReplace(record0, recordWorst), is(true)); + assertThat("Later worst record should not replace earlier", GitHub.shouldReplace(recordWorst, record0), is(false)); + + assertThat("Equivalent record should not replace", GitHub.shouldReplace(record0, record00), is(false)); + assertThat("Equivalent record should not replace", GitHub.shouldReplace(record00, record0), is(false)); + + assertThat("Lower limit record should replace higher", GitHub.shouldReplace(record1, record0), is(true)); + assertThat("Lower limit record should replace higher", GitHub.shouldReplace(record2, record1), is(true)); + + assertThat("Higher limit record should not replace lower", GitHub.shouldReplace(record1, record2), is(false)); + + assertThat("Higher limit record with later reset should replace lower", GitHub.shouldReplace(record3, record2), is(true)); + + assertThat("Lower limit record with later reset should replace higher", GitHub.shouldReplace(record4, record1), is(true)); + + assertThat("Lower limit record with earlier reset should not replace higher", GitHub.shouldReplace(record2, record4), is(false)); + + + + + + } static String formatDate(Date dt, String format) { diff --git a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimit/__files/rate_limit-4e2fc33b-fb25-4dfc-9d56-34f9b4d707be.json b/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimit/__files/rate_limit-4e2fc33b-fb25-4dfc-9d56-34f9b4d707be.json index dc1b25b18..607385447 100644 --- a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimit/__files/rate_limit-4e2fc33b-fb25-4dfc-9d56-34f9b4d707be.json +++ b/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimit/__files/rate_limit-4e2fc33b-fb25-4dfc-9d56-34f9b4d707be.json @@ -3,27 +3,27 @@ "core": { "limit": 5000, "remaining": 4896, - "reset": 1570478899 + "reset": {{now offset='1 hours' format='unix'}} }, "search": { "limit": 30, "remaining": 30, - "reset": 1570478180 + "reset": {{now offset='1 hours' format='unix'}} }, "graphql": { "limit": 5000, "remaining": 5000, - "reset": 1570481642 + "reset": {{now offset='1 hours' format='unix'}} }, "integration_manifest": { "limit": 5000, "remaining": 5000, - "reset": 1570481642 + "reset": {{now offset='1 hours' format='unix'}} } }, "rate": { "limit": 5000, "remaining": 4896, - "reset": {{now offset='1 hours' format='unix'}} + "reset": 1570478899 } } \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimit/__files/rate_limit-a1f82a96-500c-4462-ae7b-e0159afa8208.json b/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimit/__files/rate_limit-a1f82a96-500c-4462-ae7b-e0159afa8208.json index b05430bbf..e5881bcd4 100644 --- a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimit/__files/rate_limit-a1f82a96-500c-4462-ae7b-e0159afa8208.json +++ b/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimit/__files/rate_limit-a1f82a96-500c-4462-ae7b-e0159afa8208.json @@ -3,27 +3,27 @@ "core": { "limit": 5000, "remaining": 4897, - "reset": 1570478899 + "reset": {{now offset='1 hours' format='unix'}} }, "search": { "limit": 30, "remaining": 30, - "reset": 1570478180 + "reset": {{now offset='1 hours' format='unix'}} }, "graphql": { "limit": 5000, "remaining": 5000, - "reset": 1570481642 + "reset": {{now offset='1 hours' format='unix'}} }, "integration_manifest": { "limit": 5000, "remaining": 5000, - "reset": 1570481642 + "reset": {{now offset='1 hours' format='unix'}} } }, "rate": { "limit": 5000, "remaining": 4897, - "reset": {{now offset='1 hours' format='unix'}} + "reset": 1570478899 } } \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimit/__files/rate_limit-f22b1cea-3679-481d-8b95-459b2c47bf98.json b/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimit/__files/rate_limit-f22b1cea-3679-481d-8b95-459b2c47bf98.json index b05430bbf..e5881bcd4 100644 --- a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimit/__files/rate_limit-f22b1cea-3679-481d-8b95-459b2c47bf98.json +++ b/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimit/__files/rate_limit-f22b1cea-3679-481d-8b95-459b2c47bf98.json @@ -3,27 +3,27 @@ "core": { "limit": 5000, "remaining": 4897, - "reset": 1570478899 + "reset": {{now offset='1 hours' format='unix'}} }, "search": { "limit": 30, "remaining": 30, - "reset": 1570478180 + "reset": {{now offset='1 hours' format='unix'}} }, "graphql": { "limit": 5000, "remaining": 5000, - "reset": 1570481642 + "reset": {{now offset='1 hours' format='unix'}} }, "integration_manifest": { "limit": 5000, "remaining": 5000, - "reset": 1570481642 + "reset": {{now offset='1 hours' format='unix'}} } }, "rate": { "limit": 5000, "remaining": 4897, - "reset": {{now offset='1 hours' format='unix'}} + "reset": 1570478899 } } \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/__files/rate_limit-4e2fc33b-fb25-4dfc-9d56-34f9b4d707be.json b/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/__files/rate_limit-4e2fc33b-fb25-4dfc-9d56-34f9b4d707be.json deleted file mode 100644 index 04bc2d1c4..000000000 --- a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/__files/rate_limit-4e2fc33b-fb25-4dfc-9d56-34f9b4d707be.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "resources": { - "core": { - "limit": 5000, - "remaining": 4896, - "reset": 1570478899 - }, - "search": { - "limit": 30, - "remaining": 30, - "reset": 1570478180 - }, - "graphql": { - "limit": 5000, - "remaining": 5000, - "reset": 1570481642 - }, - "integration_manifest": { - "limit": 5000, - "remaining": 5000, - "reset": 1570481642 - } - }, - "rate": { - "limit": 5000, - "remaining": 4896, - "reset": {{now offset='5 seconds' format='unix'}} - } -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/__files/rate_limit-a1f82a96-500c-4462-ae7b-e0159afa8208.json b/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/__files/rate_limit-a1f82a96-500c-4462-ae7b-e0159afa8208.json deleted file mode 100644 index d846f8221..000000000 --- a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/__files/rate_limit-a1f82a96-500c-4462-ae7b-e0159afa8208.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "resources": { - "core": { - "limit": 5000, - "remaining": 4897, - "reset": 1570478899 - }, - "search": { - "limit": 30, - "remaining": 30, - "reset": 1570478180 - }, - "graphql": { - "limit": 5000, - "remaining": 5000, - "reset": 1570481642 - }, - "integration_manifest": { - "limit": 5000, - "remaining": 5000, - "reset": 1570481642 - } - }, - "rate": { - "limit": 5000, - "remaining": 4897, - "reset": {{now offset='5 seconds' format='unix'}} - } -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/__files/rate_limit-f22b1cea-3679-481d-8b95-459b2c47bf98.json b/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/__files/rate_limit-f22b1cea-3679-481d-8b95-459b2c47bf98.json deleted file mode 100644 index d846f8221..000000000 --- a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/__files/rate_limit-f22b1cea-3679-481d-8b95-459b2c47bf98.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "resources": { - "core": { - "limit": 5000, - "remaining": 4897, - "reset": 1570478899 - }, - "search": { - "limit": 30, - "remaining": 30, - "reset": 1570478180 - }, - "graphql": { - "limit": 5000, - "remaining": 5000, - "reset": 1570481642 - }, - "integration_manifest": { - "limit": 5000, - "remaining": 5000, - "reset": 1570481642 - } - }, - "rate": { - "limit": 5000, - "remaining": 4897, - "reset": {{now offset='5 seconds' format='unix'}} - } -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/__files/user-a460fd69-99f3-46c7-aeb1-888c34085d4a.json b/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/__files/user-a460fd69-99f3-46c7-aeb1-888c34085d4a.json deleted file mode 100644 index 41fc9e3d0..000000000 --- a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/__files/user-a460fd69-99f3-46c7-aeb1-888c34085d4a.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "login": "bitwiseman", - "id": 1958953, - "node_id": "MDQ6VXNlcjE5NTg5NTM=", - "avatar_url": "https://avatars3.githubusercontent.com/u/1958953?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/bitwiseman", - "html_url": "https://github.com/bitwiseman", - "followers_url": "https://api.github.com/users/bitwiseman/followers", - "following_url": "https://api.github.com/users/bitwiseman/following{/other_user}", - "gists_url": "https://api.github.com/users/bitwiseman/gists{/gist_id}", - "starred_url": "https://api.github.com/users/bitwiseman/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/bitwiseman/subscriptions", - "organizations_url": "https://api.github.com/users/bitwiseman/orgs", - "repos_url": "https://api.github.com/users/bitwiseman/repos", - "events_url": "https://api.github.com/users/bitwiseman/events{/privacy}", - "received_events_url": "https://api.github.com/users/bitwiseman/received_events", - "type": "User", - "site_admin": false, - "name": "Liam Newman", - "company": "Cloudbees, Inc.", - "blog": "", - "location": "Seattle, WA, USA", - "email": "bitwiseman@gmail.com", - "hireable": null, - "bio": "https://twitter.com/bitwiseman", - "public_repos": 168, - "public_gists": 4, - "followers": 136, - "following": 9, - "created_at": "2012-07-11T20:38:33Z", - "updated_at": "2019-09-24T19:32:29Z", - "private_gists": 7, - "total_private_repos": 9, - "owned_private_repos": 0, - "disk_usage": 33697, - "collaborators": 0, - "two_factor_authentication": true, - "plan": { - "name": "free", - "space": 976562499, - "collaborators": 0, - "private_repos": 10000 - } -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/mappings/rate_limit-2-f22b1c.json b/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/mappings/rate_limit-2-f22b1c.json deleted file mode 100644 index 19fff3635..000000000 --- a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/mappings/rate_limit-2-f22b1c.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "id": "f22b1cea-3679-481d-8b95-459b2c47bf98", - "name": "rate_limit", - "request": { - "url": "/rate_limit", - "method": "GET" - }, - "response": { - "status": 200, - "bodyFileName": "rate_limit-f22b1cea-3679-481d-8b95-459b2c47bf98.json", - "headers": { - "Date": "{{now timezone='GMT' format='EEE, dd MMM yyyy HH:mm:ss z'}}", - "Content-Type": "application/json; charset=utf-8", - "Server": "GitHub.com", - "Status": "200 OK", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4897", - "X-RateLimit-Reset": "{{now offset='3 seconds' format='unix'}}", - "Cache-Control": "no-cache", - "X-OAuth-Scopes": "admin:org, admin:org_hook, admin:public_key, admin:repo_hook, delete_repo, gist, notifications, repo, user, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "X-GitHub-Media-Type": "unknown, github.v3", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "1; mode=block", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Vary": "Accept-Encoding", - "X-GitHub-Request-Id": "E39F:3620:2D9D346:369B91A:5D9B9848" - } - }, - "uuid": "f22b1cea-3679-481d-8b95-459b2c47bf98", - "persistent": true, - "scenarioName": "scenario-1-rate_limit", - "requiredScenarioState": "Started", - "newScenarioState": "scenario-1-rate_limit-2", - "insertionIndex": 2 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/mappings/rate_limit-3-a1f82a.json b/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/mappings/rate_limit-3-a1f82a.json deleted file mode 100644 index a2b904158..000000000 --- a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/mappings/rate_limit-3-a1f82a.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "id": "a1f82a96-500c-4462-ae7b-e0159afa8208", - "name": "rate_limit", - "request": { - "url": "/rate_limit", - "method": "GET" - }, - "response": { - "status": 200, - "bodyFileName": "rate_limit-a1f82a96-500c-4462-ae7b-e0159afa8208.json", - "headers": { - "Date": "{{now timezone='GMT' format='EEE, dd MMM yyyy HH:mm:ss z'}}", - "Content-Type": "application/json; charset=utf-8", - "Server": "GitHub.com", - "Status": "200 OK", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4897", - "X-RateLimit-Reset": "{{now offset='3 seconds' format='unix'}}", - "Cache-Control": "no-cache", - "X-OAuth-Scopes": "admin:org, admin:org_hook, admin:public_key, admin:repo_hook, delete_repo, gist, notifications, repo, user, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "X-GitHub-Media-Type": "unknown, github.v3", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "1; mode=block", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Vary": "Accept-Encoding", - "X-GitHub-Request-Id": "E39F:3620:2D9D3B3:369BA1D:5D9B984A" - } - }, - "uuid": "a1f82a96-500c-4462-ae7b-e0159afa8208", - "persistent": true, - "scenarioName": "scenario-1-rate_limit", - "requiredScenarioState": "scenario-1-rate_limit-2", - "newScenarioState": "scenario-1-rate_limit-3", - "insertionIndex": 3 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/mappings/rate_limit-5-4e2fc3.json b/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/mappings/rate_limit-5-4e2fc3.json deleted file mode 100644 index 629820ed4..000000000 --- a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/mappings/rate_limit-5-4e2fc3.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "id": "4e2fc33b-fb25-4dfc-9d56-34f9b4d707be", - "name": "rate_limit", - "request": { - "url": "/rate_limit", - "method": "GET" - }, - "response": { - "status": 200, - "bodyFileName": "rate_limit-4e2fc33b-fb25-4dfc-9d56-34f9b4d707be.json", - "headers": { - "Date": "{{now timezone='GMT' format='EEE, dd MMM yyyy HH:mm:ss z'}}", - "Content-Type": "application/json; charset=utf-8", - "Server": "GitHub.com", - "Status": "200 OK", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4896", - "X-RateLimit-Reset": "{{now offset='3 seconds' format='unix'}}", - "Cache-Control": "no-cache", - "X-OAuth-Scopes": "admin:org, admin:org_hook, admin:public_key, admin:repo_hook, delete_repo, gist, notifications, repo, user, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "X-GitHub-Media-Type": "unknown, github.v3", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "1; mode=block", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Vary": "Accept-Encoding", - "X-GitHub-Request-Id": "E39F:3620:2D9D3D1:369BAD1:5D9B984C" - } - }, - "uuid": "4e2fc33b-fb25-4dfc-9d56-34f9b4d707be", - "persistent": true, - "scenarioName": "scenario-1-rate_limit", - "requiredScenarioState": "scenario-1-rate_limit-3", - "insertionIndex": 5 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/mappings/user-1-a460fd.json b/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/mappings/user-1-a460fd.json deleted file mode 100644 index 0256fc577..000000000 --- a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpiration/mappings/user-1-a460fd.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "id": "a460fd69-99f3-46c7-aeb1-888c34085d4a", - "name": "user", - "request": { - "url": "/user", - "method": "GET" - }, - "response": { - "status": 200, - "bodyFileName": "user-a460fd69-99f3-46c7-aeb1-888c34085d4a.json", - "headers": { - "Date": "{{now timezone='GMT' format='EEE, dd MMM yyyy HH:mm:ss z'}}", - "Content-Type": "application/json; charset=utf-8", - "Server": "GitHub.com", - "Status": "200 OK", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4897", - "X-RateLimit-Reset": "{{now offset='3 seconds' format='unix'}}", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": [ - "Accept, Authorization, Cookie, X-GitHub-OTP", - "Accept-Encoding" - ], - "ETag": "W/\"af0c41afcacb8ceee14b7d896719c3bd\"", - "Last-Modified": "Tue, 24 Sep 2019 19:32:29 GMT", - "X-OAuth-Scopes": "admin:org, admin:org_hook, admin:public_key, admin:repo_hook, delete_repo, gist, notifications, repo, user, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "X-GitHub-Media-Type": "unknown, github.v3", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "1; mode=block", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "X-GitHub-Request-Id": "E39F:3620:2D9D266:369B909:5D9B9848" - } - }, - "uuid": "a460fd69-99f3-46c7-aeb1-888c34085d4a", - "persistent": true, - "insertionIndex": 1 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpirationServerFiveMinutesAhead/__files/rate_limit-4e2fc33b-fb25-4dfc-9d56-34f9b4d707be.json b/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpirationServerFiveMinutesAhead/__files/rate_limit-4e2fc33b-fb25-4dfc-9d56-34f9b4d707be.json index 69cf0ad9d..404ebd4de 100644 --- a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpirationServerFiveMinutesAhead/__files/rate_limit-4e2fc33b-fb25-4dfc-9d56-34f9b4d707be.json +++ b/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpirationServerFiveMinutesAhead/__files/rate_limit-4e2fc33b-fb25-4dfc-9d56-34f9b4d707be.json @@ -3,27 +3,27 @@ "core": { "limit": 5000, "remaining": 4896, - "reset": 1570478899 + "reset": {{now offset='305 seconds' format='unix'}} }, "search": { "limit": 30, "remaining": 30, - "reset": 1570478180 + "reset": {{now offset='305 seconds' format='unix'}} }, "graphql": { "limit": 5000, "remaining": 5000, - "reset": 1570481642 + "reset": {{now offset='305 seconds' format='unix'}} }, "integration_manifest": { "limit": 5000, "remaining": 5000, - "reset": 1570481642 + "reset": {{now offset='305 seconds' format='unix'}} } }, "rate": { "limit": 5000, "remaining": 4896, - "reset": {{now offset='305 seconds' format='unix'}} + "reset": 1570478899 } } \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpirationServerFiveMinutesAhead/__files/rate_limit-a1f82a96-500c-4462-ae7b-e0159afa8208.json b/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpirationServerFiveMinutesAhead/__files/rate_limit-a1f82a96-500c-4462-ae7b-e0159afa8208.json index ef6501911..bacd79c0f 100644 --- a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpirationServerFiveMinutesAhead/__files/rate_limit-a1f82a96-500c-4462-ae7b-e0159afa8208.json +++ b/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpirationServerFiveMinutesAhead/__files/rate_limit-a1f82a96-500c-4462-ae7b-e0159afa8208.json @@ -3,27 +3,27 @@ "core": { "limit": 5000, "remaining": 4897, - "reset": 1570478899 + "reset": {{now offset='305 seconds' format='unix'}} }, "search": { "limit": 30, "remaining": 30, - "reset": 1570478180 + "reset": {{now offset='305 seconds' format='unix'}} }, "graphql": { "limit": 5000, "remaining": 5000, - "reset": 1570481642 + "reset": {{now offset='305 seconds' format='unix'}} }, "integration_manifest": { "limit": 5000, "remaining": 5000, - "reset": 1570481642 + "reset": {{now offset='305 seconds' format='unix'}} } }, "rate": { "limit": 5000, "remaining": 4897, - "reset": {{now offset='305 seconds' format='unix'}} + "reset": 1570478899 } } \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpirationServerFiveMinutesAhead/__files/rate_limit-f22b1cea-3679-481d-8b95-459b2c47bf98.json b/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpirationServerFiveMinutesAhead/__files/rate_limit-f22b1cea-3679-481d-8b95-459b2c47bf98.json index ef6501911..bacd79c0f 100644 --- a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpirationServerFiveMinutesAhead/__files/rate_limit-f22b1cea-3679-481d-8b95-459b2c47bf98.json +++ b/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpirationServerFiveMinutesAhead/__files/rate_limit-f22b1cea-3679-481d-8b95-459b2c47bf98.json @@ -3,27 +3,27 @@ "core": { "limit": 5000, "remaining": 4897, - "reset": 1570478899 + "reset": {{now offset='305 seconds' format='unix'}} }, "search": { "limit": 30, "remaining": 30, - "reset": 1570478180 + "reset": {{now offset='305 seconds' format='unix'}} }, "graphql": { "limit": 5000, "remaining": 5000, - "reset": 1570481642 + "reset": {{now offset='305 seconds' format='unix'}} }, "integration_manifest": { "limit": 5000, "remaining": 5000, - "reset": 1570481642 + "reset": {{now offset='305 seconds' format='unix'}} } }, "rate": { "limit": 5000, "remaining": 4897, - "reset": {{now offset='305 seconds' format='unix'}} + "reset": 1570478899 } } \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpirationServerFiveMinutesBehind/__files/rate_limit-4e2fc33b-fb25-4dfc-9d56-34f9b4d707be.json b/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpirationServerFiveMinutesBehind/__files/rate_limit-4e2fc33b-fb25-4dfc-9d56-34f9b4d707be.json index 2d5473a9f..9d326f28a 100644 --- a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpirationServerFiveMinutesBehind/__files/rate_limit-4e2fc33b-fb25-4dfc-9d56-34f9b4d707be.json +++ b/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpirationServerFiveMinutesBehind/__files/rate_limit-4e2fc33b-fb25-4dfc-9d56-34f9b4d707be.json @@ -3,27 +3,27 @@ "core": { "limit": 5000, "remaining": 4896, - "reset": 1570478899 + "reset": {{now offset='-295 seconds' format='unix'}} }, "search": { "limit": 30, "remaining": 30, - "reset": 1570478180 + "reset": {{now offset='-295 seconds' format='unix'}} }, "graphql": { "limit": 5000, "remaining": 5000, - "reset": 1570481642 + "reset": {{now offset='-295 seconds' format='unix'}} }, "integration_manifest": { "limit": 5000, "remaining": 5000, - "reset": 1570481642 + "reset": {{now offset='-295 seconds' format='unix'}} } }, "rate": { "limit": 5000, "remaining": 4896, - "reset": {{now offset='-295 seconds' format='unix'}} + "reset": 1570478899 } } \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpirationServerFiveMinutesBehind/__files/rate_limit-a1f82a96-500c-4462-ae7b-e0159afa8208.json b/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpirationServerFiveMinutesBehind/__files/rate_limit-a1f82a96-500c-4462-ae7b-e0159afa8208.json index bbb5574bd..c18f00dbb 100644 --- a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpirationServerFiveMinutesBehind/__files/rate_limit-a1f82a96-500c-4462-ae7b-e0159afa8208.json +++ b/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpirationServerFiveMinutesBehind/__files/rate_limit-a1f82a96-500c-4462-ae7b-e0159afa8208.json @@ -3,27 +3,27 @@ "core": { "limit": 5000, "remaining": 4897, - "reset": 1570478899 + "reset": {{now offset='-295 seconds' format='unix'}} }, "search": { "limit": 30, "remaining": 30, - "reset": 1570478180 + "reset": {{now offset='-295 seconds' format='unix'}} }, "graphql": { "limit": 5000, "remaining": 5000, - "reset": 1570481642 + "reset": {{now offset='-295 seconds' format='unix'}} }, "integration_manifest": { "limit": 5000, "remaining": 5000, - "reset": 1570481642 + "reset": {{now offset='-295 seconds' format='unix'}} } }, "rate": { "limit": 5000, "remaining": 4897, - "reset": {{now offset='-295 seconds' format='unix'}} + "reset": 1570478899 } } \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpirationServerFiveMinutesBehind/__files/rate_limit-f22b1cea-3679-481d-8b95-459b2c47bf98.json b/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpirationServerFiveMinutesBehind/__files/rate_limit-f22b1cea-3679-481d-8b95-459b2c47bf98.json index bbb5574bd..c18f00dbb 100644 --- a/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpirationServerFiveMinutesBehind/__files/rate_limit-f22b1cea-3679-481d-8b95-459b2c47bf98.json +++ b/src/test/resources/org/kohsuke/github/GHRateLimitTest/wiremock/testGitHubRateLimitExpirationServerFiveMinutesBehind/__files/rate_limit-f22b1cea-3679-481d-8b95-459b2c47bf98.json @@ -3,27 +3,27 @@ "core": { "limit": 5000, "remaining": 4897, - "reset": 1570478899 + "reset": {{now offset='-295 seconds' format='unix'}} }, "search": { "limit": 30, "remaining": 30, - "reset": 1570478180 + "reset": {{now offset='-295 seconds' format='unix'}} }, "graphql": { "limit": 5000, "remaining": 5000, - "reset": 1570481642 + "reset": {{now offset='-295 seconds' format='unix'}} }, "integration_manifest": { "limit": 5000, "remaining": 5000, - "reset": 1570481642 + "reset": {{now offset='-295 seconds' format='unix'}} } }, "rate": { "limit": 5000, "remaining": 4897, - "reset": {{now offset='-295 seconds' format='unix'}} + "reset": 1570478899 } } \ No newline at end of file