public void ExecuteAsync_Error()
        {
            var handler     = new ErrorMessageHanlder();
            var initializer = new BaseClientService.Initializer
            {
                HttpClientFactory = new MockHttpClientFactory(handler)
            };

            using (var service = new MockClientService(initializer))
            {
                var            request    = new TestClientServiceRequest(service, "GET", null);
                AutoResetEvent resetEvent = new AutoResetEvent(false);
                var            task       = request.ExecuteAsync();
                var            error      = string.Empty;
                task.ContinueWith(t =>
                {
                    // should not ENTER this code, the task should fail
                    resetEvent.Set();
                }, TaskContinuationOptions.OnlyOnRanToCompletion);
                task.ContinueWith(t =>
                {
                    // catch the error
                    error = t.Exception.InnerException.ToString();
                    resetEvent.Set();
                }, TaskContinuationOptions.NotOnRanToCompletion);
                resetEvent.WaitOne();
                Assert.True(error.Contains(handler.ExpectedError), "Error message is invalid");
                Assert.That(handler.Calls, Is.EqualTo(1));
            }
        }
        /// <summary>
        /// A subtest for testing async execute when an exception is thrown during sending the request, with or without
        /// back-off handler. If back-off handler is attached to the service's message handler, there are going to be
        /// several retries (up to 2 minutes).
        /// </summary>
        /// <param name="backOff">Indicates if back-off handler is attached to the service.</param>
        private void SubtestExecuteAsync_ThrowException(bool backOff)
        {
            var handler     = new MockMessageHandler(true);
            var initializer = new BaseClientService.Initializer()
            {
                HttpClientFactory = new MockHttpClientFactory(handler)
            };

            // by default back-off is used, so disable it in case backOff is false
            if (!backOff)
            {
                initializer.DefaultExponentialBackOffPolicy = BaseClientService.ExponentialBackOffPolicy.None;
            }

            using (var service = new MockClientService(initializer))
            {
                var request = new TestClientServiceRequest(service, "GET", null);
                var task    = request.ExecuteAsync();
                try
                {
                    var result = task.Result;
                    Assert.Fail("Exception should be thrown");
                }
                catch (AggregateException ex)
                {
                    Assert.That(ex.InnerException, Is.AssignableFrom(typeof(InvalidOperationMockException)));
                }

                // if back-off is enabled, we use 2 minutes maximum wait time for a request, so we should make lg(120)
                // + 1 calls
                int calls = backOff ? (int)Math.Ceiling(Math.Log(120, 2) + 1) : 1;
                Assert.That(handler.Calls, Is.EqualTo(calls));
            }
        }
