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