index_test.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  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 mvcc
  15. import (
  16. "reflect"
  17. "testing"
  18. )
  19. func TestIndexGet(t *testing.T) {
  20. ti := newTreeIndex()
  21. ti.Put([]byte("foo"), revision{main: 2})
  22. ti.Put([]byte("foo"), revision{main: 4})
  23. ti.Tombstone([]byte("foo"), revision{main: 6})
  24. tests := []struct {
  25. rev int64
  26. wrev revision
  27. wcreated revision
  28. wver int64
  29. werr error
  30. }{
  31. {0, revision{}, revision{}, 0, ErrRevisionNotFound},
  32. {1, revision{}, revision{}, 0, ErrRevisionNotFound},
  33. {2, revision{main: 2}, revision{main: 2}, 1, nil},
  34. {3, revision{main: 2}, revision{main: 2}, 1, nil},
  35. {4, revision{main: 4}, revision{main: 2}, 2, nil},
  36. {5, revision{main: 4}, revision{main: 2}, 2, nil},
  37. {6, revision{}, revision{}, 0, ErrRevisionNotFound},
  38. }
  39. for i, tt := range tests {
  40. rev, created, ver, err := ti.Get([]byte("foo"), tt.rev)
  41. if err != tt.werr {
  42. t.Errorf("#%d: err = %v, want %v", i, err, tt.werr)
  43. }
  44. if rev != tt.wrev {
  45. t.Errorf("#%d: rev = %+v, want %+v", i, rev, tt.wrev)
  46. }
  47. if created != tt.wcreated {
  48. t.Errorf("#%d: created = %+v, want %+v", i, created, tt.wcreated)
  49. }
  50. if ver != tt.wver {
  51. t.Errorf("#%d: ver = %d, want %d", i, ver, tt.wver)
  52. }
  53. }
  54. }
  55. func TestIndexRange(t *testing.T) {
  56. allKeys := [][]byte{[]byte("foo"), []byte("foo1"), []byte("foo2")}
  57. allRevs := []revision{{main: 1}, {main: 2}, {main: 3}}
  58. ti := newTreeIndex()
  59. for i := range allKeys {
  60. ti.Put(allKeys[i], allRevs[i])
  61. }
  62. atRev := int64(3)
  63. tests := []struct {
  64. key, end []byte
  65. wkeys [][]byte
  66. wrevs []revision
  67. }{
  68. // single key that not found
  69. {
  70. []byte("bar"), nil, nil, nil,
  71. },
  72. // single key that found
  73. {
  74. []byte("foo"), nil, allKeys[:1], allRevs[:1],
  75. },
  76. // range keys, return first member
  77. {
  78. []byte("foo"), []byte("foo1"), allKeys[:1], allRevs[:1],
  79. },
  80. // range keys, return first two members
  81. {
  82. []byte("foo"), []byte("foo2"), allKeys[:2], allRevs[:2],
  83. },
  84. // range keys, return all members
  85. {
  86. []byte("foo"), []byte("fop"), allKeys, allRevs,
  87. },
  88. // range keys, return last two members
  89. {
  90. []byte("foo1"), []byte("fop"), allKeys[1:], allRevs[1:],
  91. },
  92. // range keys, return last member
  93. {
  94. []byte("foo2"), []byte("fop"), allKeys[2:], allRevs[2:],
  95. },
  96. // range keys, return nothing
  97. {
  98. []byte("foo3"), []byte("fop"), nil, nil,
  99. },
  100. }
  101. for i, tt := range tests {
  102. keys, revs := ti.Range(tt.key, tt.end, atRev)
  103. if !reflect.DeepEqual(keys, tt.wkeys) {
  104. t.Errorf("#%d: keys = %+v, want %+v", i, keys, tt.wkeys)
  105. }
  106. if !reflect.DeepEqual(revs, tt.wrevs) {
  107. t.Errorf("#%d: revs = %+v, want %+v", i, revs, tt.wrevs)
  108. }
  109. }
  110. }
  111. func TestIndexTombstone(t *testing.T) {
  112. ti := newTreeIndex()
  113. ti.Put([]byte("foo"), revision{main: 1})
  114. err := ti.Tombstone([]byte("foo"), revision{main: 2})
  115. if err != nil {
  116. t.Errorf("tombstone error = %v, want nil", err)
  117. }
  118. _, _, _, err = ti.Get([]byte("foo"), 2)
  119. if err != ErrRevisionNotFound {
  120. t.Errorf("get error = %v, want nil", err)
  121. }
  122. err = ti.Tombstone([]byte("foo"), revision{main: 3})
  123. if err != ErrRevisionNotFound {
  124. t.Errorf("tombstone error = %v, want %v", err, ErrRevisionNotFound)
  125. }
  126. }
  127. func TestIndexRangeSince(t *testing.T) {
  128. allKeys := [][]byte{[]byte("foo"), []byte("foo1"), []byte("foo2"), []byte("foo2"), []byte("foo1"), []byte("foo")}
  129. allRevs := []revision{{main: 1}, {main: 2}, {main: 3}, {main: 4}, {main: 5}, {main: 6}}
  130. ti := newTreeIndex()
  131. for i := range allKeys {
  132. ti.Put(allKeys[i], allRevs[i])
  133. }
  134. atRev := int64(1)
  135. tests := []struct {
  136. key, end []byte
  137. wrevs []revision
  138. }{
  139. // single key that not found
  140. {
  141. []byte("bar"), nil, nil,
  142. },
  143. // single key that found
  144. {
  145. []byte("foo"), nil, []revision{{main: 1}, {main: 6}},
  146. },
  147. // range keys, return first member
  148. {
  149. []byte("foo"), []byte("foo1"), []revision{{main: 1}, {main: 6}},
  150. },
  151. // range keys, return first two members
  152. {
  153. []byte("foo"), []byte("foo2"), []revision{{main: 1}, {main: 2}, {main: 5}, {main: 6}},
  154. },
  155. // range keys, return all members
  156. {
  157. []byte("foo"), []byte("fop"), allRevs,
  158. },
  159. // range keys, return last two members
  160. {
  161. []byte("foo1"), []byte("fop"), []revision{{main: 2}, {main: 3}, {main: 4}, {main: 5}},
  162. },
  163. // range keys, return last member
  164. {
  165. []byte("foo2"), []byte("fop"), []revision{{main: 3}, {main: 4}},
  166. },
  167. // range keys, return nothing
  168. {
  169. []byte("foo3"), []byte("fop"), nil,
  170. },
  171. }
  172. for i, tt := range tests {
  173. revs := ti.RangeSince(tt.key, tt.end, atRev)
  174. if !reflect.DeepEqual(revs, tt.wrevs) {
  175. t.Errorf("#%d: revs = %+v, want %+v", i, revs, tt.wrevs)
  176. }
  177. }
  178. }
  179. func TestIndexCompact(t *testing.T) {
  180. maxRev := int64(20)
  181. tests := []struct {
  182. key []byte
  183. remove bool
  184. rev revision
  185. created revision
  186. ver int64
  187. }{
  188. {[]byte("foo"), false, revision{main: 1}, revision{main: 1}, 1},
  189. {[]byte("foo1"), false, revision{main: 2}, revision{main: 2}, 1},
  190. {[]byte("foo2"), false, revision{main: 3}, revision{main: 3}, 1},
  191. {[]byte("foo2"), false, revision{main: 4}, revision{main: 3}, 2},
  192. {[]byte("foo"), false, revision{main: 5}, revision{main: 1}, 2},
  193. {[]byte("foo1"), false, revision{main: 6}, revision{main: 2}, 2},
  194. {[]byte("foo1"), true, revision{main: 7}, revision{}, 0},
  195. {[]byte("foo2"), true, revision{main: 8}, revision{}, 0},
  196. {[]byte("foo"), true, revision{main: 9}, revision{}, 0},
  197. {[]byte("foo"), false, revision{10, 0}, revision{10, 0}, 1},
  198. {[]byte("foo1"), false, revision{10, 1}, revision{10, 1}, 1},
  199. }
  200. // Continuous Compact
  201. ti := newTreeIndex()
  202. for _, tt := range tests {
  203. if tt.remove {
  204. ti.Tombstone(tt.key, tt.rev)
  205. } else {
  206. ti.Put(tt.key, tt.rev)
  207. }
  208. }
  209. for i := int64(1); i < maxRev; i++ {
  210. am := ti.Compact(i)
  211. wti := newTreeIndex()
  212. for _, tt := range tests {
  213. if _, ok := am[tt.rev]; ok || tt.rev.GreaterThan(revision{main: i}) {
  214. if tt.remove {
  215. wti.Tombstone(tt.key, tt.rev)
  216. } else {
  217. wti.Restore(tt.key, tt.created, tt.rev, tt.ver)
  218. }
  219. }
  220. }
  221. if !ti.Equal(wti) {
  222. t.Errorf("#%d: not equal ti", i)
  223. }
  224. }
  225. // Once Compact
  226. for i := int64(1); i < maxRev; i++ {
  227. ti := newTreeIndex()
  228. for _, tt := range tests {
  229. if tt.remove {
  230. ti.Tombstone(tt.key, tt.rev)
  231. } else {
  232. ti.Put(tt.key, tt.rev)
  233. }
  234. }
  235. am := ti.Compact(i)
  236. wti := newTreeIndex()
  237. for _, tt := range tests {
  238. if _, ok := am[tt.rev]; ok || tt.rev.GreaterThan(revision{main: i}) {
  239. if tt.remove {
  240. wti.Tombstone(tt.key, tt.rev)
  241. } else {
  242. wti.Restore(tt.key, tt.created, tt.rev, tt.ver)
  243. }
  244. }
  245. }
  246. if !ti.Equal(wti) {
  247. t.Errorf("#%d: not equal ti", i)
  248. }
  249. }
  250. }
  251. func TestIndexRestore(t *testing.T) {
  252. key := []byte("foo")
  253. tests := []struct {
  254. created revision
  255. modified revision
  256. ver int64
  257. }{
  258. {revision{1, 0}, revision{1, 0}, 1},
  259. {revision{1, 0}, revision{1, 1}, 2},
  260. {revision{1, 0}, revision{2, 0}, 3},
  261. }
  262. // Continuous Restore
  263. ti := newTreeIndex()
  264. for i, tt := range tests {
  265. ti.Restore(key, tt.created, tt.modified, tt.ver)
  266. modified, created, ver, err := ti.Get(key, tt.modified.main)
  267. if modified != tt.modified {
  268. t.Errorf("#%d: modified = %v, want %v", i, modified, tt.modified)
  269. }
  270. if created != tt.created {
  271. t.Errorf("#%d: created = %v, want %v", i, created, tt.created)
  272. }
  273. if ver != tt.ver {
  274. t.Errorf("#%d: ver = %d, want %d", i, ver, tt.ver)
  275. }
  276. if err != nil {
  277. t.Errorf("#%d: err = %v, want nil", i, err)
  278. }
  279. }
  280. // Once Restore
  281. for i, tt := range tests {
  282. ti := newTreeIndex()
  283. ti.Restore(key, tt.created, tt.modified, tt.ver)
  284. modified, created, ver, err := ti.Get(key, tt.modified.main)
  285. if modified != tt.modified {
  286. t.Errorf("#%d: modified = %v, want %v", i, modified, tt.modified)
  287. }
  288. if created != tt.created {
  289. t.Errorf("#%d: created = %v, want %v", i, created, tt.created)
  290. }
  291. if ver != tt.ver {
  292. t.Errorf("#%d: ver = %d, want %d", i, ver, tt.ver)
  293. }
  294. if err != nil {
  295. t.Errorf("#%d: err = %v, want nil", i, err)
  296. }
  297. }
  298. }