Example #3
0
        /// <summary>
        /// A subtest for testing ExecuteAsync  when an exception is thrown while sending the request. This is tested
        /// with and without back-off. If back-off handler is attached to the service's message handler, there should
        /// be 3 tries (the default value of <seealso cref="ConfigurableMessageHandler.NumTries"/>) before the
        /// operation fails.
        /// </summary>
        /// <param name="backOff">Indicates if back-off handler is attached to the service.</param>
        private void SubtestExecuteAsync_ThrowException(bool backOff)
        {
            var handler     = new MockMessageHandler(true);
            var initializer = new BaseClientService.Initializer()
            {
                HttpClientFactory = new MockHttpClientFactory(handler)
            };

            // Configure the back-off behavior by the input.
            initializer.DefaultExponentialBackOffPolicy = backOff ?
                                                          ExponentialBackOffPolicy.Exception : ExponentialBackOffPolicy.None;

            using (var service = new MockClientService(initializer))
            {
                var request = new TestClientServiceRequest(service, "GET", null);
                var task    = request.ExecuteAsync();
                try
                {
                    var result = task.Result;
                    Assert.Fail("Exception should be thrown");
                }
                catch (AggregateException ex)
                {
                    Assert.That(ex.InnerException, Is.AssignableFrom(typeof(InvalidOperationMockException)));
                }

                int calls = backOff ? service.HttpClient.MessageHandler.NumTries : 1;
                Assert.That(handler.Calls, Is.EqualTo(calls));
            }
        }
        /// <summary> A subtest for testing GZip and sync-async calls. </summary>
        private void SubtestExecute_GZip(bool gzip, bool async)
        {
            var handler = new TestBodyMessageHnalder()
            {
                GZipEnabled    = gzip,
                ResponseObject = new MockResponse {
                    Id = 100, Name = "sample name"
                },
                ExpectedRequestObject = new MockRequest {
                    Name = "long long name"
                }
            };
            var initializer = new BaseClientService.Initializer()
            {
                GZipEnabled       = gzip,
                HttpClientFactory = new MockHttpClientFactory(handler)
            };

            using (var service = new MockClientService(initializer))
            {
                handler.Serializer = service.Serializer;

                var          request  = new TestClientServiceRequest(service, "POST", handler.ExpectedRequestObject);
                MockResponse response = null;
                if (async)
                {
                    var task = request.ExecuteAsync();
                    response = task.Result;
                    Assert.AreNotEqual(Thread.CurrentThread.ManagedThreadId, handler.ThreadId);
                }
                else
                {
                    response = request.Execute();
                    Assert.AreEqual(Thread.CurrentThread.ManagedThreadId, handler.ThreadId);
                }

                // NOTICE: even if GZipEnabled is true, we don't need to extract the real string from the GZip stream,
                // because in a real request we use HttpClientHandler which its AutomaticDecompression is set to
                // System.Net.DecompressionMethods.GZip.

                Assert.That(handler.Calls, Is.EqualTo(1));
                // the returned response should contain ETag, check that the service add the right ETag property on
                // the response
                handler.ResponseObject.ETag = handler.ResponseETag;
                Assert.That(response, Is.EqualTo(handler.ResponseObject));
            }
        }
        public void ExecuteAsync_Simultaneously()
        {
            var tasks       = new List <Task <MockResponse> >();
            var handler     = new ConcurrentCallsHandler();
            var initializer = new BaseClientService.Initializer()
            {
                HttpClientFactory     = new MockHttpClientFactory(handler),
                HttpClientInitializer = new ConcurrentCallsHandler.Initializer()
            };

            using (var service = new MockClientService(initializer))
            {
                int calls = 100;
                handler.Serializer = service.Serializer;

                CountdownEvent ce = new CountdownEvent(calls);
                foreach (var i in Enumerable.Range(1, calls))
                {
                    var request = new TestClientServiceRequest(service, "GET", null)
                    {
                        CallNum = i
                    };
                    var task = request.ExecuteAsync();
                    task.ContinueWith(c => ce.Signal());
                    tasks.Add(task);
                }
                ce.Wait();

                for (var i = 1; i <= tasks.Count; ++i)
                {
                    var response = tasks[i - 1].Result;

                    // check that we got the right response. Name should be equal to the index number modulo 10 (or
                    // index number plus one module 10, if it's an even request - because even request should fail in
                    // the first request, but should succeed in the next try). That's the logic of our
                    // ConcurrentCallHandler, see it core SendAsyncCore method to understand better the logic
                    var nameIndex = ((i % 2 == 0) ? i + 1 : i) % 10;
                    Assert.That(response.Name, Is.EqualTo("Name-" + nameIndex));
                }

                // half of the request should succeed in the second call, so total calls should be calls + calls/2
                Assert.That(handler.Calls, Is.EqualTo(calls + calls / 2));
            }
        }
Example #6
0
        /// <summary>
        /// Test helper to test canceling token in a middle of a request to the server
        /// </summary>
        /// <param name="cancelRequestNum">
        /// The index of the "server"'s request which a cancel token will be mimic.
        /// </param>
        private void SubtestExecuteAsync_Cancel(int cancelRequestNum)
        {
            var handler = new CancelRedirectMessageHandler();

            handler.CancellationTokenSource = new CancellationTokenSource();
            handler.CancelRequestNum        = cancelRequestNum;

            var initializer = new BaseClientService.Initializer()
            {
                HttpClientFactory = new MockHttpClientFactory(handler)
            };

            TestClientServiceRequest request;

            using (var service = new MockClientService(initializer))
            {
                request = new TestClientServiceRequest(service, "POST", new MockRequest());
                try
                {
                    request.ExecuteAsync(handler.CancellationTokenSource.Token).Wait();
                    Assert.Fail();
                }
                catch (AggregateException ex)
                {
                    if (ex.InnerException is TaskCanceledException)
                    {
                        // We expect a task canceled exception in case the canceled request is less or equal total
                        // number of retries.
                        Assert.False(cancelRequestNum > service.HttpClient.MessageHandler.NumRedirects + 1);
                    }
                    else
                    {
                        // Canceled exception wasn't thrown, in that case the cancel request number is bigger than
                        // the actual number of tries.
                        Assert.True(cancelRequestNum > service.HttpClient.MessageHandler.NumTries + 1);
                    }
                }

                var expectedCalls = Math.Min(service.HttpClient.MessageHandler.NumRedirects + 1, cancelRequestNum);
                Assert.That(handler.Calls, Is.EqualTo(expectedCalls));
            }
        }