c_test.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. /* Copyright (c) 2011 The LevelDB Authors. All rights reserved.
  2. Use of this source code is governed by a BSD-style license that can be
  3. found in the LICENSE file. See the AUTHORS file for names of contributors. */
  4. #include "leveldb/c.h"
  5. #include <stddef.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. const char* phase = "";
  10. static void StartPhase(const char* name) {
  11. fprintf(stderr, "=== Test %s\n", name);
  12. phase = name;
  13. }
  14. #define CheckNoError(err) \
  15. if ((err) != NULL) { \
  16. fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, (err)); \
  17. abort(); \
  18. }
  19. #define CheckCondition(cond) \
  20. if (!(cond)) { \
  21. fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, #cond); \
  22. abort(); \
  23. }
  24. static void CheckEqual(const char* expected, const char* v, size_t n) {
  25. if (expected == NULL && v == NULL) {
  26. // ok
  27. } else if (expected != NULL && v != NULL && n == strlen(expected) &&
  28. memcmp(expected, v, n) == 0) {
  29. // ok
  30. return;
  31. } else {
  32. fprintf(stderr, "%s: expected '%s', got '%s'\n",
  33. phase,
  34. (expected ? expected : "(null)"),
  35. (v ? v : "(null"));
  36. abort();
  37. }
  38. }
  39. static void Free(char** ptr) {
  40. if (*ptr) {
  41. free(*ptr);
  42. *ptr = NULL;
  43. }
  44. }
  45. static void CheckGet(
  46. leveldb_t* db,
  47. const leveldb_readoptions_t* options,
  48. const char* key,
  49. const char* expected) {
  50. char* err = NULL;
  51. size_t val_len;
  52. char* val;
  53. val = leveldb_get(db, options, key, strlen(key), &val_len, &err);
  54. CheckNoError(err);
  55. CheckEqual(expected, val, val_len);
  56. Free(&val);
  57. }
  58. static void CheckIter(leveldb_iterator_t* iter,
  59. const char* key, const char* val) {
  60. size_t len;
  61. const char* str;
  62. str = leveldb_iter_key(iter, &len);
  63. CheckEqual(key, str, len);
  64. str = leveldb_iter_value(iter, &len);
  65. CheckEqual(val, str, len);
  66. }
  67. // Callback from leveldb_writebatch_iterate()
  68. static void CheckPut(void* ptr,
  69. const char* k, size_t klen,
  70. const char* v, size_t vlen) {
  71. int* state = (int*) ptr;
  72. CheckCondition(*state < 2);
  73. switch (*state) {
  74. case 0:
  75. CheckEqual("bar", k, klen);
  76. CheckEqual("b", v, vlen);
  77. break;
  78. case 1:
  79. CheckEqual("box", k, klen);
  80. CheckEqual("c", v, vlen);
  81. break;
  82. }
  83. (*state)++;
  84. }
  85. // Callback from leveldb_writebatch_iterate()
  86. static void CheckDel(void* ptr, const char* k, size_t klen) {
  87. int* state = (int*) ptr;
  88. CheckCondition(*state == 2);
  89. CheckEqual("bar", k, klen);
  90. (*state)++;
  91. }
  92. static void CmpDestroy(void* arg) { }
  93. static int CmpCompare(void* arg, const char* a, size_t alen,
  94. const char* b, size_t blen) {
  95. int n = (alen < blen) ? alen : blen;
  96. int r = memcmp(a, b, n);
  97. if (r == 0) {
  98. if (alen < blen) r = -1;
  99. else if (alen > blen) r = +1;
  100. }
  101. return r;
  102. }
  103. static const char* CmpName(void* arg) {
  104. return "foo";
  105. }
  106. // Custom filter policy
  107. static unsigned char fake_filter_result = 1;
  108. static void FilterDestroy(void* arg) { }
  109. static const char* FilterName(void* arg) {
  110. return "TestFilter";
  111. }
  112. static char* FilterCreate(
  113. void* arg,
  114. const char* const* key_array, const size_t* key_length_array,
  115. int num_keys,
  116. size_t* filter_length) {
  117. *filter_length = 4;
  118. char* result = malloc(4);
  119. memcpy(result, "fake", 4);
  120. return result;
  121. }
  122. unsigned char FilterKeyMatch(
  123. void* arg,
  124. const char* key, size_t length,
  125. const char* filter, size_t filter_length) {
  126. CheckCondition(filter_length == 4);
  127. CheckCondition(memcmp(filter, "fake", 4) == 0);
  128. return fake_filter_result;
  129. }
  130. int main(int argc, char** argv) {
  131. leveldb_t* db;
  132. leveldb_comparator_t* cmp;
  133. leveldb_cache_t* cache;
  134. leveldb_env_t* env;
  135. leveldb_options_t* options;
  136. leveldb_readoptions_t* roptions;
  137. leveldb_writeoptions_t* woptions;
  138. char* dbname;
  139. char* err = NULL;
  140. int run = -1;
  141. CheckCondition(leveldb_major_version() >= 1);
  142. CheckCondition(leveldb_minor_version() >= 1);
  143. StartPhase("create_objects");
  144. cmp = leveldb_comparator_create(NULL, CmpDestroy, CmpCompare, CmpName);
  145. env = leveldb_create_default_env();
  146. cache = leveldb_cache_create_lru(100000);
  147. dbname = leveldb_env_get_test_directory(env);
  148. CheckCondition(dbname != NULL);
  149. options = leveldb_options_create();
  150. leveldb_options_set_comparator(options, cmp);
  151. leveldb_options_set_error_if_exists(options, 1);
  152. leveldb_options_set_cache(options, cache);
  153. leveldb_options_set_env(options, env);
  154. leveldb_options_set_info_log(options, NULL);
  155. leveldb_options_set_write_buffer_size(options, 100000);
  156. leveldb_options_set_paranoid_checks(options, 1);
  157. leveldb_options_set_max_open_files(options, 10);
  158. leveldb_options_set_block_size(options, 1024);
  159. leveldb_options_set_block_restart_interval(options, 8);
  160. leveldb_options_set_max_file_size(options, 3 << 20);
  161. leveldb_options_set_compression(options, leveldb_no_compression);
  162. roptions = leveldb_readoptions_create();
  163. leveldb_readoptions_set_verify_checksums(roptions, 1);
  164. leveldb_readoptions_set_fill_cache(roptions, 0);
  165. woptions = leveldb_writeoptions_create();
  166. leveldb_writeoptions_set_sync(woptions, 1);
  167. StartPhase("destroy");
  168. leveldb_destroy_db(options, dbname, &err);
  169. Free(&err);
  170. StartPhase("open_error");
  171. db = leveldb_open(options, dbname, &err);
  172. CheckCondition(err != NULL);
  173. Free(&err);
  174. StartPhase("leveldb_free");
  175. db = leveldb_open(options, dbname, &err);
  176. CheckCondition(err != NULL);
  177. leveldb_free(err);
  178. err = NULL;
  179. StartPhase("open");
  180. leveldb_options_set_create_if_missing(options, 1);
  181. db = leveldb_open(options, dbname, &err);
  182. CheckNoError(err);
  183. CheckGet(db, roptions, "foo", NULL);
  184. StartPhase("put");
  185. leveldb_put(db, woptions, "foo", 3, "hello", 5, &err);
  186. CheckNoError(err);
  187. CheckGet(db, roptions, "foo", "hello");
  188. StartPhase("compactall");
  189. leveldb_compact_range(db, NULL, 0, NULL, 0);
  190. CheckGet(db, roptions, "foo", "hello");
  191. StartPhase("compactrange");
  192. leveldb_compact_range(db, "a", 1, "z", 1);
  193. CheckGet(db, roptions, "foo", "hello");
  194. StartPhase("writebatch");
  195. {
  196. leveldb_writebatch_t* wb = leveldb_writebatch_create();
  197. leveldb_writebatch_put(wb, "foo", 3, "a", 1);
  198. leveldb_writebatch_clear(wb);
  199. leveldb_writebatch_put(wb, "bar", 3, "b", 1);
  200. leveldb_writebatch_put(wb, "box", 3, "c", 1);
  201. leveldb_writebatch_t* wb2 = leveldb_writebatch_create();
  202. leveldb_writebatch_delete(wb2, "bar", 3);
  203. leveldb_writebatch_append(wb, wb2);
  204. leveldb_writebatch_destroy(wb2);
  205. leveldb_write(db, woptions, wb, &err);
  206. CheckNoError(err);
  207. CheckGet(db, roptions, "foo", "hello");
  208. CheckGet(db, roptions, "bar", NULL);
  209. CheckGet(db, roptions, "box", "c");
  210. int pos = 0;
  211. leveldb_writebatch_iterate(wb, &pos, CheckPut, CheckDel);
  212. CheckCondition(pos == 3);
  213. leveldb_writebatch_destroy(wb);
  214. }
  215. StartPhase("iter");
  216. {
  217. leveldb_iterator_t* iter = leveldb_create_iterator(db, roptions);
  218. CheckCondition(!leveldb_iter_valid(iter));
  219. leveldb_iter_seek_to_first(iter);
  220. CheckCondition(leveldb_iter_valid(iter));
  221. CheckIter(iter, "box", "c");
  222. leveldb_iter_next(iter);
  223. CheckIter(iter, "foo", "hello");
  224. leveldb_iter_prev(iter);
  225. CheckIter(iter, "box", "c");
  226. leveldb_iter_prev(iter);
  227. CheckCondition(!leveldb_iter_valid(iter));
  228. leveldb_iter_seek_to_last(iter);
  229. CheckIter(iter, "foo", "hello");
  230. leveldb_iter_seek(iter, "b", 1);
  231. CheckIter(iter, "box", "c");
  232. leveldb_iter_get_error(iter, &err);
  233. CheckNoError(err);
  234. leveldb_iter_destroy(iter);
  235. }
  236. StartPhase("approximate_sizes");
  237. {
  238. int i;
  239. int n = 20000;
  240. char keybuf[100];
  241. char valbuf[100];
  242. uint64_t sizes[2];
  243. const char* start[2] = { "a", "k00000000000000010000" };
  244. size_t start_len[2] = { 1, 21 };
  245. const char* limit[2] = { "k00000000000000010000", "z" };
  246. size_t limit_len[2] = { 21, 1 };
  247. leveldb_writeoptions_set_sync(woptions, 0);
  248. for (i = 0; i < n; i++) {
  249. snprintf(keybuf, sizeof(keybuf), "k%020d", i);
  250. snprintf(valbuf, sizeof(valbuf), "v%020d", i);
  251. leveldb_put(db, woptions, keybuf, strlen(keybuf), valbuf, strlen(valbuf),
  252. &err);
  253. CheckNoError(err);
  254. }
  255. leveldb_approximate_sizes(db, 2, start, start_len, limit, limit_len, sizes);
  256. CheckCondition(sizes[0] > 0);
  257. CheckCondition(sizes[1] > 0);
  258. }
  259. StartPhase("property");
  260. {
  261. char* prop = leveldb_property_value(db, "nosuchprop");
  262. CheckCondition(prop == NULL);
  263. prop = leveldb_property_value(db, "leveldb.stats");
  264. CheckCondition(prop != NULL);
  265. Free(&prop);
  266. }
  267. StartPhase("snapshot");
  268. {
  269. const leveldb_snapshot_t* snap;
  270. snap = leveldb_create_snapshot(db);
  271. leveldb_delete(db, woptions, "foo", 3, &err);
  272. CheckNoError(err);
  273. leveldb_readoptions_set_snapshot(roptions, snap);
  274. CheckGet(db, roptions, "foo", "hello");
  275. leveldb_readoptions_set_snapshot(roptions, NULL);
  276. CheckGet(db, roptions, "foo", NULL);
  277. leveldb_release_snapshot(db, snap);
  278. }
  279. StartPhase("repair");
  280. {
  281. leveldb_close(db);
  282. leveldb_options_set_create_if_missing(options, 0);
  283. leveldb_options_set_error_if_exists(options, 0);
  284. leveldb_repair_db(options, dbname, &err);
  285. CheckNoError(err);
  286. db = leveldb_open(options, dbname, &err);
  287. CheckNoError(err);
  288. CheckGet(db, roptions, "foo", NULL);
  289. CheckGet(db, roptions, "bar", NULL);
  290. CheckGet(db, roptions, "box", "c");
  291. leveldb_options_set_create_if_missing(options, 1);
  292. leveldb_options_set_error_if_exists(options, 1);
  293. }
  294. StartPhase("filter");
  295. for (run = 0; run < 2; run++) {
  296. // First run uses custom filter, second run uses bloom filter
  297. CheckNoError(err);
  298. leveldb_filterpolicy_t* policy;
  299. if (run == 0) {
  300. policy = leveldb_filterpolicy_create(
  301. NULL, FilterDestroy, FilterCreate, FilterKeyMatch, FilterName);
  302. } else {
  303. policy = leveldb_filterpolicy_create_bloom(10);
  304. }
  305. // Create new database
  306. leveldb_close(db);
  307. leveldb_destroy_db(options, dbname, &err);
  308. leveldb_options_set_filter_policy(options, policy);
  309. db = leveldb_open(options, dbname, &err);
  310. CheckNoError(err);
  311. leveldb_put(db, woptions, "foo", 3, "foovalue", 8, &err);
  312. CheckNoError(err);
  313. leveldb_put(db, woptions, "bar", 3, "barvalue", 8, &err);
  314. CheckNoError(err);
  315. leveldb_compact_range(db, NULL, 0, NULL, 0);
  316. fake_filter_result = 1;
  317. CheckGet(db, roptions, "foo", "foovalue");
  318. CheckGet(db, roptions, "bar", "barvalue");
  319. if (phase == 0) {
  320. // Must not find value when custom filter returns false
  321. fake_filter_result = 0;
  322. CheckGet(db, roptions, "foo", NULL);
  323. CheckGet(db, roptions, "bar", NULL);
  324. fake_filter_result = 1;
  325. CheckGet(db, roptions, "foo", "foovalue");
  326. CheckGet(db, roptions, "bar", "barvalue");
  327. }
  328. leveldb_options_set_filter_policy(options, NULL);
  329. leveldb_filterpolicy_destroy(policy);
  330. }
  331. StartPhase("cleanup");
  332. leveldb_close(db);
  333. leveldb_options_destroy(options);
  334. leveldb_readoptions_destroy(roptions);
  335. leveldb_writeoptions_destroy(woptions);
  336. leveldb_free(dbname);
  337. leveldb_cache_destroy(cache);
  338. leveldb_comparator_destroy(cmp);
  339. leveldb_env_destroy(env);
  340. fprintf(stderr, "PASS\n");
  341. return 0;
  342. }