/test/merge.erl

https://gitlab.com/barrel-db/erlang-rocksdb · Erlang · 346 lines · 248 code · 81 blank · 17 comment · 0 complexity · 3dd95eddad1ee875bc4d1964f1479250 MD5 · raw file

  1. %% Copyright (c) 2018-2020 Benoit Chesneau
  2. %%
  3. %% This file is provided to you under the Apache License,
  4. %% Version 2.0 (the "License"); you may not use this file
  5. %% except in compliance with the License. You may obtain
  6. %% a copy of the License at
  7. %%
  8. %% http://www.apache.org/licenses/LICENSE-2.0
  9. %%
  10. %% Unless required by applicable law or agreed to in writing,
  11. %% software distributed under the License is distributed on an
  12. %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  13. %% KIND, either express or implied. See the License for the
  14. %% specific language governing permissions and limitations
  15. %% under the License.
  16. %%
  17. %% -------------------------------------------------------------------
  18. -module(merge).
  19. -include_lib("eunit/include/eunit.hrl").
  20. merge_int_test() ->
  21. rocksdb_test_util:rm_rf("rocksdb_merge_db.test"),
  22. {ok, Db} = rocksdb:open("rocksdb_merge_db.test",
  23. [{create_if_missing, true},
  24. {merge_operator, erlang_merge_operator}]),
  25. ok = rocksdb:put(Db, <<"i">>, term_to_binary(0), []),
  26. {ok, IBin0} = rocksdb:get(Db, <<"i">>, []),
  27. 0 = binary_to_term(IBin0),
  28. ok = rocksdb:merge(Db, <<"i">>, term_to_binary({int_add, 1}), []),
  29. {ok, IBin1} = rocksdb:get(Db, <<"i">>, []),
  30. 1 = binary_to_term(IBin1),
  31. ok = rocksdb:merge(Db, <<"i">>, term_to_binary({int_add, 2}), []),
  32. {ok, IBin2} = rocksdb:get(Db, <<"i">>, []),
  33. 3 = binary_to_term(IBin2),
  34. ok = rocksdb:merge(Db, <<"i">>, term_to_binary({int_add, -1}), []),
  35. {ok, IBin3} = rocksdb:get(Db, <<"i">>, []),
  36. 2 = binary_to_term(IBin3),
  37. ok = rocksdb:put(Db, <<"i">>, term_to_binary(0), []),
  38. {ok, IBin4} = rocksdb:get(Db, <<"i">>, []),
  39. 0 = binary_to_term(IBin4),
  40. ok = rocksdb:close(Db),
  41. ok = destroy_and_rm("rocksdb_merge_db.test", []).
  42. merge_list_append_test() ->
  43. rocksdb_test_util:rm_rf("rocksdb_merge_db.test"),
  44. {ok, Db} = rocksdb:open("rocksdb_merge_db.test",
  45. [{create_if_missing, true},
  46. {merge_operator, erlang_merge_operator}]),
  47. ok = rocksdb:put(Db, <<"list">>, term_to_binary([a, b]), []),
  48. {ok, Bin0} = rocksdb:get(Db, <<"list">>, []),
  49. [a, b] = binary_to_term(Bin0),
  50. ok = rocksdb:merge(Db, <<"list">>, term_to_binary({list_append, [c, d]}), []),
  51. {ok, Bin1} = rocksdb:get(Db, <<"list">>, []),
  52. [a, b, c, d] = binary_to_term(Bin1),
  53. ok = rocksdb:merge(Db, <<"list">>, term_to_binary({list_append, [d, e]}), []),
  54. {ok, Bin2} = rocksdb:get(Db, <<"list">>, []),
  55. [a, b, c, d, d, e] = binary_to_term(Bin2),
  56. ok = rocksdb:merge(Db, <<"list">>, term_to_binary({list_append, []}), []),
  57. {ok, Bin2} = rocksdb:get(Db, <<"list">>, []),
  58. ok = rocksdb:close(Db),
  59. ok = destroy_and_rm("rocksdb_merge_db.test", []).
  60. merge_list_substract_test() ->
  61. rocksdb_test_util:rm_rf("rocksdb_merge_db.test"),
  62. {ok, Db} = rocksdb:open("rocksdb_merge_db.test",
  63. [{create_if_missing, true},
  64. {merge_operator, erlang_merge_operator}]),
  65. ok = rocksdb:put(Db, <<"list">>, term_to_binary([a, b, c, d, e, a, b, c]), []),
  66. {ok, Bin0} = rocksdb:get(Db, <<"list">>, []),
  67. [a, b, c, d, e, a, b, c] = binary_to_term(Bin0),
  68. ok = rocksdb:merge(Db, <<"list">>, term_to_binary({list_substract, [c, a]}), []),
  69. {ok, Bin1} = rocksdb:get(Db, <<"list">>, []),
  70. [b, d, e, a, b, c] = binary_to_term(Bin1),
  71. ok = rocksdb:close(Db),
  72. ok = destroy_and_rm("rocksdb_merge_db.test", []).
  73. merge_list_set_test() ->
  74. rocksdb_test_util:rm_rf("rocksdb_merge_db.test"),
  75. {ok, Db} = rocksdb:open("rocksdb_merge_db.test",
  76. [{create_if_missing, true},
  77. {merge_operator, erlang_merge_operator}]),
  78. ok = rocksdb:put(Db, <<"list">>, term_to_binary([a, b, c, d, e]), []),
  79. {ok, Bin0} = rocksdb:get(Db, <<"list">>, []),
  80. [a, b, c, d, e] = binary_to_term(Bin0),
  81. ok = rocksdb:merge(Db, <<"list">>, term_to_binary({list_set, 2, 'c1'}), []),
  82. {ok, Bin1} = rocksdb:get(Db, <<"list">>, []),
  83. [a, b, 'c1', d, e] = binary_to_term(Bin1),
  84. ok = rocksdb:merge(Db, <<"list">>, term_to_binary({list_set, 4, 'e1'}), []),
  85. {ok, Bin2} = rocksdb:get(Db, <<"list">>, []),
  86. [a, b, 'c1', d, 'e1'] = binary_to_term(Bin2),
  87. ok = rocksdb:merge(Db, <<"list">>, term_to_binary({list_set, 5, error}), []),
  88. {ok, Bin2} = rocksdb:get(Db, <<"list">>, []),
  89. ok = rocksdb:close(Db),
  90. ok = destroy_and_rm("rocksdb_merge_db.test", []).
  91. merge_list_delete_test() ->
  92. rocksdb_test_util:rm_rf("rocksdb_merge_db.test"),
  93. {ok, Db} = rocksdb:open("rocksdb_merge_db.test",
  94. [{create_if_missing, true},
  95. {merge_operator, erlang_merge_operator}]),
  96. ok = rocksdb:put(Db, <<"list">>, term_to_binary([a, b, c, d, e, f, g]), []),
  97. {ok, Bin0} = rocksdb:get(Db, <<"list">>, []),
  98. [a, b, c, d, e, f, g] = binary_to_term(Bin0),
  99. ok = rocksdb:merge(Db, <<"list">>, term_to_binary({list_delete, 2}), []),
  100. {ok, Bin1} = rocksdb:get(Db, <<"list">>, []),
  101. [a, b, d, e, f, g] = binary_to_term(Bin1),
  102. ok = rocksdb:merge(Db, <<"list">>, term_to_binary({list_delete, 2, 4}), []),
  103. {ok, Bin2} = rocksdb:get(Db, <<"list">>, []),
  104. [a, b, g] = binary_to_term(Bin2),
  105. ok = rocksdb:merge(Db, <<"list">>, term_to_binary({list_delete, 3}), []),
  106. {ok, Bin2} = rocksdb:get(Db, <<"list">>, []),
  107. ok = rocksdb:merge(Db, <<"list">>, term_to_binary({list_delete, 6}), []),
  108. {ok, Bin2} = rocksdb:get(Db, <<"list">>, []),
  109. ok = rocksdb:merge(Db, <<"list">>, term_to_binary({list_delete, 2}), []),
  110. {ok, Bin3} = rocksdb:get(Db, <<"list">>, []),
  111. [a, b] = binary_to_term(Bin3),
  112. ok = rocksdb:close(Db),
  113. ok = destroy_and_rm("rocksdb_merge_db.test", []).
  114. merge_list_insert_test() ->
  115. rocksdb_test_util:rm_rf("rocksdb_merge_db.test"),
  116. {ok, Db} = rocksdb:open("rocksdb_merge_db.test",
  117. [{create_if_missing, true},
  118. {merge_operator, erlang_merge_operator}]),
  119. ok = rocksdb:put(Db, <<"list">>, term_to_binary([a, b, c, d, e, f, g]), []),
  120. {ok, Bin0} = rocksdb:get(Db, <<"list">>, []),
  121. [a, b, c, d, e, f, g] = binary_to_term(Bin0),
  122. ok = rocksdb:merge(Db, <<"list">>, term_to_binary({list_insert, 2, [h, i]}), []),
  123. {ok, Bin1} = rocksdb:get(Db, <<"list">>, []),
  124. [a, b, h, i, c, d, e, f, g] = binary_to_term(Bin1),
  125. ok = rocksdb:merge(Db, <<"list">>, term_to_binary({list_insert, 9, [j]}), []),
  126. {ok, Bin1} = rocksdb:get(Db, <<"list">>, []),
  127. ok = rocksdb:close(Db),
  128. ok = destroy_and_rm("rocksdb_merge_db.test", []).
  129. merge_binary_append_test() ->
  130. rocksdb_test_util:rm_rf("rocksdb_merge_db.test"),
  131. {ok, Db} = rocksdb:open("rocksdb_merge_db.test",
  132. [{create_if_missing, true},
  133. {merge_operator, erlang_merge_operator}]),
  134. ok = rocksdb:put(Db, <<"encbin">>, term_to_binary(<<"test">>), []),
  135. {ok, Bin} = rocksdb:get(Db, <<"encbin">>, []),
  136. <<"test">> = binary_to_term(Bin),
  137. ok = rocksdb:merge(Db, <<"encbin">>, term_to_binary({binary_append, <<"abc">>}), []),
  138. {ok, Bin1} = rocksdb:get(Db, <<"encbin">>, []),
  139. <<"testabc">> = binary_to_term(Bin1),
  140. ok = rocksdb:merge(Db, <<"encbin">>, term_to_binary({binary_append, <<"de">>}), []),
  141. {ok, Bin2} = rocksdb:get(Db, <<"encbin">>, []),
  142. <<"testabcde">> = binary_to_term(Bin2),
  143. ok = rocksdb:merge(Db, <<"empty">>, term_to_binary({binary_append, <<"abc">>}), []),
  144. {ok, Bin3} = rocksdb:get(Db, <<"empty">>, []),
  145. <<"abc">> = binary_to_term(Bin3),
  146. ok = rocksdb:close(Db),
  147. ok = destroy_and_rm("rocksdb_merge_db.test", []).
  148. merge_binary_replace_test() ->
  149. rocksdb_test_util:rm_rf("rocksdb_merge_db.test"),
  150. {ok, Db} = rocksdb:open("rocksdb_merge_db.test",
  151. [{create_if_missing, true},
  152. {merge_operator, erlang_merge_operator}]),
  153. ok = rocksdb:put(Db, <<"encbin">>, term_to_binary(<<"The quick brown fox jumps over the lazy dog.">>), []),
  154. {ok, Bin} = rocksdb:get(Db, <<"encbin">>, []),
  155. <<"The quick brown fox jumps over the lazy dog.">> = binary_to_term(Bin),
  156. ok = rocksdb:merge(Db, <<"encbin">>, term_to_binary({binary_replace, 10, 5, <<"red">>}), []),
  157. ok = rocksdb:merge(Db, <<"encbin">>, term_to_binary({binary_replace, 0, 3, <<"A">>}), []),
  158. {ok, Bin1} = rocksdb:get(Db, <<"encbin">>, []),
  159. <<"A quick red fox jumps over the lazy dog.">> = binary_to_term(Bin1),
  160. ok = rocksdb:put(Db, <<"bitmap">>, term_to_binary(<<1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1>>), []),
  161. ok = rocksdb:merge(Db, <<"bitmap">>, term_to_binary({binary_replace, 2, 1, <<0>>}), []),
  162. {ok, Bin2} = rocksdb:get(Db, <<"bitmap">>, []),
  163. <<1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1>> = binary_to_term(Bin2),
  164. ok = rocksdb:merge(Db, <<"bitmap">>, term_to_binary({binary_replace, 6, 1, <<0>>}), []),
  165. {ok, Bin3} = rocksdb:get(Db, <<"bitmap">>, []),
  166. <<1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1>> = binary_to_term(Bin3),
  167. ok = rocksdb:put(Db, <<"encbin1">>, term_to_binary(<<"abcdef">>), []),
  168. ok = rocksdb:merge(Db, <<"encbin1">>, term_to_binary({binary_replace, 6, 1, <<"A">>}), []),
  169. {ok, Bin4} = rocksdb:get(Db, <<"encbin1">>, []),
  170. <<"abcdef">> = binary_to_term(Bin4),
  171. ok = rocksdb:close(Db),
  172. ok = destroy_and_rm("rocksdb_merge_db.test", []).
  173. merge_binary_erase_test() ->
  174. rocksdb_test_util:rm_rf("rocksdb_merge_db.test"),
  175. {ok, Db} = rocksdb:open("rocksdb_merge_db.test",
  176. [{create_if_missing, true},
  177. {merge_operator, erlang_merge_operator}]),
  178. ok = rocksdb:put(Db, <<"eraseterm">>, term_to_binary(<<"abcdefghij">>), []),
  179. ok = rocksdb:merge(Db, <<"eraseterm">>, term_to_binary({binary_erase, 2, 4}), []),
  180. {ok, Bin} = rocksdb:get(Db, <<"eraseterm">>, []),
  181. <<"abghij">> = binary_to_term(Bin),
  182. ok = rocksdb:put(Db, <<"erase_end">>, term_to_binary(<<"abcdefghij">>), []),
  183. ok = rocksdb:merge(Db, <<"erase_end">>, term_to_binary({binary_erase, 9, 2}), []),
  184. {ok, Bin1} = rocksdb:get(Db, <<"erase_end">>, []),
  185. <<"abcdefghi">> = binary_to_term(Bin1),
  186. ok = rocksdb:put(Db, <<"erase_to_end1">>, term_to_binary(<<"abcdefghij">>), []),
  187. ok = rocksdb:merge(Db, <<"erase_to_end1">>, term_to_binary({binary_erase, 2, 9}), []),
  188. {ok, Bin2} = rocksdb:get(Db, <<"erase_to_end1">>, []),
  189. <<"ab">> = binary_to_term(Bin2),
  190. ok = rocksdb:put(Db, <<"erase_to_end2">>, term_to_binary(<<"abcdefghij">>), []),
  191. ok = rocksdb:merge(Db, <<"erase_to_end2">>, term_to_binary({binary_erase, 2, 8}), []),
  192. {ok, Bin3} = rocksdb:get(Db, <<"erase_to_end2">>, []),
  193. <<"ab">> = binary_to_term(Bin3),
  194. ok = rocksdb:close(Db),
  195. ok = destroy_and_rm("rocksdb_merge_db.test", []).
  196. merge_binary_insert_test() ->
  197. rocksdb_test_util:rm_rf("rocksdb_merge_db.test"),
  198. {ok, Db} = rocksdb:open("rocksdb_merge_db.test",
  199. [{create_if_missing, true},
  200. {merge_operator, erlang_merge_operator}]),
  201. ok = rocksdb:put(Db, <<"insertterm">>, term_to_binary(<<"abcdefghij">>), []),
  202. ok = rocksdb:merge(Db, <<"insertterm">>, term_to_binary({binary_insert, 2, <<"1234">>}), []),
  203. {ok, Bin} = rocksdb:get(Db, <<"insertterm">>, []),
  204. <<"ab1234cdefghij">> = binary_to_term(Bin),
  205. ok = rocksdb:put(Db, <<"insert">>, term_to_binary(<<"abcdefghij">>), []),
  206. ok = rocksdb:merge(Db, <<"insert">>, term_to_binary({binary_insert, 9, <<"1234">>}), []),
  207. {ok, Bin1} = rocksdb:get(Db, <<"insert">>, []),
  208. <<"abcdefghi1234j">> = binary_to_term(Bin1),
  209. ok = rocksdb:put(Db, <<"insert">>, term_to_binary(<<"abcdefghij">>), []),
  210. ok = rocksdb:merge(Db, <<"insert">>, term_to_binary({binary_insert, 10, <<"1234">>}), []),
  211. {ok, Bin2} = rocksdb:get(Db, <<"insert">>, []),
  212. <<"abcdefghij1234">> = binary_to_term(Bin2),
  213. ok = rocksdb:put(Db, <<"insert">>, term_to_binary(<<"abcdefghij">>), []),
  214. ok = rocksdb:merge(Db, <<"insert">>, term_to_binary({binary_insert, 11, <<"1234">>}), []),
  215. {ok, Bin3} = rocksdb:get(Db, <<"insert">>, []),
  216. <<"abcdefghij">> = binary_to_term(Bin3),
  217. ok = rocksdb:close(Db),
  218. ok = destroy_and_rm("rocksdb_merge_db.test", []).
  219. merge_bitset_test() ->
  220. rocksdb_test_util:rm_rf("rocksdb_merge_db.test"),
  221. {ok, Db} = rocksdb:open("rocksdb_merge_db.test",
  222. [{create_if_missing, true},
  223. {merge_operator, {bitset_merge_operator, 1024}}]),
  224. Bitmap = << 0:1024/unsigned >>,
  225. ok = rocksdb:put(Db, <<"bitmap">>, Bitmap, []),
  226. ok = rocksdb:merge(Db, <<"bitmap">>, <<"+2">>, []),
  227. {ok, << 32, _/binary>> = Bin1 } = rocksdb:get(Db, <<"bitmap">>, []),
  228. 1024 = bit_size(Bin1),
  229. ok = rocksdb:merge(Db, <<"bitmap">>, <<"-2">>, []),
  230. {ok, << 0, _/binary>> } = rocksdb:get(Db, <<"bitmap">>, []),
  231. ok = rocksdb:merge(Db, <<"bitmap">>, <<"+11">>, []),
  232. {ok, << 0, 16, _/binary>> } = rocksdb:get(Db, <<"bitmap">>, []),
  233. ok = rocksdb:merge(Db, <<"bitmap">>, <<"+10">>, []),
  234. {ok, << 0, 48, _/binary>> } = rocksdb:get(Db, <<"bitmap">>, []),
  235. ok = rocksdb:merge(Db, <<"bitmap">>, <<"">>, []),
  236. {ok, << 0, 0, _/binary>> = Bin2 } = rocksdb:get(Db, <<"bitmap">>, []),
  237. 1024 = bit_size(Bin2),
  238. ok = rocksdb:merge(Db, <<"unsetbitmap">>, <<"+2">>, []),
  239. {ok, << 32, _/binary>> } = rocksdb:get(Db, <<"unsetbitmap">>, []),
  240. ok = rocksdb:merge(Db, <<"unsetbitmap">>, <<"-2">>, []),
  241. {ok, << 0, _/binary>> } = rocksdb:get(Db, <<"unsetbitmap">>, []),
  242. ok = rocksdb:merge(Db, <<"unsetbitmap">>, <<"+11">>, []),
  243. {ok, << 0, 16, _/binary>> } = rocksdb:get(Db, <<"unsetbitmap">>, []),
  244. ok = rocksdb:merge(Db, <<"unsetbitmap">>, <<"+10">>, []),
  245. {ok, << 0, 48, _/binary>> } = rocksdb:get(Db, <<"unsetbitmap">>, []),
  246. ok = rocksdb:close(Db),
  247. ok = destroy_and_rm("rocksdb_merge_db.test", []).
  248. merge_counter_test() ->
  249. rocksdb_test_util:rm_rf("rocksdb_counter_merge_db.test"),
  250. {ok, Db} = rocksdb:open("rocksdb_counter_merge_db.test",
  251. [{create_if_missing, true},
  252. {merge_operator, counter_merge_operator}]),
  253. ok = rocksdb:merge(Db, <<"c">>, << "1" >>, []),
  254. {ok, << "1" >>} = rocksdb:get(Db, <<"c">>, []),
  255. ok = rocksdb:merge(Db, <<"c">>, << "2" >>, []),
  256. {ok, << "3" >>} = rocksdb:get(Db, <<"c">>, []),
  257. ok = rocksdb:merge(Db, <<"c">>, <<"-1">> , []),
  258. {ok, <<"2">>} = rocksdb:get(Db, <<"c">>, []),
  259. ok = rocksdb:put(Db, <<"c">>, <<"0">>, []),
  260. {ok, <<"0">>} = rocksdb:get(Db, <<"c">>, []),
  261. ok = rocksdb:close(Db),
  262. ok = destroy_and_rm("rocksdb_counter_merge_db.test", []).
  263. destroy_and_rm(Dir, Options) ->
  264. rocksdb:destroy(Dir, Options),
  265. rocksdb_test_util:rm_rf(Dir).