key_index_test.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. package storage
  2. import (
  3. "reflect"
  4. "testing"
  5. )
  6. func TestKeyIndexGet(t *testing.T) {
  7. // key: "foo"
  8. // index: 12
  9. // generations:
  10. // {empty}
  11. // {8[1], 10[2], 12(t)[3]}
  12. // {4[2], 6(t)[3]}
  13. ki := newTestKeyIndex()
  14. ki.compact(4, make(map[uint64]struct{}))
  15. tests := []struct {
  16. index uint64
  17. windex uint64
  18. werr error
  19. }{
  20. // expected not exist on an index that is greater than the last tombstone
  21. {13, 0, ErrIndexNotFound},
  22. {13, 0, ErrIndexNotFound},
  23. // get on generation 2
  24. {12, 12, nil},
  25. {11, 10, nil},
  26. {10, 10, nil},
  27. {9, 8, nil},
  28. {8, 8, nil},
  29. {7, 0, ErrIndexNotFound},
  30. // get on generation 1
  31. {6, 6, nil},
  32. {5, 4, nil},
  33. {4, 4, nil},
  34. }
  35. for i, tt := range tests {
  36. index, err := ki.get(tt.index)
  37. if err != tt.werr {
  38. t.Errorf("#%d: err = %v, want %v", i, err, tt.werr)
  39. }
  40. if index != tt.windex {
  41. t.Errorf("#%d: index = %d, want %d", i, index, tt.index)
  42. }
  43. }
  44. }
  45. func TestKeyIndexPut(t *testing.T) {
  46. ki := &keyIndex{key: []byte("foo")}
  47. ki.put(5)
  48. wki := &keyIndex{
  49. key: []byte("foo"),
  50. index: 5,
  51. generations: []generation{{ver: 1, cont: []uint64{5}}},
  52. }
  53. if !reflect.DeepEqual(ki, wki) {
  54. t.Errorf("ki = %+v, want %+v", ki, wki)
  55. }
  56. ki.put(7)
  57. wki = &keyIndex{
  58. key: []byte("foo"),
  59. index: 7,
  60. generations: []generation{{ver: 2, cont: []uint64{5, 7}}},
  61. }
  62. if !reflect.DeepEqual(ki, wki) {
  63. t.Errorf("ki = %+v, want %+v", ki, wki)
  64. }
  65. }
  66. func TestKeyIndexTombstone(t *testing.T) {
  67. ki := &keyIndex{key: []byte("foo")}
  68. ki.put(5)
  69. ki.tombstone(7)
  70. wki := &keyIndex{
  71. key: []byte("foo"),
  72. index: 7,
  73. generations: []generation{{ver: 2, cont: []uint64{5, 7}}, {}},
  74. }
  75. if !reflect.DeepEqual(ki, wki) {
  76. t.Errorf("ki = %+v, want %+v", ki, wki)
  77. }
  78. ki.put(8)
  79. ki.put(9)
  80. ki.tombstone(15)
  81. wki = &keyIndex{
  82. key: []byte("foo"),
  83. index: 15,
  84. generations: []generation{{ver: 2, cont: []uint64{5, 7}}, {ver: 3, cont: []uint64{8, 9, 15}}, {}},
  85. }
  86. if !reflect.DeepEqual(ki, wki) {
  87. t.Errorf("ki = %+v, want %+v", ki, wki)
  88. }
  89. }
  90. func TestKeyIndexCompact(t *testing.T) {
  91. tests := []struct {
  92. compact uint64
  93. wki *keyIndex
  94. wam map[uint64]struct{}
  95. }{
  96. {
  97. 1,
  98. &keyIndex{
  99. key: []byte("foo"),
  100. index: 12,
  101. generations: []generation{
  102. {ver: 3, cont: []uint64{2, 4, 6}},
  103. {ver: 3, cont: []uint64{8, 10, 12}},
  104. {},
  105. },
  106. },
  107. map[uint64]struct{}{
  108. 2: struct{}{}, 4: struct{}{}, 6: struct{}{},
  109. 8: struct{}{}, 10: struct{}{}, 12: struct{}{},
  110. },
  111. },
  112. {
  113. 2,
  114. &keyIndex{
  115. key: []byte("foo"),
  116. index: 12,
  117. generations: []generation{
  118. {ver: 3, cont: []uint64{2, 4, 6}},
  119. {ver: 3, cont: []uint64{8, 10, 12}},
  120. {},
  121. },
  122. },
  123. map[uint64]struct{}{
  124. 2: struct{}{}, 4: struct{}{}, 6: struct{}{},
  125. 8: struct{}{}, 10: struct{}{}, 12: struct{}{},
  126. },
  127. },
  128. {
  129. 3,
  130. &keyIndex{
  131. key: []byte("foo"),
  132. index: 12,
  133. generations: []generation{
  134. {ver: 3, cont: []uint64{2, 4, 6}},
  135. {ver: 3, cont: []uint64{8, 10, 12}},
  136. {},
  137. },
  138. },
  139. map[uint64]struct{}{
  140. 2: struct{}{}, 4: struct{}{}, 6: struct{}{},
  141. 8: struct{}{}, 10: struct{}{}, 12: struct{}{},
  142. },
  143. },
  144. {
  145. 4,
  146. &keyIndex{
  147. key: []byte("foo"),
  148. index: 12,
  149. generations: []generation{
  150. {ver: 3, cont: []uint64{4, 6}},
  151. {ver: 3, cont: []uint64{8, 10, 12}},
  152. {},
  153. },
  154. },
  155. map[uint64]struct{}{
  156. 4: struct{}{}, 6: struct{}{},
  157. 8: struct{}{}, 10: struct{}{}, 12: struct{}{},
  158. },
  159. },
  160. {
  161. 5,
  162. &keyIndex{
  163. key: []byte("foo"),
  164. index: 12,
  165. generations: []generation{
  166. {ver: 3, cont: []uint64{4, 6}},
  167. {ver: 3, cont: []uint64{8, 10, 12}},
  168. {},
  169. },
  170. },
  171. map[uint64]struct{}{
  172. 4: struct{}{}, 6: struct{}{},
  173. 8: struct{}{}, 10: struct{}{}, 12: struct{}{},
  174. },
  175. },
  176. {
  177. 6,
  178. &keyIndex{
  179. key: []byte("foo"),
  180. index: 12,
  181. generations: []generation{
  182. {ver: 3, cont: []uint64{6}},
  183. {ver: 3, cont: []uint64{8, 10, 12}},
  184. {},
  185. },
  186. },
  187. map[uint64]struct{}{
  188. 6: struct{}{},
  189. 8: struct{}{}, 10: struct{}{}, 12: struct{}{},
  190. },
  191. },
  192. {
  193. 7,
  194. &keyIndex{
  195. key: []byte("foo"),
  196. index: 12,
  197. generations: []generation{
  198. {ver: 3, cont: []uint64{8, 10, 12}},
  199. {},
  200. },
  201. },
  202. map[uint64]struct{}{
  203. 8: struct{}{}, 10: struct{}{}, 12: struct{}{},
  204. },
  205. },
  206. {
  207. 8,
  208. &keyIndex{
  209. key: []byte("foo"),
  210. index: 12,
  211. generations: []generation{
  212. {ver: 3, cont: []uint64{8, 10, 12}},
  213. {},
  214. },
  215. },
  216. map[uint64]struct{}{
  217. 8: struct{}{}, 10: struct{}{}, 12: struct{}{},
  218. },
  219. },
  220. {
  221. 9,
  222. &keyIndex{
  223. key: []byte("foo"),
  224. index: 12,
  225. generations: []generation{
  226. {ver: 3, cont: []uint64{8, 10, 12}},
  227. {},
  228. },
  229. },
  230. map[uint64]struct{}{
  231. 8: struct{}{}, 10: struct{}{}, 12: struct{}{},
  232. },
  233. },
  234. {
  235. 10,
  236. &keyIndex{
  237. key: []byte("foo"),
  238. index: 12,
  239. generations: []generation{
  240. {ver: 3, cont: []uint64{10, 12}},
  241. {},
  242. },
  243. },
  244. map[uint64]struct{}{
  245. 10: struct{}{}, 12: struct{}{},
  246. },
  247. },
  248. {
  249. 11,
  250. &keyIndex{
  251. key: []byte("foo"),
  252. index: 12,
  253. generations: []generation{
  254. {ver: 3, cont: []uint64{10, 12}},
  255. {},
  256. },
  257. },
  258. map[uint64]struct{}{
  259. 10: struct{}{}, 12: struct{}{},
  260. },
  261. },
  262. {
  263. 12,
  264. &keyIndex{
  265. key: []byte("foo"),
  266. index: 12,
  267. generations: []generation{
  268. {ver: 3, cont: []uint64{12}},
  269. {},
  270. },
  271. },
  272. map[uint64]struct{}{
  273. 12: struct{}{},
  274. },
  275. },
  276. {
  277. 13,
  278. &keyIndex{
  279. key: []byte("foo"),
  280. index: 12,
  281. generations: []generation{
  282. {},
  283. },
  284. },
  285. map[uint64]struct{}{},
  286. },
  287. }
  288. // Continous Compaction
  289. ki := newTestKeyIndex()
  290. for i, tt := range tests {
  291. am := make(map[uint64]struct{})
  292. ki.compact(tt.compact, am)
  293. if !reflect.DeepEqual(ki, tt.wki) {
  294. t.Errorf("#%d: ki = %+v, want %+v", i, ki, tt.wki)
  295. }
  296. if !reflect.DeepEqual(am, tt.wam) {
  297. t.Errorf("#%d: am = %+v, want %+v", am, tt.wam)
  298. }
  299. }
  300. // Jump Compaction
  301. for i, tt := range tests {
  302. if (i%2 == 0 && i < 6) && (i%2 == 1 && i > 6) {
  303. am := make(map[uint64]struct{})
  304. ki.compact(tt.compact, am)
  305. if !reflect.DeepEqual(ki, tt.wki) {
  306. t.Errorf("#%d: ki = %+v, want %+v", i, ki, tt.wki)
  307. }
  308. if !reflect.DeepEqual(am, tt.wam) {
  309. t.Errorf("#%d: am = %+v, want %+v", am, tt.wam)
  310. }
  311. }
  312. }
  313. // OnceCompaction
  314. for i, tt := range tests {
  315. ki := newTestKeyIndex()
  316. am := make(map[uint64]struct{})
  317. ki.compact(tt.compact, am)
  318. if !reflect.DeepEqual(ki, tt.wki) {
  319. t.Errorf("#%d: ki = %+v, want %+v", i, ki, tt.wki)
  320. }
  321. if !reflect.DeepEqual(am, tt.wam) {
  322. t.Errorf("#%d: am = %+v, want %+v", am, tt.wam)
  323. }
  324. }
  325. }
  326. func newTestKeyIndex() *keyIndex {
  327. // key: "foo"
  328. // index: 12
  329. // generations:
  330. // {empty}
  331. // {8[1], 10[2], 12(t)[3]}
  332. // {2[1], 4[2], 6(t)[3]}
  333. ki := &keyIndex{key: []byte("foo")}
  334. ki.put(2)
  335. ki.put(4)
  336. ki.tombstone(6)
  337. ki.put(8)
  338. ki.put(10)
  339. ki.tombstone(12)
  340. return ki
  341. }