|
|
@@ -831,3 +831,47 @@ func TestNodeProposeAddLearnerNode(t *testing.T) {
|
|
|
close(stop)
|
|
|
<-done
|
|
|
}
|
|
|
+
|
|
|
+func TestAppendPagination(t *testing.T) {
|
|
|
+ const maxSizePerMsg = 2048
|
|
|
+ n := newNetworkWithConfig(func(c *Config) {
|
|
|
+ c.MaxSizePerMsg = maxSizePerMsg
|
|
|
+ }, nil, nil, nil)
|
|
|
+
|
|
|
+ seenFullMessage := false
|
|
|
+ // Inspect all messages to see that we never exceed the limit, but
|
|
|
+ // we do see messages of larger than half the limit.
|
|
|
+ n.msgHook = func(m raftpb.Message) bool {
|
|
|
+ if m.Type == raftpb.MsgApp {
|
|
|
+ size := 0
|
|
|
+ for _, e := range m.Entries {
|
|
|
+ size += len(e.Data)
|
|
|
+ }
|
|
|
+ if size > maxSizePerMsg {
|
|
|
+ t.Errorf("sent MsgApp that is too large: %d bytes", size)
|
|
|
+ }
|
|
|
+ if size > maxSizePerMsg/2 {
|
|
|
+ seenFullMessage = true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true
|
|
|
+ }
|
|
|
+
|
|
|
+ n.send(raftpb.Message{From: 1, To: 1, Type: raftpb.MsgHup})
|
|
|
+
|
|
|
+ // Partition the network while we make our proposals. This forces
|
|
|
+ // the entries to be batched into larger messages.
|
|
|
+ n.isolate(1)
|
|
|
+ blob := []byte(strings.Repeat("a", 1000))
|
|
|
+ for i := 0; i < 5; i++ {
|
|
|
+ n.send(raftpb.Message{From: 1, To: 1, Type: raftpb.MsgProp, Entries: []raftpb.Entry{{Data: blob}}})
|
|
|
+ }
|
|
|
+ n.recover()
|
|
|
+
|
|
|
+ // After the partition recovers, tick the clock to wake everything
|
|
|
+ // back up and send the messages.
|
|
|
+ n.send(raftpb.Message{From: 1, To: 1, Type: raftpb.MsgBeat})
|
|
|
+ if !seenFullMessage {
|
|
|
+ t.Error("didn't see any messages more than half the max size; something is wrong with this test")
|
|
|
+ }
|
|
|
+}
|