Exemplo n.º 1
0
            public void CanPopulateObjectFromSerializedData()
            {
                var headers = new Dictionary <string, string> {
                    { "X-RateLimit-Limit", "100" },
                    { "X-RateLimit-Remaining", "42" },
                    { "X-RateLimit-Reset", "1372700873" }
                };
                var response = CreateResponse(HttpStatusCode.Forbidden, headers);

                var exception = new RateLimitExceededException(response);

                using (var stream = new MemoryStream())
                {
                    var formatter = new BinaryFormatter();
                    formatter.Serialize(stream, exception);
                    stream.Position = 0;
                    var deserialized = (RateLimitExceededException)formatter.Deserialize(stream);

                    Assert.Equal(HttpStatusCode.Forbidden, deserialized.StatusCode);
                    Assert.Equal(100, deserialized.Limit);
                    Assert.Equal(42, deserialized.Remaining);
                    var expectedReset = DateTimeOffset.ParseExact(
                        "Mon 01 Jul 2013 5:47:53 PM -00:00",
                        "ddd dd MMM yyyy h:mm:ss tt zzz",
                        CultureInfo.InvariantCulture);
                    Assert.Equal(expectedReset, deserialized.Reset);
                }
            }
Exemplo n.º 2
0
    public void RetryAfter_Equals_CtorRetryAfterParameter()
    {
        var testValue = 100.Seconds();
        var e         = new RateLimitExceededException(testValue);

        Assert.Equal(testValue, e.RetryAfter);
    }
Exemplo n.º 3
0
    public void Message_ContainsCorrectText()
    {
        var testValue = 100.Seconds();
        var e         = new RateLimitExceededException(testValue);

        Assert.Equal("Rate limit exceeded", e.Message);
    }
Exemplo n.º 4
0
        public void Exception_ResponseMessageConstructor()
        {
            var response = new RiotResponse(null);
            var message  = "TEST";

            var ex1 = new RestException(response, message);

            Assert.That(ex1.Response, Is.EqualTo(response));
            Assert.That(ex1.Message, Is.EqualTo(message));

            var ex2 = new NotFoundException(response, message);

            Assert.That(ex2.Response, Is.EqualTo(response));
            Assert.That(ex2.Message, Is.EqualTo(message));

            var ex3 = new RateLimitExceededException(response, message);

            Assert.That(ex3.Response, Is.EqualTo(response));
            Assert.That(ex3.Message, Is.EqualTo(message));

            var ex4 = new RestTimeoutException(response, message);

            Assert.That(ex4.Response, Is.EqualTo(response));
            Assert.That(ex4.Message, Is.EqualTo(message));

            var ex5 = new ConnectionFailedException(response, message);

            Assert.That(ex5.Response, Is.EqualTo(response));
            Assert.That(ex5.Message, Is.EqualTo(message));
        }
Exemplo n.º 5
0
            public void ReturnsSkewedDistanceFromReset()
            {
                // One hour into the future is hopefully long enough to still be
                // in the future at the end of this method
                var resetTime = DateTimeOffset.Now + TimeSpan.FromHours(1);
                var recvDate  = new DateTimeOffset(2020, 06, 07, 12, 00, 00, TimeSpan.Zero);
                var skew      = TimeSpan.FromSeconds(-5);

                var response = CreateResponse(HttpStatusCode.Forbidden,
                                              new Dictionary <string, string>
                {
                    ["X-RateLimit-Limit"]     = "100",
                    ["X-RateLimit-Remaining"] = "0",
                    ["X-RateLimit-Reset"]     = resetTime.ToUnixTimeSeconds()
                                                .ToString(CultureInfo.InvariantCulture),
                    ["Date"] = (recvDate + skew).ToString("r"),
                    [ApiInfoParser.ReceivedTimeHeaderName] = recvDate.ToString("r"),
                });

                Assert.Equal(skew, response.ApiInfo.ServerTimeDifference);
                var except = new RateLimitExceededException(response);

                var timeToReset = except.GetRetryAfterTimeSpan();

                Assert.NotEqual(TimeSpan.Zero, timeToReset);
                Assert.InRange(timeToReset, TimeSpan.Zero, TimeSpan.FromHours(1));
            }
