예제 #1
0
        public void DoesNotWriteEntryForTruncateCommandWhenPrevIdxIsGreaterThanOrEqualToCommitIdx(long prevIdx)
        {
            // Arrange
            var @event = new AppendEntriesRequested
            {
                PreviousLogTerm  = 1,
                PreviousLogIndex = prevIdx
            };

            var nodeData = new NodeData
            {
                CommitIndex = 30,
                CurrentTerm = 2
            };

            var nodePublisher   = Substitute.For <IPublishToBuffer <NodeCommandScheduled, NodeCommandResult> >();
            var writeDataBlocks = Substitute.For <IWriteDataBlocks>();
            var raftNode        = Substitute.For <INode>();

            raftNode.Data.Returns(nodeData);

            var handler = new RpcLogTruncator(raftNode, writeDataBlocks, nodePublisher);

            // Act
            handler.OnNext(@event, 0L, false);

            // Assert
            writeDataBlocks.DidNotReceive().WriteBlock(Arg.Any <byte[]>());
        }
예제 #2
0
        public void PublishesTruncateLogCommandToNodeAfterEntrySuccessfullyWritten()
        {
            // Arrange
            var @event = new AppendEntriesRequested
            {
                PreviousLogTerm  = 1,
                PreviousLogIndex = 5
            };

            var nodeData = new NodeData
            {
                CommitIndex = 20,
                CurrentTerm = 2
            };

            var writeDataBlocks = Substitute.For <IWriteDataBlocks>();
            var nodePublisher   = new TestBufferPublisher <NodeCommandScheduled, NodeCommandResult>();

            var raftNode = Substitute.For <INode>();

            raftNode.Data.Returns(nodeData);

            var handler = new RpcLogTruncator(raftNode, writeDataBlocks, nodePublisher);

            // Act
            handler.OnNext(@event, 0L, false);

            // Assert
            writeDataBlocks.Received().WriteBlock(Arg.Any <byte[]>());
            nodePublisher.Events.Should().HaveCount(1);
            nodePublisher.Events[0].Command.Should().BeOfType <TruncateLog>();
            ((TruncateLog)nodePublisher.Events[0].Command).TruncateFromIndex.Should().Be(@event.PreviousLogIndex);
        }
예제 #3
0
        public void ThrowsWhenPrevTermIsGreaterThanCurrentTerm()
        {
            // Arrange
            var @event = new AppendEntriesRequested
            {
                PreviousLogTerm  = 3,
                PreviousLogIndex = 5
            };

            var nodeData = new NodeData
            {
                CommitIndex = 20,
                CurrentTerm = 2
            };

            var nodePublisher   = Substitute.For <IPublishToBuffer <NodeCommandScheduled, NodeCommandResult> >();
            var writeDataBlocks = Substitute.For <IWriteDataBlocks>();
            var raftNode        = Substitute.For <INode>();

            raftNode.Data.Returns(nodeData);

            var handler = new RpcLogTruncator(raftNode, writeDataBlocks, nodePublisher);

            // Act
            var actAction = new Action(() => handler.OnNext(@event, 0L, false));

            // Assert
            actAction.ShouldThrow <InvalidOperationException>();
        }
예제 #4
0
        public void CreatesAndWritesEntryForTruncateCommand()
        {
            // Arrange
            var @event = new AppendEntriesRequested
            {
                PreviousLogTerm  = 1,
                PreviousLogIndex = 5
            };

            var nodeData = new NodeData
            {
                CommitIndex = 20,
                CurrentTerm = 2
            };

            byte[] blockWritten = null;

            var writeDataBlocks = Substitute.For <IWriteDataBlocks>();

            writeDataBlocks
            .When(x => x.WriteBlock(Arg.Any <byte[]>()))
            .Do(x => blockWritten = x.Arg <byte[]>());

            var nodePublisher = Substitute.For <IPublishToBuffer <NodeCommandScheduled, NodeCommandResult> >();
            var raftNode      = Substitute.For <INode>();

            raftNode.Data.Returns(nodeData);

            var handler = new RpcLogTruncator(raftNode, writeDataBlocks, nodePublisher);

            // Act
            handler.OnNext(@event, 0L, false);

            // Assert
            writeDataBlocks.Received().WriteBlock(Arg.Any <byte[]>());
            blockWritten.Should().NotBeNull();
            using (var ms = new MemoryStream(blockWritten))
            {
                Serializer.DeserializeWithLengthPrefix <TruncateLogCommandEntry>(ms, PrefixStyle.Base128)
                .TruncateFromIndex.Should().Be(@event.PreviousLogIndex);
            }
        }
예제 #5
0
        public void DoesNotWriteEntryForTruncateCommandWhenPrevLogIdxIsNullOrPrevLogTermIsNull()
        {
            // Arrange
            var @event = new AppendEntriesRequested
            {
                PreviousLogIndex = null,
                PreviousLogTerm  = null
            };

            var nodePublisher   = Substitute.For <IPublishToBuffer <NodeCommandScheduled, NodeCommandResult> >();
            var raftNode        = Substitute.For <INode>();
            var writeDataBlocks = Substitute.For <IWriteDataBlocks>();

            var handler = new RpcLogTruncator(raftNode, writeDataBlocks, nodePublisher);

            // Act
            handler.OnNext(@event, 0L, false);

            // Assert
            writeDataBlocks.DidNotReceive().WriteBlock(Arg.Any <byte[]>());
        }