public void GetFavouriteDelta_should_return_lowest_hash_when_candidate_scores_are_equal() { using (var realCache = new MemoryCache(new MemoryCacheOptions())) { _voter = new DeltaVoter(realCache, _producersProvider, _peerSettings, _logger); var scoredCandidates = AddCandidatesToCacheAndVote(10, 110, realCache); scoredCandidates.Select(c => c.Score).Distinct().Count().Should().Be(1); scoredCandidates.Select(c => c.Candidate.Hash).Distinct().Count().Should().Be(2); scoredCandidates.Select(c => c.Candidate.PreviousDeltaDfsHash).Distinct().Count().Should().Be(1); var found = _voter.TryGetFavouriteDelta( scoredCandidates.First().Candidate.PreviousDeltaDfsHash.ToByteArray().ToCid(), out var favouriteCandidate); found.Should().BeTrue(); var expectedFavourite = scoredCandidates .OrderBy(c => c.Candidate.Hash.ToByteArray(), ByteUtil.ByteListMinSizeComparer.Default) .First(); // ReSharper disable once ReturnValueOfPureMethodIsNotUsed favouriteCandidate.Candidate.Hash.Equals(expectedFavourite.Candidate.Hash); } }
private List <IScoredCandidateDelta> AddCandidatesToCacheAndVote(int firstVotesCount, int secondVotesCount, MemoryCache realCache) { var firstCandidate = DeltaHelper.GetCandidateDelta(_hashProvider, _previousDeltaHash, producerId: _producerIds.First()); var secondCandidate = DeltaHelper.GetCandidateDelta(_hashProvider, _previousDeltaHash, producerId: _producerIds.Skip(1).First()); var candidateStream = Enumerable.Repeat(firstCandidate, firstVotesCount) .Concat(Enumerable.Repeat(secondCandidate, secondVotesCount)) .Shuffle().ToObservable(); using (candidateStream.Subscribe(_voter)) { var firstKey = DeltaVoter.GetCandidateCacheKey(firstCandidate); var secondKey = DeltaVoter.GetCandidateCacheKey(secondCandidate); realCache.TryGetValue(firstKey, out IScoredCandidateDelta firstRetrieved).Should().BeTrue(); realCache.TryGetValue(secondKey, out IScoredCandidateDelta secondRetrieved).Should().BeTrue(); return(new List <IScoredCandidateDelta> { firstRetrieved, secondRetrieved }); } }
public void When_candidate_in_cache_should_retrieve_ScoredCandidate() { _voter = new DeltaVoter(_cache, _producersProvider, _peerSettings, _logger); var initialScore = 10; var cacheCandidate = ScoredCandidateDeltaHelper.GetScoredCandidateDelta( _hashProvider, producerId: _producerIds.First(), previousDeltaHash: _previousDeltaHash, score: initialScore); var candidateHash = cacheCandidate.Candidate.Hash.ToByteArray().ToCid(); _cache.TryGetValue(Arg.Any <string>(), out Arg.Any <object>()).Returns(ci => { ci[1] = cacheCandidate; return(true); }); _voter.OnNext(cacheCandidate.Candidate); _cache.Received(1) .TryGetValue(Arg.Is <string>(s => s.EndsWith(candidateHash)), out Arg.Any <object>()); _cache.DidNotReceiveWithAnyArgs().CreateEntry(Arg.Any <string>()); cacheCandidate.Score.Should().Be(initialScore + 1); }
public void When_candidate_not_in_cache_should_build_ScoredCandidate_with_ranking_and_store_it() { _voter = new DeltaVoter(_cache, _producersProvider, _peerSettings, _logger); var candidate = DeltaHelper.GetCandidateDelta(_hashProvider, _previousDeltaHash, producerId: _producerIds.First()); var candidateHash = candidate.Hash.ToByteArray().ToCid(); var addedEntry = Substitute.For <ICacheEntry>(); _cache.CreateEntry(Arg.Is <string>(s => s.EndsWith(candidateHash))) .Returns(addedEntry); _voter.OnNext(candidate); _cache.Received(1) .TryGetValue(Arg.Is <string>(s => s.EndsWith(candidateHash)), out Arg.Any <object>()); _cache.ReceivedWithAnyArgs(2).CreateEntry(Arg.Any <object>()); _cache.Received(1).CreateEntry(Arg.Is <string>(s => s.EndsWith(candidateHash))); addedEntry.Value.Should().BeAssignableTo <IScoredCandidateDelta>(); var scoredCandidateDelta = (IScoredCandidateDelta)addedEntry.Value; scoredCandidateDelta.Candidate.Hash.SequenceEqual(candidate.Hash).Should().BeTrue(); scoredCandidateDelta.Score.Should().Be(100 * _producerIds.Count + 1); }
public void When_candidate_is_empty_should_log_and_return_without_hitting_the_cache() { _voter = new DeltaVoter(_cache, _producersProvider, _peerSettings, _logger); _voter.OnNext(new CandidateDeltaBroadcast()); _cache.DidNotReceiveWithAnyArgs().TryGetValue(Arg.Any <object>(), out Arg.Any <object>()); _cache.DidNotReceiveWithAnyArgs().CreateEntry(Arg.Any <object>()); }
public void When_candidate_hash_is_empty_should_log_and_return_without_hitting_the_cache() { _voter = new DeltaVoter(_cache, _producersProvider, _peerSettings, _logger); _voter.OnNext(new CandidateDeltaBroadcast { PreviousDeltaDfsHash = ByteUtil.GenerateRandomByteArray(32).ToByteString(), ProducerId = PeerIdHelper.GetPeerId("unknown_producer") }); _cache.DidNotReceiveWithAnyArgs().TryGetValue(Arg.Any <object>(), out Arg.Any <object>()); _cache.DidNotReceiveWithAnyArgs().CreateEntry(Arg.Any <object>()); }
public void When_candidate_is_produced_by_unexpected_producer_should_log_and_return_without_hitting_the_cache() { var candidateFromUnknownProducer = DeltaHelper.GetCandidateDelta(_hashProvider, producerId: PeerIdHelper.GetPeerId("unknown_producer")); _voter = new DeltaVoter(_cache, _producersProvider, _peerSettings, _logger); _voter.OnNext(candidateFromUnknownProducer); _logger.Received(1).Error(Arg.Is <Exception>(e => e is KeyNotFoundException), Arg.Any <string>(), Arg.Any <CandidateDeltaBroadcast>()); _cache.DidNotReceiveWithAnyArgs().TryGetValue(Arg.Any <object>(), out Arg.Any <object>()); _cache.DidNotReceiveWithAnyArgs().CreateEntry(Arg.Any <object>()); }
public void GetFavouriteDelta_should_return_null_on_unknown_previous_delta_hash() { using (var realCache = new MemoryCache(new MemoryCacheOptions())) { _voter = new DeltaVoter(realCache, _producersProvider, _peerSettings, _logger); AddCandidatesToCacheAndVote(10, 500, realCache); var found = _voter.TryGetFavouriteDelta(_hashProvider.ComputeMultiHash(ByteUtil.GenerateRandomByteArray(32)), out var favouriteCandidate); found.Should().BeFalse(); favouriteCandidate.Should().BeNull(); } }
public void When_second_candidate_is_more_popular_it_should_score_higher() { using (var realCache = new MemoryCache(new MemoryCacheOptions())) { _voter = new DeltaVoter(realCache, _producersProvider, _peerSettings, _logger); var firstVotesCount = 10; var secondVotesCount = 100 + 100 / 2; var retrievedCandidates = AddCandidatesToCacheAndVote(firstVotesCount, secondVotesCount, realCache); retrievedCandidates[0].Score.Should().Be(100 * _producerIds.Count + firstVotesCount); retrievedCandidates[1].Score.Should().Be(100 * (_producerIds.Count - 1) + secondVotesCount); } }
public void When_candidates_not_in_cache_should_create_or_update_a_previous_hash_entry() { using (var realCache = new MemoryCache(new MemoryCacheOptions())) { _voter = new DeltaVoter(realCache, _producersProvider, _peerSettings, _logger); var candidate1 = DeltaHelper.GetCandidateDelta( _hashProvider, _previousDeltaHash, producerId: _producerIds.First()); var candidate1CacheKey = DeltaVoter.GetCandidateCacheKey(candidate1); var candidate2 = DeltaHelper.GetCandidateDelta( _hashProvider, _previousDeltaHash, producerId: _producerIds.Last()); var candidate2CacheKey = DeltaVoter.GetCandidateCacheKey(candidate2); var previousDeltaCacheKey = DeltaVoter.GetCandidateListCacheKey(candidate1); _voter.OnNext(candidate1); realCache.TryGetValue(candidate1CacheKey, out ScoredCandidateDelta retrievedCandidate1).Should().BeTrue(); retrievedCandidate1.Candidate.ProducerId.Should().Be(_producerIds.First()); realCache.TryGetValue(previousDeltaCacheKey, out ConcurrentBag <string> retrievedCandidateList).Should().BeTrue(); retrievedCandidateList.Should().BeEquivalentTo(candidate1CacheKey); _voter.OnNext(candidate2); realCache.TryGetValue(candidate2CacheKey, out ScoredCandidateDelta retrievedCandidate2).Should().BeTrue(); retrievedCandidate2.Candidate.ProducerId.Should().Be(_producerIds.Last()); realCache.TryGetValue(previousDeltaCacheKey, out ConcurrentBag <string> retrievedUpdatedCandidateList).Should().BeTrue(); retrievedUpdatedCandidateList.Should().BeEquivalentTo(candidate1CacheKey, candidate2CacheKey); } }
public void GetFavouriteDelta_should_retrieve_favourite_delta() { using (var realCache = new MemoryCache(new MemoryCacheOptions())) { _voter = new DeltaVoter(realCache, _producersProvider, _peerSettings, _logger); var scoredCandidates = AddCandidatesToCacheAndVote(10, 500, realCache); scoredCandidates[1].Score.Should().BeGreaterThan(scoredCandidates[0].Score); var previousDeltaHash = _hashProvider.Cast(scoredCandidates[0].Candidate.PreviousDeltaDfsHash.ToByteArray()); var found = _voter.TryGetFavouriteDelta(previousDeltaHash, out var favouriteCandidate); found.Should().BeTrue(); favouriteCandidate.Candidate.PreviousDeltaDfsHash.ToByteArray().SequenceEqual(previousDeltaHash.ToArray()).Should().BeTrue(); favouriteCandidate.Candidate.Hash.ToByteArray().SequenceEqual(scoredCandidates[1].Candidate.Hash.ToByteArray()).Should().BeTrue(); favouriteCandidate.Candidate.ProducerId.Should().Be(scoredCandidates[1].Candidate.ProducerId); } }