Exemplo n.º 6
0
            public void HandlesInvalidHeaderValues()
            {
                var headers = new Dictionary <string, string>
                {
                    { "X-RateLimit-Limit", "XXX" },
                    { "X-RateLimit-Remaining", "XXXX" },
                    { "X-RateLimit-Reset", "XXXX" },
                    { "Date", "XXX" },
                    { ApiInfoParser.ReceivedTimeHeaderName, "XXX" },
                };
                var response = CreateResponse(HttpStatusCode.Forbidden, headers);

                var exception = new RateLimitExceededException(response);

                Assert.Equal(HttpStatusCode.Forbidden, exception.StatusCode);
                Assert.Equal(0, exception.Limit);
                Assert.Equal(0, exception.Remaining);
                var expectedReset = DateTimeOffset.ParseExact(
                    "Thu 01 Jan 1970 0:00:00 AM -00:00",
                    "ddd dd MMM yyyy h:mm:ss tt zzz",
                    CultureInfo.InvariantCulture);

                Assert.Equal(expectedReset, exception.Reset);
                Assert.Equal(TimeSpan.Zero, exception.GetRetryAfterTimeSpan());
            }
Exemplo n.º 7
0
        public void Exception_DefaultConstructor()
        {
            var ex1 = new RestException();

            Assert.That(ex1.Response, Is.EqualTo(null));
            Assert.That(ex1.Message, Is.EqualTo("A REST request failed."));
            Assert.That(ex1.InnerException, Is.Null);

            var ex2 = new NotFoundException();

            Assert.That(ex2.Response, Is.EqualTo(null));
            Assert.That(ex2.Message, Is.EqualTo("The requested resource was not found."));
            Assert.That(ex2.InnerException, Is.Null);

            var ex3 = new RateLimitExceededException();

            Assert.That(ex3.Response, Is.EqualTo(null));
            Assert.That(ex3.Message, Is.EqualTo("The rate limit for the current API key was exceeded."));
            Assert.That(ex3.InnerException, Is.Null);

            var ex4 = new RestTimeoutException();

            Assert.That(ex4.Response, Is.EqualTo(null));
            Assert.That(ex4.Message, Is.EqualTo("A REST request timed out."));
            Assert.That(ex4.InnerException, Is.Null);

            var ex5 = new ConnectionFailedException();

            Assert.That(ex5.Response, Is.EqualTo(null));
            Assert.That(ex5.Message, Is.EqualTo("Failed to connect to the server."));
            Assert.That(ex5.InnerException, Is.Null);
        }
Exemplo n.º 8
0
        ObjectResult RateLimit(RateLimitExceededException exception)
        {
            Logger.LogWarning(exception, "Exceeded GitHub rate limit!");
            var secondsString = Math.Ceiling((exception.Reset - DateTimeOffset.Now).TotalSeconds).ToString(CultureInfo.InvariantCulture);

            Response.Headers.Add("Retry-After", new StringValues(secondsString));
            return(StatusCode(HttpStatusCode.TooManyRequests, new ErrorMessage(ErrorCode.GitHubApiRateLimit)));
        }
        StatusCodeResult RateLimit(RateLimitExceededException exception)
        {
            Logger.LogWarning("Exceeded GitHub rate limit! Exception {0}", exception);
            var secondsString = Math.Ceiling((exception.Reset - DateTimeOffset.Now).TotalSeconds).ToString(CultureInfo.InvariantCulture);

            Response.Headers.Add("Retry-After", new StringValues(secondsString));
            return(StatusCode(429));
        }
Exemplo n.º 10
0
            public void HandlesMissingHeaderValues()
            {
                var response  = new Response(HttpStatusCode.Forbidden, null, new Dictionary <string, string>(), "application/json");
                var exception = new RateLimitExceededException(response);

                Assert.Equal(HttpStatusCode.Forbidden, exception.StatusCode);
                Assert.Equal(0, exception.Limit);
                Assert.Equal(0, exception.Remaining);
                var expectedReset = new DateTimeOffset(DateTime.UtcNow.CeilingSecond());

                Assert.Equal(expectedReset, exception.Reset);
            }
