1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package rafthttp
16
17 import (
18 "bytes"
19 "encoding/binary"
20 "io"
21 "net/http"
22 "reflect"
23 "testing"
24
25 "go.etcd.io/etcd/api/v3/version"
26 "go.etcd.io/etcd/raft/v3/raftpb"
27
28 "github.com/coreos/go-semver/semver"
29 )
30
31 func TestEntry(t *testing.T) {
32 tests := []raftpb.Entry{
33 {},
34 {Term: 1, Index: 1},
35 {Term: 1, Index: 1, Data: []byte("some data")},
36 }
37 for i, tt := range tests {
38 b := &bytes.Buffer{}
39 if err := writeEntryTo(b, &tt); err != nil {
40 t.Errorf("#%d: unexpected write ents error: %v", i, err)
41 continue
42 }
43 var ent raftpb.Entry
44 if err := readEntryFrom(b, &ent); err != nil {
45 t.Errorf("#%d: unexpected read ents error: %v", i, err)
46 continue
47 }
48 if !reflect.DeepEqual(ent, tt) {
49 t.Errorf("#%d: ent = %+v, want %+v", i, ent, tt)
50 }
51 }
52 }
53
54 func TestCompareMajorMinorVersion(t *testing.T) {
55 tests := []struct {
56 va, vb *semver.Version
57 w int
58 }{
59
60 {
61 semver.Must(semver.NewVersion("2.1.0")),
62 semver.Must(semver.NewVersion("2.1.0")),
63 0,
64 },
65
66 {
67 semver.Must(semver.NewVersion("2.0.0")),
68 semver.Must(semver.NewVersion("2.1.0")),
69 -1,
70 },
71
72 {
73 semver.Must(semver.NewVersion("2.2.0")),
74 semver.Must(semver.NewVersion("2.1.0")),
75 1,
76 },
77
78 {
79 semver.Must(semver.NewVersion("2.1.1")),
80 semver.Must(semver.NewVersion("2.1.0")),
81 0,
82 },
83
84 {
85 semver.Must(semver.NewVersion("2.1.0-alpha.0")),
86 semver.Must(semver.NewVersion("2.1.0")),
87 0,
88 },
89 }
90 for i, tt := range tests {
91 if g := compareMajorMinorVersion(tt.va, tt.vb); g != tt.w {
92 t.Errorf("#%d: compare = %d, want %d", i, g, tt.w)
93 }
94 }
95 }
96
97 func TestServerVersion(t *testing.T) {
98 tests := []struct {
99 h http.Header
100 wv *semver.Version
101 }{
102
103 {
104 http.Header{},
105 semver.Must(semver.NewVersion("2.0.0")),
106 },
107 {
108 http.Header{"X-Server-Version": []string{"2.1.0"}},
109 semver.Must(semver.NewVersion("2.1.0")),
110 },
111 {
112 http.Header{"X-Server-Version": []string{"2.1.0-alpha.0+git"}},
113 semver.Must(semver.NewVersion("2.1.0-alpha.0+git")),
114 },
115 }
116 for i, tt := range tests {
117 v := serverVersion(tt.h)
118 if v.String() != tt.wv.String() {
119 t.Errorf("#%d: version = %s, want %s", i, v, tt.wv)
120 }
121 }
122 }
123
124 func TestMinClusterVersion(t *testing.T) {
125 tests := []struct {
126 h http.Header
127 wv *semver.Version
128 }{
129
130 {
131 http.Header{},
132 semver.Must(semver.NewVersion("2.0.0")),
133 },
134 {
135 http.Header{"X-Min-Cluster-Version": []string{"2.1.0"}},
136 semver.Must(semver.NewVersion("2.1.0")),
137 },
138 {
139 http.Header{"X-Min-Cluster-Version": []string{"2.1.0-alpha.0+git"}},
140 semver.Must(semver.NewVersion("2.1.0-alpha.0+git")),
141 },
142 }
143 for i, tt := range tests {
144 v := minClusterVersion(tt.h)
145 if v.String() != tt.wv.String() {
146 t.Errorf("#%d: version = %s, want %s", i, v, tt.wv)
147 }
148 }
149 }
150
151 func TestCheckVersionCompatibility(t *testing.T) {
152 ls := semver.Must(semver.NewVersion(version.Version))
153 lmc := semver.Must(semver.NewVersion(version.MinClusterVersion))
154 tests := []struct {
155 server *semver.Version
156 minCluster *semver.Version
157 wok bool
158 }{
159
160 {
161 ls,
162 lmc,
163 true,
164 },
165
166 {
167 lmc,
168 &semver.Version{},
169 true,
170 },
171
172 {
173 &semver.Version{Major: ls.Major + 1},
174 ls,
175 true,
176 },
177
178 {
179 &semver.Version{Major: lmc.Major - 1},
180 &semver.Version{},
181 false,
182 },
183
184 {
185 &semver.Version{Major: ls.Major + 1, Minor: 1},
186 &semver.Version{Major: ls.Major + 1},
187 false,
188 },
189 }
190 for i, tt := range tests {
191 _, _, err := checkVersionCompatibility("", tt.server, tt.minCluster)
192 if ok := err == nil; ok != tt.wok {
193 t.Errorf("#%d: ok = %v, want %v", i, ok, tt.wok)
194 }
195 }
196 }
197
198 func writeEntryTo(w io.Writer, ent *raftpb.Entry) error {
199 size := ent.Size()
200 if err := binary.Write(w, binary.BigEndian, uint64(size)); err != nil {
201 return err
202 }
203 b, err := ent.Marshal()
204 if err != nil {
205 return err
206 }
207 _, err = w.Write(b)
208 return err
209 }
210
211 func readEntryFrom(r io.Reader, ent *raftpb.Entry) error {
212 var l uint64
213 if err := binary.Read(r, binary.BigEndian, &l); err != nil {
214 return err
215 }
216 buf := make([]byte, int(l))
217 if _, err := io.ReadFull(r, buf); err != nil {
218 return err
219 }
220 return ent.Unmarshal(buf)
221 }
222
View as plain text