index_test.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. // Copyright 2015 CoreOS, Inc.
  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 storage
  15. import (
  16. "reflect"
  17. "testing"
  18. )
  19. func TestIndexGet(t *testing.T) {
  20. index := newTreeIndex()
  21. index.Put([]byte("foo"), revision{main: 2})
  22. index.Put([]byte("foo"), revision{main: 4})
  23. index.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 := index.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. index := newTreeIndex()
  59. for i := range allKeys {
  60. index.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 := index.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. index := newTreeIndex()
  113. index.Put([]byte("foo"), revision{main: 1})
  114. err := index.Tombstone([]byte("foo"), revision{main: 2})
  115. if err != nil {
  116. t.Errorf("tombstone error = %v, want nil", err)
  117. }
  118. _, _, _, err = index.Get([]byte("foo"), 2)
  119. if err != ErrRevisionNotFound {
  120. t.Errorf("get error = %v, want nil", err)
  121. }
  122. err = index.Tombstone([]byte("foo"), revision{main: 3})
  123. if err != ErrRevisionNotFound {
  124. t.Errorf("tombstone error = %v, want %v", err, ErrRevisionNotFound)
  125. }
  126. }
  127. func TestIndexCompact(t *testing.T) {
  128. maxRev := int64(20)
  129. tests := []struct {
  130. key []byte
  131. remove bool
  132. rev revision
  133. created revision
  134. ver int64
  135. }{
  136. {[]byte("foo"), false, revision{main: 1}, revision{main: 1}, 1},
  137. {[]byte("foo1"), false, revision{main: 2}, revision{main: 2}, 1},
  138. {[]byte("foo2"), false, revision{main: 3}, revision{main: 3}, 1},
  139. {[]byte("foo2"), false, revision{main: 4}, revision{main: 3}, 2},
  140. {[]byte("foo"), false, revision{main: 5}, revision{main: 1}, 2},
  141. {[]byte("foo1"), false, revision{main: 6}, revision{main: 2}, 2},
  142. {[]byte("foo1"), true, revision{main: 7}, revision{}, 0},
  143. {[]byte("foo2"), true, revision{main: 8}, revision{}, 0},
  144. {[]byte("foo"), true, revision{main: 9}, revision{}, 0},
  145. {[]byte("foo"), false, revision{10, 0}, revision{10, 0}, 1},
  146. {[]byte("foo1"), false, revision{10, 1}, revision{10, 1}, 1},
  147. }
  148. // Continuous Compact
  149. index := newTreeIndex()
  150. for _, tt := range tests {
  151. if tt.remove {
  152. index.Tombstone(tt.key, tt.rev)
  153. } else {
  154. index.Put(tt.key, tt.rev)
  155. }
  156. }
  157. for i := int64(1); i < maxRev; i++ {
  158. am := index.Compact(i)
  159. windex := newTreeIndex()
  160. for _, tt := range tests {
  161. if _, ok := am[tt.rev]; ok || tt.rev.GreaterThan(revision{main: i}) {
  162. if tt.remove {
  163. windex.Tombstone(tt.key, tt.rev)
  164. } else {
  165. windex.Restore(tt.key, tt.created, tt.rev, tt.ver)
  166. }
  167. }
  168. }
  169. if !index.Equal(windex) {
  170. t.Errorf("#%d: not equal index", i)
  171. }
  172. }
  173. // Once Compact
  174. for i := int64(1); i < maxRev; i++ {
  175. index := newTreeIndex()
  176. for _, tt := range tests {
  177. if tt.remove {
  178. index.Tombstone(tt.key, tt.rev)
  179. } else {
  180. index.Put(tt.key, tt.rev)
  181. }
  182. }
  183. am := index.Compact(i)
  184. windex := newTreeIndex()
  185. for _, tt := range tests {
  186. if _, ok := am[tt.rev]; ok || tt.rev.GreaterThan(revision{main: i}) {
  187. if tt.remove {
  188. windex.Tombstone(tt.key, tt.rev)
  189. } else {
  190. windex.Restore(tt.key, tt.created, tt.rev, tt.ver)
  191. }
  192. }
  193. }
  194. if !index.Equal(windex) {
  195. t.Errorf("#%d: not equal index", i)
  196. }
  197. }
  198. }
  199. func TestIndexRestore(t *testing.T) {
  200. key := []byte("foo")
  201. tests := []struct {
  202. created revision
  203. modified revision
  204. ver int64
  205. }{
  206. {revision{1, 0}, revision{1, 0}, 1},
  207. {revision{1, 0}, revision{1, 1}, 2},
  208. {revision{1, 0}, revision{2, 0}, 3},
  209. }
  210. // Continuous Restore
  211. index := newTreeIndex()
  212. for i, tt := range tests {
  213. index.Restore(key, tt.created, tt.modified, tt.ver)
  214. modified, created, ver, err := index.Get(key, tt.modified.main)
  215. if modified != tt.modified {
  216. t.Errorf("#%d: modified = %v, want %v", i, modified, tt.modified)
  217. }
  218. if created != tt.created {
  219. t.Errorf("#%d: created = %v, want %v", i, created, tt.created)
  220. }
  221. if ver != tt.ver {
  222. t.Errorf("#%d: ver = %d, want %d", i, ver, tt.ver)
  223. }
  224. if err != nil {
  225. t.Errorf("#%d: err = %v, want nil", i, err)
  226. }
  227. }
  228. // Once Restore
  229. for i, tt := range tests {
  230. index := newTreeIndex()
  231. index.Restore(key, tt.created, tt.modified, tt.ver)
  232. modified, created, ver, err := index.Get(key, tt.modified.main)
  233. if modified != tt.modified {
  234. t.Errorf("#%d: modified = %v, want %v", i, modified, tt.modified)
  235. }
  236. if created != tt.created {
  237. t.Errorf("#%d: created = %v, want %v", i, created, tt.created)
  238. }
  239. if ver != tt.ver {
  240. t.Errorf("#%d: ver = %d, want %d", i, ver, tt.ver)
  241. }
  242. if err != nil {
  243. t.Errorf("#%d: err = %v, want nil", i, err)
  244. }
  245. }
  246. }