Exemplo n.º 11
0
        /// <summary>
        /// 429 response for a given <paramref name="rateLimitException"/>.
        /// </summary>
        /// <param name="rateLimitException">The <see cref="RateLimitExceededException"/> that occurred.</param>
        /// <returns>A <see cref="HttpStatusCode.TooManyRequests"/> <see cref="ObjectResult"/>.</returns>
        protected ObjectResult RateLimit(RateLimitExceededException rateLimitException)
        {
            if (rateLimitException == null)
            {
                throw new ArgumentNullException(nameof(rateLimitException));
            }

            Logger.LogWarning(rateLimitException, "Exceeded GitHub rate limit!");
            var secondsString = Math.Ceiling((rateLimitException.Reset - DateTimeOffset.UtcNow).TotalSeconds).ToString(CultureInfo.InvariantCulture);

            Response.Headers.Add(HeaderNames.RetryAfter, secondsString);
            return(StatusCode(HttpStatusCode.TooManyRequests, new ErrorMessageResponse(ErrorCode.GitHubApiRateLimit)));
        }
            public void HandlesMissingHeaderValues()
            {
                var response = new Response(HttpStatusCode.Forbidden, null, new Dictionary<string, string>(), "application/json");
                var exception = new RateLimitExceededException(response);

                Assert.Equal(HttpStatusCode.Forbidden, exception.StatusCode);
                Assert.Equal(0, exception.Limit);
                Assert.Equal(0, exception.Remaining);
                var expectedReset = DateTimeOffset.ParseExact(
                    "Thu 01 Jan 1970 0:00:00 AM -00:00",
                    "ddd dd MMM yyyy h:mm:ss tt zzz",
                    CultureInfo.InvariantCulture);
                Assert.Equal(expectedReset, exception.Reset);
            }
Exemplo n.º 13
0
            public void HandlesMissingHeaderValues()
            {
                var response  = CreateResponse(HttpStatusCode.Forbidden);
                var exception = new RateLimitExceededException(response);

                Assert.Equal(HttpStatusCode.Forbidden, exception.StatusCode);
                Assert.Equal(0, exception.Limit);
                Assert.Equal(0, exception.Remaining);
                var expectedReset = DateTimeOffset.ParseExact(
                    "Thu 01 Jan 1970 0:00:00 AM -00:00",
                    "ddd dd MMM yyyy h:mm:ss tt zzz",
                    CultureInfo.InvariantCulture);

                Assert.Equal(expectedReset, exception.Reset);
            }
            public void HandlesMissingHeaderValues()
            {
                var response = new ApiResponse<object>
                {
                    StatusCode = HttpStatusCode.Forbidden
                };
                response.ApiInfo = CreateApiInfo(response);
                var exception = new RateLimitExceededException(response);

                Assert.Equal(HttpStatusCode.Forbidden, exception.StatusCode);
                Assert.Equal(0, exception.Limit);
                Assert.Equal(0, exception.Remaining);
                var expectedReset = DateTimeOffset.ParseExact(
                    "Thu 01 Jan 1970 0:00:00 AM -00:00",
                    "ddd dd MMM yyyy h:mm:ss tt zzz",
                    CultureInfo.InvariantCulture);
                Assert.Equal(expectedReset, exception.Reset);
            }
Exemplo n.º 15
0
            public void HandlesInvalidHeaderValues()
            {
                var headers = new Dictionary <string, string>
                {
                    { "X-RateLimit-Limit", "XXX" },
                    { "X-RateLimit-Remaining", "XXXX" },
                    { "X-RateLimit-Reset", "XXXX" }
                };
                var response = new Response(HttpStatusCode.Forbidden, null, headers, "application/json");

                var exception = new RateLimitExceededException(response);

                Assert.Equal(HttpStatusCode.Forbidden, exception.StatusCode);
                Assert.Equal(0, exception.Limit);
                Assert.Equal(0, exception.Remaining);
                var expectedReset = new DateTimeOffset(DateTime.UtcNow.CeilingSecond());

                Assert.Equal(expectedReset, exception.Reset);
            }
