git / moonbite-core / src/leveldb/db/c_test.c · raw

/* Copyright (c) 2011 The LevelDB Authors. All rights reserved.   Use of this source code is governed by a BSD-style license that can be   found in the LICENSE file. See the AUTHORS file for names of contributors. */#include "leveldb/c.h"#include <stddef.h>#include <stdio.h>#include <stdlib.h>#include <string.h>const char* phase = "";static void StartPhase(const char* name) {  fprintf(stderr, "=== Test %s\n", name);  phase = name;}#define CheckNoError(err)                                               \  if ((err) != NULL) {                                                  \    fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, (err)); \    abort();                                                            \  }#define CheckCondition(cond)                                            \  if (!(cond)) {                                                        \    fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, #cond); \    abort();                                                            \  }static void CheckEqual(const char* expected, const char* v, size_t n) {  if (expected == NULL && v == NULL) {    // ok  } else if (expected != NULL && v != NULL && n == strlen(expected) &&             memcmp(expected, v, n) == 0) {    // ok    return;  } else {    fprintf(stderr, "%s: expected '%s', got '%s'\n",            phase,            (expected ? expected : "(null)"),            (v ? v : "(null"));    abort();  }}static void Free(char** ptr) {  if (*ptr) {    free(*ptr);    *ptr = NULL;  }}static void CheckGet(    leveldb_t* db,    const leveldb_readoptions_t* options,    const char* key,    const char* expected) {  char* err = NULL;  size_t val_len;  char* val;  val = leveldb_get(db, options, key, strlen(key), &val_len, &err);  CheckNoError(err);  CheckEqual(expected, val, val_len);  Free(&val);}static void CheckIter(leveldb_iterator_t* iter,                      const char* key, const char* val) {  size_t len;  const char* str;  str = leveldb_iter_key(iter, &len);  CheckEqual(key, str, len);  str = leveldb_iter_value(iter, &len);  CheckEqual(val, str, len);}// Callback from leveldb_writebatch_iterate()static void CheckPut(void* ptr,                     const char* k, size_t klen,                     const char* v, size_t vlen) {  int* state = (int*) ptr;  CheckCondition(*state < 2);  switch (*state) {    case 0:      CheckEqual("bar", k, klen);      CheckEqual("b", v, vlen);      break;    case 1:      CheckEqual("box", k, klen);      CheckEqual("c", v, vlen);      break;  }  (*state)++;}// Callback from leveldb_writebatch_iterate()static void CheckDel(void* ptr, const char* k, size_t klen) {  int* state = (int*) ptr;  CheckCondition(*state == 2);  CheckEqual("bar", k, klen);  (*state)++;}static void CmpDestroy(void* arg) { }static int CmpCompare(void* arg, const char* a, size_t alen,                      const char* b, size_t blen) {  int n = (alen < blen) ? alen : blen;  int r = memcmp(a, b, n);  if (r == 0) {    if (alen < blen) r = -1;    else if (alen > blen) r = +1;  }  return r;}static const char* CmpName(void* arg) {  return "foo";}// Custom filter policystatic uint8_t fake_filter_result = 1;static void FilterDestroy(void* arg) { }static const char* FilterName(void* arg) {  return "TestFilter";}static char* FilterCreate(    void* arg,    const char* const* key_array, const size_t* key_length_array,    int num_keys,    size_t* filter_length) {  *filter_length = 4;  char* result = malloc(4);  memcpy(result, "fake", 4);  return result;}uint8_t FilterKeyMatch(void* arg, const char* key, size_t length,                       const char* filter, size_t filter_length) {  CheckCondition(filter_length == 4);  CheckCondition(memcmp(filter, "fake", 4) == 0);  return fake_filter_result;}int main(int argc, char** argv) {  leveldb_t* db;  leveldb_comparator_t* cmp;  leveldb_cache_t* cache;  leveldb_env_t* env;  leveldb_options_t* options;  leveldb_readoptions_t* roptions;  leveldb_writeoptions_t* woptions;  char* dbname;  char* err = NULL;  int run = -1;  CheckCondition(leveldb_major_version() >= 1);  CheckCondition(leveldb_minor_version() >= 1);  StartPhase("create_objects");  cmp = leveldb_comparator_create(NULL, CmpDestroy, CmpCompare, CmpName);  env = leveldb_create_default_env();  cache = leveldb_cache_create_lru(100000);  dbname = leveldb_env_get_test_directory(env);  CheckCondition(dbname != NULL);  options = leveldb_options_create();  leveldb_options_set_comparator(options, cmp);  leveldb_options_set_error_if_exists(options, 1);  leveldb_options_set_cache(options, cache);  leveldb_options_set_env(options, env);  leveldb_options_set_info_log(options, NULL);  leveldb_options_set_write_buffer_size(options, 100000);  leveldb_options_set_paranoid_checks(options, 1);  leveldb_options_set_max_open_files(options, 10);  leveldb_options_set_block_size(options, 1024);  leveldb_options_set_block_restart_interval(options, 8);  leveldb_options_set_max_file_size(options, 3 << 20);  leveldb_options_set_compression(options, leveldb_no_compression);  roptions = leveldb_readoptions_create();  leveldb_readoptions_set_verify_checksums(roptions, 1);  leveldb_readoptions_set_fill_cache(roptions, 0);  woptions = leveldb_writeoptions_create();  leveldb_writeoptions_set_sync(woptions, 1);  StartPhase("destroy");  leveldb_destroy_db(options, dbname, &err);  Free(&err);  StartPhase("open_error");  db = leveldb_open(options, dbname, &err);  CheckCondition(err != NULL);  Free(&err);  StartPhase("leveldb_free");  db = leveldb_open(options, dbname, &err);  CheckCondition(err != NULL);  leveldb_free(err);  err = NULL;  StartPhase("open");  leveldb_options_set_create_if_missing(options, 1);  db = leveldb_open(options, dbname, &err);  CheckNoError(err);  CheckGet(db, roptions, "foo", NULL);  StartPhase("put");  leveldb_put(db, woptions, "foo", 3, "hello", 5, &err);  CheckNoError(err);  CheckGet(db, roptions, "foo", "hello");  StartPhase("compactall");  leveldb_compact_range(db, NULL, 0, NULL, 0);  CheckGet(db, roptions, "foo", "hello");  StartPhase("compactrange");  leveldb_compact_range(db, "a", 1, "z", 1);  CheckGet(db, roptions, "foo", "hello");  StartPhase("writebatch");  {    leveldb_writebatch_t* wb = leveldb_writebatch_create();    leveldb_writebatch_put(wb, "foo", 3, "a", 1);    leveldb_writebatch_clear(wb);    leveldb_writebatch_put(wb, "bar", 3, "b", 1);    leveldb_writebatch_put(wb, "box", 3, "c", 1);    leveldb_writebatch_t* wb2 = leveldb_writebatch_create();    leveldb_writebatch_delete(wb2, "bar", 3);    leveldb_writebatch_append(wb, wb2);    leveldb_writebatch_destroy(wb2);    leveldb_write(db, woptions, wb, &err);    CheckNoError(err);    CheckGet(db, roptions, "foo", "hello");    CheckGet(db, roptions, "bar", NULL);    CheckGet(db, roptions, "box", "c");    int pos = 0;    leveldb_writebatch_iterate(wb, &pos, CheckPut, CheckDel);    CheckCondition(pos == 3);    leveldb_writebatch_destroy(wb);  }  StartPhase("iter");  {    leveldb_iterator_t* iter = leveldb_create_iterator(db, roptions);    CheckCondition(!leveldb_iter_valid(iter));    leveldb_iter_seek_to_first(iter);    CheckCondition(leveldb_iter_valid(iter));    CheckIter(iter, "box", "c");    leveldb_iter_next(iter);    CheckIter(iter, "foo", "hello");    leveldb_iter_prev(iter);    CheckIter(iter, "box", "c");    leveldb_iter_prev(iter);    CheckCondition(!leveldb_iter_valid(iter));    leveldb_iter_seek_to_last(iter);    CheckIter(iter, "foo", "hello");    leveldb_iter_seek(iter, "b", 1);    CheckIter(iter, "box", "c");    leveldb_iter_get_error(iter, &err);    CheckNoError(err);    leveldb_iter_destroy(iter);  }  StartPhase("approximate_sizes");  {    int i;    int n = 20000;    char keybuf[100];    char valbuf[100];    uint64_t sizes[2];    const char* start[2] = { "a", "k00000000000000010000" };    size_t start_len[2] = { 1, 21 };    const char* limit[2] = { "k00000000000000010000", "z" };    size_t limit_len[2] = { 21, 1 };    leveldb_writeoptions_set_sync(woptions, 0);    for (i = 0; i < n; i++) {      snprintf(keybuf, sizeof(keybuf), "k%020d", i);      snprintf(valbuf, sizeof(valbuf), "v%020d", i);      leveldb_put(db, woptions, keybuf, strlen(keybuf), valbuf, strlen(valbuf),                  &err);      CheckNoError(err);    }    leveldb_approximate_sizes(db, 2, start, start_len, limit, limit_len, sizes);    CheckCondition(sizes[0] > 0);    CheckCondition(sizes[1] > 0);  }  StartPhase("property");  {    char* prop = leveldb_property_value(db, "nosuchprop");    CheckCondition(prop == NULL);    prop = leveldb_property_value(db, "leveldb.stats");    CheckCondition(prop != NULL);    Free(&prop);  }  StartPhase("snapshot");  {    const leveldb_snapshot_t* snap;    snap = leveldb_create_snapshot(db);    leveldb_delete(db, woptions, "foo", 3, &err);    CheckNoError(err);    leveldb_readoptions_set_snapshot(roptions, snap);    CheckGet(db, roptions, "foo", "hello");    leveldb_readoptions_set_snapshot(roptions, NULL);    CheckGet(db, roptions, "foo", NULL);    leveldb_release_snapshot(db, snap);  }  StartPhase("repair");  {    leveldb_close(db);    leveldb_options_set_create_if_missing(options, 0);    leveldb_options_set_error_if_exists(options, 0);    leveldb_repair_db(options, dbname, &err);    CheckNoError(err);    db = leveldb_open(options, dbname, &err);    CheckNoError(err);    CheckGet(db, roptions, "foo", NULL);    CheckGet(db, roptions, "bar", NULL);    CheckGet(db, roptions, "box", "c");    leveldb_options_set_create_if_missing(options, 1);    leveldb_options_set_error_if_exists(options, 1);  }  StartPhase("filter");  for (run = 0; run < 2; run++) {    // First run uses custom filter, second run uses bloom filter    CheckNoError(err);    leveldb_filterpolicy_t* policy;    if (run == 0) {      policy = leveldb_filterpolicy_create(          NULL, FilterDestroy, FilterCreate, FilterKeyMatch, FilterName);    } else {      policy = leveldb_filterpolicy_create_bloom(10);    }    // Create new database    leveldb_close(db);    leveldb_destroy_db(options, dbname, &err);    leveldb_options_set_filter_policy(options, policy);    db = leveldb_open(options, dbname, &err);    CheckNoError(err);    leveldb_put(db, woptions, "foo", 3, "foovalue", 8, &err);    CheckNoError(err);    leveldb_put(db, woptions, "bar", 3, "barvalue", 8, &err);    CheckNoError(err);    leveldb_compact_range(db, NULL, 0, NULL, 0);    fake_filter_result = 1;    CheckGet(db, roptions, "foo", "foovalue");    CheckGet(db, roptions, "bar", "barvalue");    if (phase == 0) {      // Must not find value when custom filter returns false      fake_filter_result = 0;      CheckGet(db, roptions, "foo", NULL);      CheckGet(db, roptions, "bar", NULL);      fake_filter_result = 1;      CheckGet(db, roptions, "foo", "foovalue");      CheckGet(db, roptions, "bar", "barvalue");    }    leveldb_options_set_filter_policy(options, NULL);    leveldb_filterpolicy_destroy(policy);  }  StartPhase("cleanup");  leveldb_close(db);  leveldb_options_destroy(options);  leveldb_readoptions_destroy(roptions);  leveldb_writeoptions_destroy(woptions);  leveldb_free(dbname);  leveldb_cache_destroy(cache);  leveldb_comparator_destroy(cmp);  leveldb_env_destroy(env);  fprintf(stderr, "PASS\n");  return 0;}