public async Task CreatesSnapshotAsALeader() { _settings.MinSnapshottingIndexInterval = 10L; _manijer.Setup(x => x.GetPeers()).Returns(new[] { "1", "3", "5", "7" }.Select(s => new Peer(s, Guid.NewGuid()))); _manijer.Setup(x => x.GetProxy(It.IsAny <string>())).Returns(_mockPeer.Object); _mockPeer.Setup(x => x.RequestVoteAsync(It.IsAny <RequestVoteRequest>())).ReturnsAsync( new RequestVoteResponse() { CurrentTerm = 0, VoteGranted = true } ); _mockPeer.Setup(x => x.AppendEntriesAsync(It.IsAny <AppendEntriesRequest>())).ReturnsAsync( new AppendEntriesResponse(1, true) ); _server = new DefaultRaftServer(_sister, _sister, _sister, _maqina.Object, _manijer.Object, _settings); _server.LastHeartBeat = new AlwaysOldTimestamp(); _server.Start(); Thread.Sleep(1000); // must be a leader by now Assert.Equal(Role.Leader, _server.Role); for (var i = 0; i < 15; i++) { await _server.ApplyCommandAsync(new StateMachineCommandRequest() { Command = new byte[128] }); } Thread.Sleep(3000); _mockPeer.VerifyAll(); }
public async Task LeadsFollowersAndTheirLogsLikeALeader() { var list = new ConcurrentBag <FriendlyPeer>(); _manijer.Setup(x => x.GetPeers()).Returns(new[] { "1", "3", "5", "7" }.Select(s => new Peer(s, Guid.NewGuid()))); _manijer.Setup(x => x.GetProxy(It.IsAny <string>())).Returns( () => { var s = new FriendlyPeer(); list.Add(s); return(s); } ); _server = new DefaultRaftServer(_sister, _sister, _sister, _maqina.Object, _manijer.Object, _settings); _server.LastHeartBeat = new AlwaysOldTimestamp(); _server.Start(); Thread.Sleep(2000); // must be a leader by now Assert.Equal(Role.Leader, _server.Role); await _server.ApplyCommandAsync(new StateMachineCommandRequest() { Command = new byte[128] }); await _server.ApplyCommandAsync(new StateMachineCommandRequest() { Command = new byte[128] }); await _server.ApplyCommandAsync(new StateMachineCommandRequest() { Command = new byte[128] }); Thread.Sleep(2000); var timesFollowersServed = list.SelectMany(x => { var copy = x.AllThemAppendEntriesRequests.ToArray(); return(copy.Where(y => y.Entries.Length > 0)); }).Count(); _output.WriteLine($"timesFollowersServed: {timesFollowersServed}"); Assert.True(timesFollowersServed > 1); Assert.Equal(2, _sister.LastIndex); }
public async Task LeaderSendsSnapshotForAClientSoBehind() { _settings.MinSnapshottingIndexInterval = 10L; _maqina.Setup(x => x.WriteSnapshotAsync(It.IsAny <Stream>())) .Callback(async(Stream s) => s.Write(new byte[256], 0, 256)).Returns(Task.CompletedTask); var term = 1L; _manijer.Setup(x => x.GetPeers()).Returns(new[] { "1", "3", "5", "7" }.Select(s => new Peer(s, Guid.NewGuid()))); _manijer.Setup(x => x.GetProxy(It.Is <string>(s => s != "1"))).Returns(_mockPeer.Object); var behindPeer = new Mock <IRaftServer>(); _manijer.Setup(x => x.GetProxy(It.Is <string>(s => s == "1"))).Returns(behindPeer.Object); _mockPeer.Setup(x => x.RequestVoteAsync(It.IsAny <RequestVoteRequest>())).ReturnsAsync( new RequestVoteResponse() { CurrentTerm = term, VoteGranted = true } ); behindPeer.Setup(x => x.RequestVoteAsync(It.IsAny <RequestVoteRequest>())).ReturnsAsync( new RequestVoteResponse() { CurrentTerm = term, VoteGranted = true } ); _mockPeer.Setup(x => x.AppendEntriesAsync(It.IsAny <AppendEntriesRequest>())).ReturnsAsync( new AppendEntriesResponse(term, true) ); // unsuccessful response to append entry so that it is left behind behindPeer.Setup(x => x.AppendEntriesAsync(It.Is <AppendEntriesRequest>( req => req.Entries.Length > 0 ))).ReturnsAsync( new AppendEntriesResponse(term, false) ); // but success to heartbeat behindPeer.Setup(x => x.AppendEntriesAsync(It.Is <AppendEntriesRequest>( req => req.Entries.Length == 0 ))).ReturnsAsync( new AppendEntriesResponse(term, true) ); // should be called for installing snapshot behindPeer.Setup(x => x.InstallSnapshotAsync(It.Is <InstallSnapshotRequest>(req => req.CurrentTerm == term && req.LastIncludedIndex == 14 ))).ReturnsAsync( new InstallSnapshotResponse() { CurrentTerm = term } ); _server = new DefaultRaftServer(_sister, _sister, _sister, _maqina.Object, _manijer.Object, _settings); _server.LastHeartBeat = new AlwaysOldTimestamp(); _server.Start(); Thread.Sleep(1000); // must be a leader by now Assert.Equal(Role.Leader, _server.Role); for (var i = 0; i < 15; i++) { await _server.ApplyCommandAsync(new StateMachineCommandRequest() { Command = new byte[128] }); } Thread.Sleep(3000); _mockPeer.VerifyAll(); behindPeer.VerifyAll(); }