Exemplo n.º 16
0
            public void ParsesRateLimitsFromHeaders()
            {
                var headers = new Dictionary <string, string>
                {
                    { "X-RateLimit-Limit", "100" },
                    { "X-RateLimit-Remaining", "42" },
                    { "X-RateLimit-Reset", "49" }
                };
                var response = new Response(HttpStatusCode.Forbidden, null, headers, "application/json");

                var exception = new RateLimitExceededException(response);

                Assert.Equal(HttpStatusCode.Forbidden, exception.StatusCode);
                Assert.Equal(100, exception.Limit);
                Assert.Equal(42, exception.Remaining);
                var expectedReset = DateTime.UtcNow.CeilingSecond().AddSeconds(49);

                Assert.Equal("API Rate Limit exceeded", exception.Message);
                Assert.Equal(expectedReset, exception.Reset);
            }
            public void ParsesRateLimitsFromHeaders()
            {
                var response = new ApiResponse<object> { StatusCode = HttpStatusCode.Forbidden };
                response.Headers.Add("X-RateLimit-Limit", "100");
                response.Headers.Add("X-RateLimit-Remaining", "42");
                response.Headers.Add("X-RateLimit-Reset", "1372700873");
                response.ApiInfo = CreateApiInfo(response);
                var exception = new RateLimitExceededException(response);

                Assert.Equal(HttpStatusCode.Forbidden, exception.StatusCode);
                Assert.Equal(100, exception.Limit);
                Assert.Equal(42, exception.Remaining);
                var expectedReset = DateTimeOffset.ParseExact(
                    "Mon 01 Jul 2013 5:47:53 PM -00:00",
                    "ddd dd MMM yyyy h:mm:ss tt zzz",
                    CultureInfo.InvariantCulture);
                
                Assert.Equal("API Rate Limit exceeded", exception.Message);
                Assert.Equal(expectedReset, exception.Reset);
            }
Exemplo n.º 18
0
            public void HandlesInvalidHeaderValues()
            {
                var response = new ApiResponse <object> {
                    StatusCode = HttpStatusCode.Forbidden
                };

                response.Headers.Add("X-RateLimit-Limit", "XXX");
                response.Headers.Add("X-RateLimit-Remaining", "XXXX");
                response.Headers.Add("X-RateLimit-Reset", "XXXX");
                response.ApiInfo = CreateApiInfo(response);
                var exception = new RateLimitExceededException(response);

                Assert.Equal(HttpStatusCode.Forbidden, exception.StatusCode);
                Assert.Equal(0, exception.Limit);
                Assert.Equal(0, exception.Remaining);
                var expectedReset = DateTimeOffset.ParseExact(
                    "Thu 01 Jan 1970 0:00:00 AM -00:00",
                    "ddd dd MMM yyyy h:mm:ss tt zzz",
                    CultureInfo.InvariantCulture);

                Assert.Equal(expectedReset, exception.Reset);
            }
            public void ParsesRateLimitsFromHeaders()
            {
                var headers = new Dictionary<string, string>
                {
                    {"X-RateLimit-Limit", "100"},
                    {"X-RateLimit-Remaining", "42"},
                    {"X-RateLimit-Reset", "1372700873"}
                };
                var response = new Response(HttpStatusCode.Forbidden, null, headers, "application/json");

                var exception = new RateLimitExceededException(response);

                Assert.Equal(HttpStatusCode.Forbidden, exception.StatusCode);
                Assert.Equal(100, exception.Limit);
                Assert.Equal(42, exception.Remaining);
                var expectedReset = DateTimeOffset.ParseExact(
                    "Mon 01 Jul 2013 5:47:53 PM -00:00",
                    "ddd dd MMM yyyy h:mm:ss tt zzz",
                    CultureInfo.InvariantCulture);
                Assert.Equal("API Rate Limit exceeded", exception.Message);
                Assert.Equal(expectedReset, exception.Reset);
            }
            public void HandlesInvalidHeaderValues()
            {
                var headers = new Dictionary <string, string>
                {
                    { "X-RateLimit-Limit", "XXX" },
                    { "X-RateLimit-Remaining", "XXXX" },
                    { "X-RateLimit-Reset", "XXXX" }
                };
                var response = new Response(HttpStatusCode.Forbidden, null, headers, "application/json");

                var exception = new RateLimitExceededException(response);

                Assert.Equal(HttpStatusCode.Forbidden, exception.StatusCode);
                Assert.Equal(0, exception.Limit);
                Assert.Equal(0, exception.Remaining);
                var expectedReset = DateTimeOffset.ParseExact(
                    "Thu 01 Jan 1970 0:00:00 AM -00:00",
                    "ddd dd MMM yyyy h:mm:ss tt zzz",
                    CultureInfo.InvariantCulture);

                Assert.Equal(expectedReset, exception.Reset);
            }
