public void Modify_should_calculate_weights_for_each_replica_in_cluster_statistic()
        {
            var _         = 0d;
            var timestamp = DateTime.UtcNow;

            clusterState.LastUpdateTimestamp = timestamp;
            clusterState.TimeProvider.GetCurrentTime().Returns(timestamp + settings.WeightUpdatePeriod + 1.Seconds());
            var r1 = (new Uri("http://r1"), new AggregatedStatistic(10, 0.2, 12, 150, timestamp), new Weight(0.5, timestamp));
            var r2 = (new Uri("http://r2"), new AggregatedStatistic(10, 0.2, 15, 120, timestamp), new Weight(0.7, timestamp));
            var r3 = (new Uri("http://r3"), new AggregatedStatistic(10, 0.2, 15, 110, timestamp), new Weight(0.1, timestamp));
            var clusterStatistic = new AggregatedClusterStatistic(new AggregatedStatistic(10, 0.2, 13, 130, timestamp), new Dictionary <Uri, AggregatedStatistic>()
            {
                [r1.Item1] = r1.Item2,
                [r2.Item1] = r2.Item2,
                [r3.Item1] = r3.Item2,
            });

            clusterState.CurrentStatistic.GetPenalizedAndSmoothedStatistic(Arg.Any <DateTime>(), Arg.Any <AggregatedClusterStatistic>(), settings.PenaltyMultiplier, settings.StatisticSmoothingConstant)
            .Returns(clusterStatistic);
            clusterState.RelativeWeightCalculator.Calculate(clusterStatistic.Cluster, r1.Item2, Arg.Any <Weight>(), settings).Returns(r1.Item3);
            clusterState.RelativeWeightCalculator.Calculate(clusterStatistic.Cluster, r2.Item2, Arg.Any <Weight>(), settings).Returns(r2.Item3);
            clusterState.RelativeWeightCalculator.Calculate(clusterStatistic.Cluster, r3.Item2, Arg.Any <Weight>(), settings).Returns(r3.Item3);

            relativeWeightModifier.Modify(r1.Item1, new List <Uri>(), replicaStorageProvider, Request.Get(""), RequestParameters.Empty, ref _);

            clusterState.RelativeWeightCalculator.Received(1).Calculate(clusterStatistic.Cluster, clusterStatistic.Replicas[r1.Item1], Arg.Any <Weight>(), settings);
            clusterState.RelativeWeightCalculator.Received(1).Calculate(clusterStatistic.Cluster, clusterStatistic.Replicas[r2.Item1], Arg.Any <Weight>(), settings);
            clusterState.RelativeWeightCalculator.Received(1).Calculate(clusterStatistic.Cluster, clusterStatistic.Replicas[r3.Item1], Arg.Any <Weight>(), settings);
        }
        public void Modify_should_update_statistics_history()
        {
            var _         = 0d;
            var timestamp = DateTime.UtcNow;

            clusterState.LastUpdateTimestamp = timestamp;
            clusterState.TimeProvider.GetCurrentTime().Returns(timestamp + settings.WeightUpdatePeriod + 1.Seconds());
            var clusterStatistic = new AggregatedClusterStatistic(new AggregatedStatistic(10, 0.2, 13, 130, timestamp), new Dictionary <Uri, AggregatedStatistic>());

            clusterState.CurrentStatistic.GetPenalizedAndSmoothedStatistic(Arg.Any <DateTime>(), Arg.Any <AggregatedClusterStatistic>(), settings.PenaltyMultiplier, settings.StatisticSmoothingConstant)
            .Returns(clusterStatistic);

            relativeWeightModifier.Modify(new Uri("http://replica1"), new List <Uri>(), replicaStorageProvider, Request.Get(""), RequestParameters.Empty, ref _);

            clusterState.StatisticHistory.Received(1).Update(clusterStatistic, settings.StatisticTTL);
        }
        public void Modify_should_normalize_only_new_weights()
        {
            var _         = 0d;
            var timestamp = DateTime.UtcNow;

            clusterState.LastUpdateTimestamp = timestamp;
            clusterState.TimeProvider.GetCurrentTime().Returns(timestamp + settings.WeightUpdatePeriod + 1.Seconds());
            var r1 = (new Uri("http://r1"), new AggregatedStatistic(10, 0.2, 12, 150, timestamp));
            var r2 = (new Uri("http://r2"), new AggregatedStatistic(10, 0.2, 15, 120, timestamp));
            var r3 = (new Uri("http://r3"), new AggregatedStatistic(10, 0.2, 15, 110, timestamp));
            var clusterStatistic = new AggregatedClusterStatistic(new AggregatedStatistic(10, 0.2, 13, 130, timestamp), new Dictionary <Uri, AggregatedStatistic>()
            {
                [r1.Item1] = r1.Item2,
                [r2.Item1] = r2.Item2,
                [r3.Item1] = r3.Item2,
            });
            Dictionary <Uri, Weight> weightsPassedToWeightsNormalizer = null;

            clusterState.WeightsNormalizer
            .When(normalizer => normalizer.Normalize(Arg.Any <Dictionary <Uri, Weight> >(), Arg.Any <double>()))
            .Do(info => weightsPassedToWeightsNormalizer = info.Arg <Dictionary <Uri, Weight> >());
            clusterState.CurrentStatistic
            .GetPenalizedAndSmoothedStatistic(Arg.Any <DateTime>(), Arg.Any <AggregatedClusterStatistic>(), settings.PenaltyMultiplier, settings.StatisticSmoothingConstant).Returns(clusterStatistic);

            relativeWeightModifier.Modify(
                r1.Item1,
                new List <Uri> {
                r1.Item1, r2.Item1, r3.Item1, new Uri("http://newReplica")
            },
                replicaStorageProvider,
                Request.Get(""),
                RequestParameters.Empty, ref _);

            weightsPassedToWeightsNormalizer.Should().NotBeNull();
            weightsPassedToWeightsNormalizer.Count.Should().Be(3);
            weightsPassedToWeightsNormalizer.ContainsKey(r1.Item1).Should().BeTrue();
            weightsPassedToWeightsNormalizer.ContainsKey(r2.Item1).Should().BeTrue();
            weightsPassedToWeightsNormalizer.ContainsKey(r3.Item1).Should().BeTrue();
        }