1// Copyright 2015 The etcd Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package rafthttp
16
17import (
18	"bytes"
19	"reflect"
20	"testing"
21
22	stats "go.etcd.io/etcd/etcdserver/api/v2stats"
23	"go.etcd.io/etcd/pkg/types"
24	"go.etcd.io/etcd/raft/raftpb"
25)
26
27func TestMsgAppV2(t *testing.T) {
28	tests := []raftpb.Message{
29		linkHeartbeatMessage,
30		{
31			Type:    raftpb.MsgApp,
32			From:    1,
33			To:      2,
34			Term:    1,
35			LogTerm: 1,
36			Index:   0,
37			Entries: []raftpb.Entry{
38				{Term: 1, Index: 1, Data: []byte("some data")},
39				{Term: 1, Index: 2, Data: []byte("some data")},
40				{Term: 1, Index: 3, Data: []byte("some data")},
41			},
42		},
43		// consecutive MsgApp
44		{
45			Type:    raftpb.MsgApp,
46			From:    1,
47			To:      2,
48			Term:    1,
49			LogTerm: 1,
50			Index:   3,
51			Entries: []raftpb.Entry{
52				{Term: 1, Index: 4, Data: []byte("some data")},
53			},
54		},
55		linkHeartbeatMessage,
56		// consecutive MsgApp after linkHeartbeatMessage
57		{
58			Type:    raftpb.MsgApp,
59			From:    1,
60			To:      2,
61			Term:    1,
62			LogTerm: 1,
63			Index:   4,
64			Entries: []raftpb.Entry{
65				{Term: 1, Index: 5, Data: []byte("some data")},
66			},
67		},
68		// MsgApp with higher term
69		{
70			Type:    raftpb.MsgApp,
71			From:    1,
72			To:      2,
73			Term:    3,
74			LogTerm: 1,
75			Index:   5,
76			Entries: []raftpb.Entry{
77				{Term: 3, Index: 6, Data: []byte("some data")},
78			},
79		},
80		linkHeartbeatMessage,
81		// consecutive MsgApp
82		{
83			Type:    raftpb.MsgApp,
84			From:    1,
85			To:      2,
86			Term:    3,
87			LogTerm: 2,
88			Index:   6,
89			Entries: []raftpb.Entry{
90				{Term: 3, Index: 7, Data: []byte("some data")},
91			},
92		},
93		// consecutive empty MsgApp
94		{
95			Type:    raftpb.MsgApp,
96			From:    1,
97			To:      2,
98			Term:    3,
99			LogTerm: 2,
100			Index:   7,
101			Entries: nil,
102		},
103		linkHeartbeatMessage,
104	}
105	b := &bytes.Buffer{}
106	enc := newMsgAppV2Encoder(b, &stats.FollowerStats{})
107	dec := newMsgAppV2Decoder(b, types.ID(2), types.ID(1))
108
109	for i, tt := range tests {
110		if err := enc.encode(&tt); err != nil {
111			t.Errorf("#%d: unexpected encode message error: %v", i, err)
112			continue
113		}
114		m, err := dec.decode()
115		if err != nil {
116			t.Errorf("#%d: unexpected decode message error: %v", i, err)
117			continue
118		}
119		if !reflect.DeepEqual(m, tt) {
120			t.Errorf("#%d: message = %+v, want %+v", i, m, tt)
121		}
122	}
123}
124