Exemplo n.º 21
0
            public void ParsesRateLimitsFromHeaders()
            {
                var response = new ApiResponse <object> {
                    StatusCode = HttpStatusCode.Forbidden
                };

                response.Headers.Add("X-RateLimit-Limit", "100");
                response.Headers.Add("X-RateLimit-Remaining", "42");
                response.Headers.Add("X-RateLimit-Reset", "1372700873");
                response.ApiInfo = CreateApiInfo(response);
                var exception = new RateLimitExceededException(response);

                Assert.Equal(HttpStatusCode.Forbidden, exception.StatusCode);
                Assert.Equal(100, exception.Limit);
                Assert.Equal(42, exception.Remaining);
                var expectedReset = DateTimeOffset.ParseExact(
                    "Mon 01 Jul 2013 5:47:53 PM -00:00",
                    "ddd dd MMM yyyy h:mm:ss tt zzz",
                    CultureInfo.InvariantCulture);

                Assert.Equal("API Rate Limit exceeded", exception.Message);
                Assert.Equal(expectedReset, exception.Reset);
            }
Exemplo n.º 22
0
            public void ReturnsZeroIfSkewedResetInPast()
            {
                var beginTime = DateTimeOffset.Now;
                var resetTime = beginTime - TimeSpan.FromHours(1);

                var response = CreateResponse(HttpStatusCode.Forbidden,
                                              new Dictionary <string, string>
                {
                    ["X-RateLimit-Limit"]     = "100",
                    ["X-RateLimit-Remaining"] = "0",
                    ["X-RateLimit-Reset"]     = resetTime.ToUnixTimeSeconds()
                                                .ToString(CultureInfo.InvariantCulture),
                    ["Date"] = beginTime.ToString("r"),
                    [ApiInfoParser.ReceivedTimeHeaderName] = beginTime.ToString("r"),
                });

                Assert.Equal(TimeSpan.Zero, response.ApiInfo.ServerTimeDifference);
                var except = new RateLimitExceededException(response);

                var timeToReset = except.GetRetryAfterTimeSpan();

                Assert.Equal(TimeSpan.Zero, timeToReset);
            }
Exemplo n.º 23
0
            public void ParsesRateLimitsFromHeaders()
            {
                var headers = new Dictionary <string, string>
                {
                    { "X-RateLimit-Limit", "100" },
                    { "X-RateLimit-Remaining", "42" },
                    { "X-RateLimit-Reset", "1372700873" }
                };
                var response = CreateResponse(HttpStatusCode.Forbidden, headers);

                var exception = new RateLimitExceededException(response);

                Assert.Equal(HttpStatusCode.Forbidden, exception.StatusCode);
                Assert.Equal(100, exception.Limit);
                Assert.Equal(42, exception.Remaining);
                var expectedReset = DateTimeOffset.ParseExact(
                    "Mon 01 Jul 2013 5:47:53 PM -00:00",
                    "ddd dd MMM yyyy h:mm:ss tt zzz",
                    CultureInfo.InvariantCulture);

                Assert.Equal("API Rate Limit exceeded", exception.Message);
                Assert.Equal(expectedReset, exception.Reset);
            }
Exemplo n.º 24
0
        public void Exception_ResponseConstructor()
        {
            var response = new RiotResponse(new HttpResponseMessage(System.Net.HttpStatusCode.OK));

            var ex1 = new RestException(response);

            Assert.That(ex1.Response, Is.EqualTo(response));

            var ex2 = new NotFoundException(response);

            Assert.That(ex2.Response, Is.EqualTo(response));

            var ex3 = new RateLimitExceededException(response);

            Assert.That(ex3.Response, Is.EqualTo(response));

            var ex4 = new RestTimeoutException(response);

            Assert.That(ex4.Response, Is.EqualTo(response));

            var ex5 = new ConnectionFailedException(response);

            Assert.That(ex5.Response, Is.EqualTo(response));
        }
Exemplo n.º 25
0
        public void Exception_ResponseConstructor_NullHttpResponse()
        {
            var response = new RiotResponse(null);

            var ex1 = new RestException(response);

            Assert.That(ex1.Response, Is.EqualTo(response));

            var ex2 = new NotFoundException(response);

            Assert.That(ex2.Response, Is.EqualTo(response));

            var ex3 = new RateLimitExceededException(response);

            Assert.That(ex3.Response, Is.EqualTo(response));

            var ex4 = new RestTimeoutException(response);

            Assert.That(ex4.Response, Is.EqualTo(response));

            var ex5 = new ConnectionFailedException(response);

            Assert.That(ex5.Response, Is.EqualTo(response));
        }
