public async Task CanAddPolicies_ThreeWays()
        {
            var mockTransport = new MockTransport(new MockResponse(200));

            var clientOptions = new TestOptions()
            {
                Transport = mockTransport,
            };
            var perCallPolicies  = new HttpPipelinePolicy[] { new AddHeaderPolicy("PerCall", "Builder") };
            var perRetryPolicies = new HttpPipelinePolicy[] { new AddHeaderPolicy("PerRetry", "Builder") };

            clientOptions.AddPolicy(new AddHeaderPolicy("BeforeTransport", "ClientOptions"), HttpPipelinePosition.BeforeTransport);
            clientOptions.AddPolicy(new AddHeaderPolicy("PerRetry", "ClientOptions"), HttpPipelinePosition.PerRetry);
            clientOptions.AddPolicy(new AddHeaderPolicy("PerCall", "ClientOptions"), HttpPipelinePosition.PerCall);

            var pipeline = HttpPipelineBuilder.Build(clientOptions, perCallPolicies, perRetryPolicies, null);

            var options = new RequestOptions();

            options.AddPolicy(new AddHeaderPolicy("PerRetry", "RequestContext"), HttpPipelinePosition.PerRetry);
            options.AddPolicy(new AddHeaderPolicy("PerCall", "RequestContext"), HttpPipelinePosition.PerCall);
            options.AddPolicy(new AddHeaderPolicy("BeforeTransport", "RequestContext"), HttpPipelinePosition.BeforeTransport);

            var context = new RequestContext(options);

            context.CancellationToken = default;
            var message = pipeline.CreateMessage(context);
            await pipeline.SendAsync(message, message.CancellationToken);

            Request request = mockTransport.Requests[0];

            Assert.IsTrue(request.Headers.TryGetValues("PerCall", out var perCallValues));
            Assert.AreEqual(3, perCallValues.Count());
            Assert.AreEqual("Builder", perCallValues.ElementAt(0));
            Assert.AreEqual("ClientOptions", perCallValues.ElementAt(1));
            Assert.AreEqual("RequestContext", perCallValues.ElementAt(2));

            Assert.IsTrue(request.Headers.TryGetValues("PerRetry", out var perRetryValues));
            Assert.AreEqual(3, perRetryValues.Count());
            Assert.AreEqual("Builder", perRetryValues.ElementAt(0));
            Assert.AreEqual("ClientOptions", perRetryValues.ElementAt(1));
            Assert.AreEqual("RequestContext", perRetryValues.ElementAt(2));

            Assert.IsTrue(request.Headers.TryGetValues("BeforeTransport", out var beforeTransportValues));
            Assert.AreEqual(2, beforeTransportValues.Count());
            Assert.AreEqual("ClientOptions", beforeTransportValues.ElementAt(0));
            Assert.AreEqual("RequestContext", beforeTransportValues.ElementAt(1));
        }
        public async Task CustomClientRequestIdSetInPerCallPolicyAppliedAsAHeader()
        {
            var policy = new Mock <HttpPipelineSynchronousPolicy>();

            policy.CallBase = true;
            policy.Setup(p => p.OnSendingRequest(It.IsAny <HttpMessage>()))
            .Callback <HttpMessage>(message =>
            {
                message.Request.ClientRequestId = "MyPolicyClientId";
            }).Verifiable();

            var options   = new TestOptions();
            var transport = new MockTransport(new MockResponse(200));

            options.Transport = transport;
            options.AddPolicy(policy.Object, HttpPipelinePosition.PerCall);

            var pipeline = HttpPipelineBuilder.Build(options);

            using (Request request = pipeline.CreateRequest())
            {
                request.Method = RequestMethod.Get;
                request.Uri.Reset(new Uri("http://example.com"));
                request.Headers.Add("x-ms-client-request-id", "ExternalClientId");
                await pipeline.SendRequestAsync(request, CancellationToken.None);
            }

            policy.Verify();

            Assert.True(transport.SingleRequest.Headers.TryGetValue("x-ms-client-request-id", out var value));
            Assert.AreEqual("MyPolicyClientId", value);
        }
        public async Task CustomPolicyOrdering()
        {
            bool perCallRan         = false;
            bool perRetryRan        = false;
            bool beforeTransportRan = false;

            var transport = new MockTransport(new MockResponse(200));
            var options   = new TestOptions();

            options.AddPolicy(new CallbackPolicy(m =>
            {
                perCallRan = true;
                Assert.False(perRetryRan);
                Assert.False(beforeTransportRan);
            }), HttpPipelinePosition.PerCall);

            options.AddPolicy(new CallbackPolicy(m =>
            {
                perRetryRan = true;
                Assert.True(perCallRan);
                Assert.False(beforeTransportRan);
            }), HttpPipelinePosition.PerRetry);

            options.AddPolicy(new CallbackPolicy(m =>
            {
                beforeTransportRan = true;
                Assert.True(perRetryRan);
                Assert.True(perCallRan);
            }), HttpPipelinePosition.BeforeTransport);

            options.Transport = transport;

            HttpPipeline pipeline = HttpPipelineBuilder.Build(options);

            using Request request = transport.CreateRequest();
            request.Method        = RequestMethod.Get;
            request.Uri.Reset(new Uri("http://example.com"));

            await pipeline.SendRequestAsync(request, CancellationToken.None);

            Assert.True(perRetryRan);
            Assert.True(perCallRan);
            Assert.True(beforeTransportRan);
        }
        public async Task CanAddCustomPolicy(HttpPipelinePosition position, int expectedCount)
        {
            var policy    = new CounterPolicy();
            var transport = new MockTransport(new MockResponse(503), new MockResponse(200));

            var options = new TestOptions();

            options.AddPolicy(policy, position);
            options.Transport = transport;

            HttpPipeline pipeline = HttpPipelineBuilder.Build(options);

            using Request request = transport.CreateRequest();
            request.Method        = RequestMethod.Get;
            request.Uri.Reset(new Uri("http://example.com"));

            Response response = await pipeline.SendRequestAsync(request, CancellationToken.None);

            Assert.AreEqual(200, response.Status);
            Assert.AreEqual(expectedCount, policy.ExecutionCount);
        }