util_test.go 4.8 KB

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