Exemplo n.º 26
0
    public void Is_HaveIBeenPwnedClientException()
    {
        var e = new RateLimitExceededException(1.Seconds());

        Assert.IsAssignableFrom <HaveIBeenPwnedClientException>(e);
    }
Exemplo n.º 27
0
        internal async Task <HttpResponse> GetAsync(string url, CancellationToken token, IProgress <double> progress = null)
        {
            HttpResponseMessage resp = await Client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token).ConfigureAwait(false);

            if ((int)resp.StatusCode == 429)
            {
                var ex = new RateLimitExceededException(resp);
                if (Options.HandleRateLimits == false)
                {
                    throw ex;
                }

                RateLimitInfo info = ex.RateLimit;
                TimeSpan      diff = info.Reset - DateTime.Now;

                int millis = (int)diff.TotalMilliseconds;
                if (millis > 0)
                {
                    await Task.Delay(millis).ConfigureAwait(false);
                }

                return(await GetAsync(url, token, progress).ConfigureAwait(false));
            }

            if (token.IsCancellationRequested)
            {
                throw new TaskCanceledException();
            }

            using MemoryStream ms = new MemoryStream();
            using Stream s        = await resp.Content.ReadAsStreamAsync().ConfigureAwait(false);

            byte[] buffer = new byte[1 << 13];
            int    bytesRead;

            long?contentLength = resp.Content.Headers.ContentLength;
            long totalRead     = 0;

            progress?.Report(0);

            while ((bytesRead = await s.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false)) > 0)
            {
                if (token.IsCancellationRequested)
                {
                    throw new TaskCanceledException();
                }

                if (contentLength != null)
                {
                    double prog = (double)totalRead / (double)contentLength;
                    progress?.Report(prog);
                }

                await ms.WriteAsync(buffer, 0, bytesRead).ConfigureAwait(false);

                totalRead += bytesRead;
            }

            progress?.Report(1);
            byte[] bytes = ms.ToArray();

            return(new HttpResponse(resp, bytes));
        }
            public void CanPopulateObjectFromSerializedData()
            {
                var response = new ApiResponse<object> { StatusCode = HttpStatusCode.Forbidden };
                response.Headers.Add("X-RateLimit-Limit", "100");
                response.Headers.Add("X-RateLimit-Remaining", "42");
                response.Headers.Add("X-RateLimit-Reset", "1372700873");
                response.ApiInfo = CreateApiInfo(response);

                var exception = new RateLimitExceededException(response);

                using (var stream = new MemoryStream())
                {
                    var formatter = new BinaryFormatter();
                    formatter.Serialize(stream, exception);
                    stream.Position = 0;
                    var deserialized = (RateLimitExceededException)formatter.Deserialize(stream);

                    Assert.Equal(HttpStatusCode.Forbidden, deserialized.StatusCode);
                    Assert.Equal(100, deserialized.Limit);
                    Assert.Equal(42, deserialized.Remaining);
                    var expectedReset = DateTimeOffset.ParseExact(
                        "Mon 01 Jul 2013 5:47:53 PM -00:00",
                        "ddd dd MMM yyyy h:mm:ss tt zzz",
                        CultureInfo.InvariantCulture);
                    Assert.Equal(expectedReset, deserialized.Reset);
                }
            }
            public void CanPopulateObjectFromSerializedData()
            {
                var headers = new Dictionary<string, string>{
                    {"X-RateLimit-Limit", "100"},
                    {"X-RateLimit-Remaining", "42"},
                    {"X-RateLimit-Reset", "1372700873"}
                };
                var response = new Response(HttpStatusCode.Forbidden, null, headers, "application/json");

                var exception = new RateLimitExceededException(response);

                using (var stream = new MemoryStream())
                {
                    var formatter = new BinaryFormatter();
                    formatter.Serialize(stream, exception);
                    stream.Position = 0;
                    var deserialized = (RateLimitExceededException)formatter.Deserialize(stream);

                    Assert.Equal(HttpStatusCode.Forbidden, deserialized.StatusCode);
                    Assert.Equal(100, deserialized.Limit);
                    Assert.Equal(42, deserialized.Remaining);
                    var expectedReset = DateTimeOffset.ParseExact(
                        "Mon 01 Jul 2013 5:47:53 PM -00:00",
                        "ddd dd MMM yyyy h:mm:ss tt zzz",
                        CultureInfo.InvariantCulture);
                    Assert.Equal(expectedReset, deserialized.Reset);
                }
            }