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