public async void ClientRequestsDataFromEachMachineExactlyOnce()
        {
            var request = new TieredRequest
            {
                FanoutTimeoutInMilliseconds = 10,
                MaxFanout = 2
            };

            var allMachines = new List <ServerInfo>();

            foreach (var name in new[] { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j" })
            {
                allMachines.Add(new ServerInfo {
                    Hostname = name, Port = 42
                });
            }
            var seenMachines = new HashSet <ServerInfo>();

            (request.Sources as List <ServerInfo>).AddRange(allMachines);

            DistributedQueryClient.RequesterFactory = new MockHttpRequesterFactory(requestMessage =>
            {
                var requestedSources = MockDataFactory.UnpackRequest <TieredRequest>(requestMessage).Result;
                lock (allMachines)
                {
                    var leaderName = MockDataFactory.ExtractServerInfo(requestMessage.RequestUri);
                    requestedSources.Sources.Add(leaderName);

                    foreach (var name in requestedSources.Sources)
                    {
                        Assert.IsTrue(seenMachines.Add(name));
                    }
                }

                // causes the request to fail (we don't care about the request here, we are just inspecting the request)
                throw new WebException();
            });


            var response = await this.client.CounterQuery("/something", request, null);

            Assert.IsNotNull(response);
            Assert.AreEqual(allMachines.Count, seenMachines.Count);
            Assert.IsTrue(allMachines.All(seenMachines.Contains));
        }
        public async void MixedStatusAndFailureResponses()
        {
            var       nfcChampionship  = new DateTime(2015, 01, 18);
            const int numSampleBuckets = 10;

            int callbackNumber = 0;

            // N - 1 successes. 1 failure (timeout)
            DistributedQueryClient.RequesterFactory = new MockHttpRequesterFactory(requestMessage =>
            {
                var isFirst = Interlocked.Increment(ref callbackNumber) == 1;
                if (isFirst)
                {
                    throw new OperationCanceledException("timed out");
                }

                return(MockDataFactory.CreateGoodHitCountResponse(
                           requestMessage,
                           nfcChampionship,
                           numSampleBuckets).Result);
            });


            const int maxFanout                   = 3;
            const int totalMachinesToQuery        = 9;
            const int machinesToSucceed           = totalMachinesToQuery - maxFanout;
            const int machinesToTimeout           = 1;
            const int machinesWithFederationError = totalMachinesToQuery - machinesToSucceed - machinesToTimeout;

            var response = await this.client.CounterQuery("/something", CreateRequest(totalMachinesToQuery, maxFanout), null);

            Assert.IsNotNull(response);

            Assert.AreEqual(totalMachinesToQuery, response.RequestDetails.Count);
            Assert.AreEqual(machinesToSucceed, response.RequestDetails.Count(s => s.Status == RequestStatus.Success));
            Assert.AreEqual(machinesToTimeout, response.RequestDetails.Count(s => s.Status == RequestStatus.TimedOut));
            Assert.AreEqual(machinesWithFederationError, response.RequestDetails.Count(s => s.Status == RequestStatus.FederationError));

            Assert.AreEqual(numSampleBuckets, response.Samples.Count);
            Assert.IsTrue(response.Samples.All(sample => sample.HitCount == machinesToSucceed));
        }
        public async void DistributedQueryClientStripsPercentileOutOfQueryParameter()
        {
            bool didTestPass = false;

            DistributedQueryClient.RequesterFactory = new MockHttpRequesterFactory(requestMessage =>
            {
                Assert.AreEqual(string.Empty, requestMessage.RequestUri.Query);
                didTestPass = true;
                return(MockDataFactory.CreateFailedTieredResponse("me", HttpStatusCode.BadRequest));
            });

            // ensure the distributed client removed the 'percentile = xxx' parameter in the request
            var response =
                await
                this.client.CounterQuery("/something", CreateRequest(10, 5),
                                         new Dictionary <string, string> {
                { "Percentile", "45.1243" }
            });

            Assert.IsNotNull(response);

            Assert.IsTrue(didTestPass);
        }
        private static async Task <HttpResponseMessage> GenerateFailureResponse(HttpRequestMessage request,
                                                                                HttpStatusCode responseCode,
                                                                                RequestStatus statusForDownstreamSources)
        {
            var requestMessage = await MockDataFactory.UnpackRequest <TieredRequest>(request);

            var responseContent = new CounterQueryResponse();

            responseContent.RequestDetails = requestMessage.Sources.Select(source =>
                                                                           new RequestDetails
            {
                Server = source,
                Status = statusForDownstreamSources
            }).ToList();

            // add one for the leader
            responseContent.RequestDetails.Add(new RequestDetails
            {
                Server           = MockDataFactory.ExtractServerInfo(request.RequestUri),
                Status           = RequestStatus.ServerFailureResponse,
                HttpResponseCode = (short)responseCode
            });
            return(MockDataFactory.CreateResponse(responseContent, responseCode));
        }
        public async void DataIsMergedProperly()
        {
            var       nfcChampionship  = new DateTime(2015, 01, 18);
            const int numSampleBuckets = 10;

            DistributedQueryClient.RequesterFactory = new MockHttpRequesterFactory(requestMessage => MockDataFactory.CreateGoodHitCountResponse(
                                                                                       requestMessage,
                                                                                       nfcChampionship,
                                                                                       numSampleBuckets).Result);

            const int maxFanout            = 2;
            const int totalMachinesToQuery = 10;

            var response = await this.client.CounterQuery("/something", CreateRequest(totalMachinesToQuery, maxFanout), null);

            Assert.IsNotNull(response);

            Assert.AreEqual(totalMachinesToQuery, response.RequestDetails.Count);
            Assert.AreEqual(totalMachinesToQuery, response.RequestDetails.Count(s => s.Status == RequestStatus.Success));

            Assert.AreEqual(numSampleBuckets, response.Samples.Count);
            Assert.IsTrue(response.Samples.All(sample => sample.HitCount == totalMachinesToQuery));
        }