1 #include "iwkv.h"
2 #include "iwlog.h"
3 #include "iwutils.h"
4 #include "iwcfg.h"
5 #include "iwkv_tests.h"
6
7 #define KBUFSZ 128
8 #define VBUFSZ 128
9 char kbuf[KBUFSZ];
10 char vbuf[VBUFSZ];
11
12 extern int8_t iwkv_next_level;
13
logstage(FILE * f,const char * name,IWDB db)14 static int logstage(FILE *f, const char *name, IWDB db) {
15 int rci = fprintf(f, "\n#### Stage: %s\n", name);
16 iwkvd_db(f, db, IWKVD_PRINT_NO_LEVEVELS | IWKVD_PRINT_VALS, 0);
17 fflush(f);
18 return rci < 0 ? rci : 0;
19 }
20
logstage2(FILE * f,const char * name,IWDB db)21 static int logstage2(FILE *f, const char *name, IWDB db) {
22 int rci = fprintf(f, "\n#### Stage: %s\n", name);
23 iwkvd_db(f, db, IWKVD_PRINT_NO_LEVEVELS | IWKVD_PRINT_VALS, 0);
24 fflush(f);
25 return rci < 0 ? rci : 0;
26 }
27
init_suite()28 int init_suite() {
29 iwrc rc = iwkv_init();
30 return rc;
31 }
32
clean_suite()33 int clean_suite() {
34 return 0;
35 }
36
37
38 // Test5 staff
39 struct Test5DUP1 {
40 bool _mv;
41 bool _1v;
42 bool _10v;
43 };
44
_test5dup5visitor(uint64_t dv,int64_t idx,void * op)45 static int64_t _test5dup5visitor(uint64_t dv, int64_t idx, void *op) {
46 CU_ASSERT_PTR_NOT_NULL_FATAL(op);
47 struct Test5DUP1 *s = op;
48 switch (dv) {
49 case -1ULL:
50 s->_mv = true;
51 break;
52 case 1ULL:
53 s->_1v = true;
54 break;
55 case 10ULL:
56 s->_10v = true;
57 break;
58 default:
59 CU_FAIL("Invalid dup value");
60 break;
61 }
62 return 1;
63 }
64
65 // Test Slides
iwkv_test3_impl(int fmt_version)66 static void iwkv_test3_impl(int fmt_version) {
67 FILE *f = fmt_version > 1 ? fopen("iwkv_test1_3_v2.log", "w+") : fopen("iwkv_test1_3.log", "w+");
68 CU_ASSERT_PTR_NOT_NULL(f);
69
70 iwrc rc;
71 IWKV_val key = {0};
72 IWKV_val val = {0};
73 IWKV iwkv;
74 IWDB db1;
75 IWKV_OPTS opts = {
76 .path = "iwkv_test1_3.db",
77 .oflags = IWKV_TRUNC,
78 .fmt_version = fmt_version
79 };
80
81 rc = iwkv_open(&opts, &iwkv);
82 CU_ASSERT_EQUAL_FATAL(rc, 0);
83 rc = iwkv_db(iwkv, 1, 0, &db1);
84 CU_ASSERT_EQUAL_FATAL(rc, 0);
85
86 for (int i = -23, c = 0; i <= 23; ++i) {
87 for (int j = 0; j < 63; ++j, ++c) {
88 iwkv_next_level = i < 0 ? -i : i;
89 snprintf(kbuf, KBUFSZ, "%05dkkk", c);
90 snprintf(vbuf, VBUFSZ, "%05dval", c);
91 key.data = kbuf;
92 key.size = strlen(key.data);
93 val.data = vbuf;
94 val.size = strlen(val.data);
95 rc = iwkv_put(db1, &key, &val, 0);
96 CU_ASSERT_EQUAL_FATAL(rc, 0);
97 }
98 }
99 // middle
100 // 23 \ | / 23
101 // \ | /
102 // 0 \__|__/ 0
103 iwkv_next_level = 23;
104 // put: 01858aaa in order to split middle zero sblk
105 snprintf(kbuf, KBUFSZ, "%05daaa", 1858);
106 snprintf(vbuf, VBUFSZ, "%05dval", 1858);
107 rc = iwkv_put(db1, &key, &val, 0);
108 CU_ASSERT_EQUAL_FATAL(rc, 0);
109
110 logstage2(f, "iwkv_test3", db1);
111
112 rc = iwkv_close(&iwkv);
113 CU_ASSERT_EQUAL_FATAL(rc, 0);
114 // Compare logs with referenced
115 #ifndef _WIN32
116 FILE *r = fmt_version > 1 ? fopen("iwkv_test1_3_v2.ref", "r+") : fopen("iwkv_test1_3.ref", "r+");
117 #else
118 FILE *r = fmt_version > 1 ? fopen("iwkv_test1_3w_v2.ref", "r+") : fopen("iwkv_test1_3w.ref", "r+");
119 #endif
120 CU_ASSERT_PTR_NOT_NULL(r);
121 int rci = cmp_files(r, f);
122 CU_ASSERT_EQUAL_FATAL(rci, 0);
123 fclose(f);
124 fclose(r);
125 }
126
iwkv_test3_v1()127 static void iwkv_test3_v1() {
128 iwkv_test3_impl(1);
129 }
130
iwkv_test3_v2()131 static void iwkv_test3_v2() {
132 iwkv_test3_impl(2);
133 }
134
iwkv_test2_impl(int fmt_version)135 static void iwkv_test2_impl(int fmt_version) {
136 FILE *f = fmt_version > 1 ? fopen("iwkv_test1_2_v2.log", "w+") : fopen("iwkv_test1_2.log", "w+");
137 CU_ASSERT_PTR_NOT_NULL(f);
138
139 iwrc rc;
140 IWKV_val key = {0};
141 IWKV_val val = {0};
142 IWKV iwkv;
143 IWDB db1;
144 IWKV_OPTS opts = {
145 .path = "iwkv_test1_2.db",
146 .oflags = IWKV_TRUNC,
147 .fmt_version = fmt_version
148 };
149
150 rc = iwkv_open(&opts, &iwkv);
151 CU_ASSERT_EQUAL_FATAL(rc, 0);
152 rc = iwkv_db(iwkv, 1, 0, &db1);
153 CU_ASSERT_EQUAL_FATAL(rc, 0);
154
155 for (int i = 252 * 2; i >= 0; --i) { // 189
156 snprintf(kbuf, KBUFSZ, "%03dkkk", i);
157 snprintf(vbuf, VBUFSZ, "%03dval", i);
158 key.data = kbuf;
159 key.size = strlen(key.data);
160 val.data = vbuf;
161 val.size = strlen(val.data);
162 rc = iwkv_put(db1, &key, &val, 0);
163 CU_ASSERT_EQUAL_FATAL(rc, 0);
164 }
165 logstage(f, "desc sorted keys inserted", db1);
166
167 for (int i = 0; i <= 252 * 2; ++i) {
168 int cret;
169 snprintf(kbuf, KBUFSZ, "%03dkkk", i);
170 snprintf(vbuf, VBUFSZ, "%03dval", i);
171 int vsize = strlen(vbuf);
172 key.data = kbuf;
173 key.size = strlen(key.data);
174 rc = iwkv_get(db1, &key, &val);
175 CU_ASSERT_EQUAL_FATAL(rc, 0);
176 IW_CMP(cret, vbuf, vsize, val.data, val.size);
177 CU_ASSERT_EQUAL_FATAL(cret, 0);
178 iwkv_kv_dispose(0, &val);
179 }
180
181 // snprintf(kbuf, KBUFSZ, "%03dkkk", 64);
182 // key.data = kbuf;
183 // key.size = strlen(key.data);
184 // rc = iwkv_del(db1, &key);
185 // CU_ASSERT_EQUAL_FATAL(rc, 0);
186 // logstage(f, "removed 064kkk", db1);
187 //
188 //
189 // snprintf(kbuf, KBUFSZ, "%03dkkk", 126);
190 // key.data = kbuf;
191 // key.size = strlen(key.data);
192 // rc = iwkv_del(db1, &key);
193 // CU_ASSERT_EQUAL_FATAL(rc, 0);
194 // logstage(f, "removed 126kkk", db1);
195 //
196 //
197 // // Now delete more than half of block records
198 // // 126
199 // for (int i = 64; i <= 99; ++i) {
200 // snprintf(kbuf, KBUFSZ, "%03dkkk", i);
201 // key.data = kbuf;
202 // key.size = strlen(key.data);
203 // rc = iwkv_del(db1, &key);
204 // if (i == 64) {
205 // CU_ASSERT_EQUAL(rc, IWKV_ERROR_NOTFOUND);
206 // rc = 0;
207 // continue;
208 // }
209 // CU_ASSERT_EQUAL_FATAL(rc, 0);
210 // }
211 // logstage(f, "removed 065kkk - 099kkk", db1); // 125
212 //
213 // for (int i = 100; i <= 125; ++i) {
214 // snprintf(kbuf, KBUFSZ, "%03dkkk", i);
215 // key.data = kbuf;
216 // key.size = strlen(key.data);
217 // rc = iwkv_del(db1, &key);
218 // CU_ASSERT_EQUAL_FATAL(rc, 0);
219 // }
220 // logstage(f, "removed all keys in SBLK[54]", db1); // 125
221
222 rc = iwkv_db_destroy(&db1); // Destroy DB and remove all db blocks
223 CU_ASSERT_EQUAL_FATAL(rc, 0);
224
225 rc = iwkv_close(&iwkv);
226 CU_ASSERT_EQUAL_FATAL(rc, 0);
227
228 // Reopen DB then check db1
229 rc = iwkv_open(&opts, &iwkv);
230 CU_ASSERT_EQUAL_FATAL(rc, 0);
231
232 rc = iwkv_db(iwkv, 1, 0, &db1);
233 CU_ASSERT_EQUAL_FATAL(rc, 0);
234 logstage(f, "db1 destroyed", db1);
235 rc = iwkv_close(&iwkv);
236 CU_ASSERT_EQUAL_FATAL(rc, 0);
237
238 // Compare logs with referenced
239 #ifndef _WIN32
240 FILE *r = fmt_version > 1 ? fopen("iwkv_test1_2_v2.ref", "r+") : fopen("iwkv_test1_2.ref", "r+");
241 #else
242 FILE *r = fmt_version > 1 ? fopen("iwkv_test1_2w_v2.ref", "r+") : fopen("iwkv_test1_2w.ref", "r+");
243 #endif
244 CU_ASSERT_PTR_NOT_NULL(r);
245 int rci = cmp_files(r, f);
246 CU_ASSERT_EQUAL_FATAL(rci, 0);
247 fclose(f);
248 fclose(r);
249 }
250
iwkv_test2_v1()251 static void iwkv_test2_v1() {
252 iwkv_test2_impl(1);
253 }
254
iwkv_test2_v2()255 static void iwkv_test2_v2() {
256 iwkv_test2_impl(2);
257 }
258
iwkv_test1_impl(int fmt_version)259 static void iwkv_test1_impl(int fmt_version) {
260 FILE *f = fmt_version > 1 ? fopen("iwkv_test1_1_v2.log", "w+") : fopen("iwkv_test1_1.log", "w+");
261 CU_ASSERT_PTR_NOT_NULL(f);
262 char buf[128];
263 size_t vsize;
264
265 IWKV_OPTS opts = {
266 .path = "iwkv_test1.db",
267 .oflags = IWKV_TRUNC,
268 .fmt_version = fmt_version
269 };
270 // Test open/close
271 IWKV iwkv;
272 IWDB db1, db2, db3;
273 iwrc rc;
274 IWKV_val key = {.data = "foo"};
275 key.size = strlen(key.data);
276 IWKV_val val = {.data = "bar"};
277 val.size = strlen(val.data);
278
279 rc = iwkv_open(&opts, &iwkv);
280 CU_ASSERT_EQUAL_FATAL(rc, 0);
281 rc = iwkv_close(&iwkv);
282 CU_ASSERT_EQUAL_FATAL(rc, 0);
283
284 // Test open/close existing db
285 opts.oflags = 0;
286 rc = iwkv_open(&opts, &iwkv);
287 CU_ASSERT_EQUAL_FATAL(rc, 0);
288 rc = iwkv_close(&iwkv);
289 CU_ASSERT_EQUAL_FATAL(rc, 0);
290
291 // Test create/destroy db
292 rc = iwkv_open(&opts, &iwkv);
293 CU_ASSERT_EQUAL_FATAL(rc, 0);
294 rc = iwkv_db(iwkv, 1, 0, &db1);
295 CU_ASSERT_EQUAL_FATAL(rc, 0);
296 rc = iwkv_db(iwkv, 2, 0, &db2); // destroyed
297 CU_ASSERT_EQUAL_FATAL(rc, 0);
298 rc = iwkv_db(iwkv, 3, 0, &db3);
299 CU_ASSERT_EQUAL_FATAL(rc, 0);
300 rc = iwkv_db_destroy(&db2); // destroyed
301 CU_ASSERT_EQUAL_FATAL(rc, 0);
302 rc = iwkv_close(&iwkv);
303 CU_ASSERT_EQUAL_FATAL(rc, 0);
304
305 // Test one in read-only mode
306 opts.oflags = IWKV_RDONLY;
307 opts.path = "not-existing.db";
308 rc = iwkv_open(&opts, &iwkv);
309 CU_ASSERT_TRUE_FATAL(rc);
310 iwrc_strip_errno(&rc);
311 #ifdef _WIN32
312 iwrc_strip_werror(&rc);
313 #endif
314 CU_ASSERT_EQUAL(rc, IW_ERROR_NOT_EXISTS);
315
316 // Open in read-only mode and acquire not existing db
317 opts.path = "iwkv_test1.db";
318 rc = iwkv_open(&opts, &iwkv);
319 CU_ASSERT_EQUAL_FATAL(rc, 0);
320
321 rc = iwkv_db(iwkv, 2, 0, &db2);
322 CU_ASSERT_EQUAL(rc, IW_ERROR_READONLY);
323
324 rc = iwkv_db(iwkv, 1, 0, &db1);
325 CU_ASSERT_EQUAL_FATAL(rc, 0);
326
327 rc = iwkv_db(iwkv, 3, 0, &db3);
328 CU_ASSERT_EQUAL_FATAL(rc, 0);
329
330 logstage(f, "empty db", db1);
331
332 rc = iwkv_close(&iwkv);
333 CU_ASSERT_EQUAL_FATAL(rc, 0);
334
335 // Open in write mode, then put a simple kv
336 opts.oflags = 0;
337 rc = iwkv_open(&opts, &iwkv);
338 CU_ASSERT_EQUAL_FATAL(rc, 0);
339 rc = iwkv_db(iwkv, 1, 0, &db1);
340 CU_ASSERT_EQUAL_FATAL(rc, 0);
341 // iwkv_next_level = 3;
342 rc = iwkv_put(db1, &key, &val, 0);
343 CU_ASSERT_EQUAL_FATAL(rc, 0);
344
345 logstage(f, "put foo:bar", db1);
346
347 rc = iwkv_close(&iwkv);
348 CU_ASSERT_EQUAL_FATAL(rc, 0);
349
350 // Open db and get out single record
351 rc = iwkv_open(&opts, &iwkv);
352 CU_ASSERT_EQUAL_FATAL(rc, 0);
353 rc = iwkv_db(iwkv, 1, 0, &db1);
354 CU_ASSERT_EQUAL_FATAL(rc, 0);
355 val.size = 0;
356 val.data = 0;
357
358 rc = iwkv_get(db1, &key, &val);
359 CU_ASSERT_EQUAL_FATAL(rc, 0);
360 CU_ASSERT_NSTRING_EQUAL(key.data, "foo", key.size);
361 CU_ASSERT_NSTRING_EQUAL(val.data, "bar", val.size);
362 iwkv_kv_dispose(0, &val);
363
364 rc = iwkv_get_copy(db1, &key, buf, sizeof(buf), &vsize);
365 CU_ASSERT_EQUAL_FATAL(rc, 0);
366 CU_ASSERT_EQUAL(3, vsize);
367 CU_ASSERT_NSTRING_EQUAL(buf, "bar", vsize);
368
369 rc = iwkv_get_copy(db1, &key, buf, 1, &vsize);
370 CU_ASSERT_EQUAL_FATAL(rc, 0);
371 CU_ASSERT_EQUAL(3, vsize);
372 CU_ASSERT_NSTRING_EQUAL(buf, "b", 1);
373
374 // put foo->bazzz
375 key.data = "foo";
376 key.size = strlen(key.data);
377 val.data = "bazzz";
378 val.size = strlen(val.data);
379 rc = iwkv_put(db1, &key, &val, 0);
380 CU_ASSERT_EQUAL_FATAL(rc, 0);
381
382 // put foo->zzz with IWKV_NO_OVERWRITE
383 val.data = "zzz";
384 val.size = strlen(val.data);
385 rc = iwkv_put(db1, &key, &val, IWKV_NO_OVERWRITE);
386
387 CU_ASSERT_EQUAL_FATAL(rc, IWKV_ERROR_KEY_EXISTS);
388 rc = iwkv_get(db1, &key, &val);
389 CU_ASSERT_NSTRING_EQUAL(key.data, "foo", key.size);
390 CU_ASSERT_NSTRING_EQUAL(val.data, "bazzz", val.size);
391 iwkv_kv_dispose(0, &val);
392
393 logstage(f, "put foo:bazz", db1);
394
395 // put foo->''
396 val.data = "";
397 val.size = strlen(val.data);
398 rc = iwkv_put(db1, &key, &val, 0);
399 CU_ASSERT_EQUAL_FATAL(rc, 0);
400 rc = iwkv_get(db1, &key, &val);
401 CU_ASSERT_NSTRING_EQUAL(key.data, "foo", key.size);
402 CU_ASSERT_NSTRING_EQUAL(val.data, "", val.size);
403 iwkv_kv_dispose(0, &val);
404
405 logstage(f, "put foo:", db1);
406
407 val.data = "bar";
408 val.size = strlen(val.data);
409 rc = iwkv_put(db1, &key, &val, 0);
410 CU_ASSERT_EQUAL_FATAL(rc, 0);
411 rc = iwkv_get(db1, &key, &val);
412 CU_ASSERT_NSTRING_EQUAL(key.data, "foo", key.size);
413 CU_ASSERT_NSTRING_EQUAL(val.data, "bar", val.size);
414 iwkv_kv_dispose(0, &val);
415
416 logstage(f, "put foo:bar", db1);
417
418 // remove key/value
419 rc = iwkv_del(db1, &key, 0);
420 CU_ASSERT_EQUAL_FATAL(rc, 0);
421 rc = iwkv_get(db1, &key, &val);
422 CU_ASSERT_EQUAL_FATAL(rc, IWKV_ERROR_NOTFOUND);
423
424 logstage(f, "remove foo:bar", db1);
425
426 rc = iwkv_close(&iwkv);
427 CU_ASSERT_EQUAL_FATAL(rc, 0);
428
429 rc = iwkv_open(&opts, &iwkv);
430 CU_ASSERT_EQUAL_FATAL(rc, 0);
431 rc = iwkv_db(iwkv, 1, 0, &db1);
432 CU_ASSERT_EQUAL_FATAL(rc, 0);
433 rc = iwkv_get(db1, &key, &val);
434 CU_ASSERT_EQUAL_FATAL(rc, IWKV_ERROR_NOTFOUND);
435
436 // iwkv_next_level = 0;
437
438 for (int i = 0; i < 127 * 2; i += 2) {
439 snprintf(kbuf, KBUFSZ, "%03dkkk", i);
440 snprintf(vbuf, VBUFSZ, "%03dval", i);
441 key.data = kbuf;
442 key.size = strlen(key.data);
443 val.data = vbuf;
444 val.size = strlen(val.data);
445 rc = iwkv_put(db1, &key, &val, 0);
446 CU_ASSERT_EQUAL_FATAL(rc, 0);
447 }
448
449 logstage(f, "fill up first block", db1);
450
451 // iwkv_next_level = 0;
452 for (int i = 0; i < 127 * 2; i += 2) {
453 snprintf(kbuf, KBUFSZ, "%03dkkk", i);
454 snprintf(vbuf, VBUFSZ, "%03dval", i);
455 key.data = kbuf;
456 key.size = strlen(key.data);
457 rc = iwkv_get(db1, &key, &val);
458 CU_ASSERT_EQUAL_FATAL(rc, 0);
459 CU_ASSERT_EQUAL_FATAL(strncmp(val.data, vbuf, val.size), 0);
460 iwkv_kv_dispose(0, &val);
461 }
462
463 for (int i = 1; i < 127 * 2; i += 2) {
464 snprintf(kbuf, KBUFSZ, "%03dkkk", i);
465 snprintf(vbuf, VBUFSZ, "%03dval", i);
466 key.data = kbuf;
467 key.size = strlen(key.data);
468 val.data = vbuf;
469 val.size = strlen(val.data);
470 //logstage(stderr, "!!!!!!", db1);
471 rc = iwkv_put(db1, &key, &val, 0);
472 CU_ASSERT_EQUAL_FATAL(rc, 0);
473 //logstage(stderr, "??????", db1);
474 }
475
476 logstage(f, "fill up second block", db1);
477
478 // Check basic cursor operations
479 IWKV_cursor cur1;
480
481 rc = iwkv_cursor_open(db1, &cur1, IWKV_CURSOR_BEFORE_FIRST, 0);
482 CU_ASSERT_EQUAL_FATAL(rc, 0);
483 rc = iwkv_cursor_to(cur1, IWKV_CURSOR_PREV);
484 CU_ASSERT_EQUAL(rc, IWKV_ERROR_NOTFOUND);
485 rc = iwkv_cursor_close(&cur1);
486 CU_ASSERT_EQUAL_FATAL(rc, 0);
487
488 rc = iwkv_cursor_open(db1, &cur1, IWKV_CURSOR_AFTER_LAST, 0);
489 CU_ASSERT_EQUAL_FATAL(rc, 0);
490 rc = iwkv_cursor_get(cur1, &key, &val);
491 CU_ASSERT_EQUAL(rc, IWKV_ERROR_NOTFOUND);
492 rc = iwkv_cursor_to(cur1, IWKV_CURSOR_NEXT);
493 CU_ASSERT_EQUAL(rc, IWKV_ERROR_NOTFOUND);
494 rc = iwkv_cursor_close(&cur1);
495 CU_ASSERT_EQUAL_FATAL(rc, 0);
496
497 rc = iwkv_cursor_open(db1, &cur1, IWKV_CURSOR_AFTER_LAST, 0);
498 CU_ASSERT_EQUAL_FATAL(rc, 0);
499
500 rc = iwkv_cursor_to(cur1, IWKV_CURSOR_PREV);
501 CU_ASSERT_EQUAL_FATAL(rc, 0);
502
503 int i = 0;
504 do {
505 IWKV_val key;
506 IWKV_val val;
507 iwrc rc2 = iwkv_cursor_get(cur1, &key, &val);
508 CU_ASSERT_EQUAL_FATAL(rc2, 0);
509 snprintf(kbuf, KBUFSZ, "%03dkkk", i);
510 snprintf(vbuf, VBUFSZ, "%03dval", i);
511 CU_ASSERT_EQUAL(strncmp(key.data, kbuf, key.size), 0);
512 CU_ASSERT_EQUAL(strncmp(val.data, vbuf, val.size), 0);
513 iwkv_kv_dispose(&key, &val);
514 if (i == 2) {
515 rc2 = iwkv_cursor_to(cur1, IWKV_CURSOR_PREV);
516 CU_ASSERT_EQUAL_FATAL(rc2, 0);
517 rc2 = iwkv_cursor_get(cur1, &key, &val);
518 CU_ASSERT_EQUAL_FATAL(rc2, 0);
519 snprintf(kbuf, KBUFSZ, "%03dkkk", i + 1);
520 snprintf(vbuf, VBUFSZ, "%03dval", i + 1);
521 CU_ASSERT_EQUAL(strncmp(key.data, kbuf, key.size), 0);
522 CU_ASSERT_EQUAL(strncmp(val.data, vbuf, val.size), 0);
523 rc2 = iwkv_cursor_to(cur1, IWKV_CURSOR_NEXT);
524 CU_ASSERT_EQUAL_FATAL(rc2, 0);
525 iwkv_kv_dispose(&key, &val);
526 }
527 ++i;
528 } while (!(rc = iwkv_cursor_to(cur1, IWKV_CURSOR_PREV)));
529 CU_ASSERT_EQUAL(rc, IWKV_ERROR_NOTFOUND);
530 rc = iwkv_cursor_close(&cur1);
531 CU_ASSERT_EQUAL_FATAL(rc, 0);
532
533 --i;
534 rc = iwkv_cursor_open(db1, &cur1, IWKV_CURSOR_BEFORE_FIRST, 0);
535 while (!(rc = iwkv_cursor_to(cur1, IWKV_CURSOR_NEXT))) {
536 IWKV_val key;
537 IWKV_val val;
538 iwrc rc2 = iwkv_cursor_get(cur1, &key, &val);
539 CU_ASSERT_EQUAL_FATAL(rc2, 0);
540 snprintf(kbuf, KBUFSZ, "%03dkkk", i);
541 snprintf(vbuf, VBUFSZ, "%03dval", i);
542 --i;
543 CU_ASSERT_EQUAL(strncmp(key.data, kbuf, key.size), 0);
544 CU_ASSERT_EQUAL(strncmp(val.data, vbuf, val.size), 0);
545 iwkv_kv_dispose(&key, &val);
546 }
547 CU_ASSERT_EQUAL(rc, IWKV_ERROR_NOTFOUND);
548 rc = iwkv_cursor_close(&cur1);
549 CU_ASSERT_EQUAL_FATAL(rc, 0);
550
551 // Set cursor to key
552 do {
553 IWKV_val key;
554 IWKV_val val;
555 snprintf(kbuf, KBUFSZ, "%03dkkk", 30);
556 snprintf(vbuf, VBUFSZ, "%03dval", 30);
557 key.data = kbuf;
558 key.size = strlen(kbuf);
559 rc = iwkv_cursor_open(db1, &cur1, IWKV_CURSOR_EQ, &key);
560 CU_ASSERT_EQUAL_FATAL(rc, 0);
561 iwrc rc2 = iwkv_cursor_get(cur1, &key, &val);
562 CU_ASSERT_EQUAL_FATAL(rc2, 0);
563 CU_ASSERT_EQUAL(strncmp(key.data, kbuf, key.size), 0);
564 CU_ASSERT_EQUAL(strncmp(val.data, vbuf, val.size), 0);
565 iwkv_kv_dispose(&key, &val);
566
567 // Move to GE 000
568 snprintf(kbuf, KBUFSZ, "%03d", 0);
569 snprintf(vbuf, VBUFSZ, "%03dval", 0);
570 key.data = kbuf;
571 key.size = strlen(kbuf);
572 rc2 = iwkv_cursor_to_key(cur1, IWKV_CURSOR_GE, &key);
573 if (rc2) {
574 iwlog_ecode_error3(rc2);
575 }
576 CU_ASSERT_EQUAL_FATAL(rc2, 0);
577 rc2 = iwkv_cursor_get(cur1, &key, &val);
578 CU_ASSERT_EQUAL_FATAL(rc2, 0);
579 snprintf(kbuf, KBUFSZ, "%03dkkk", 0);
580 snprintf(vbuf, VBUFSZ, "%03dval", 0);
581 CU_ASSERT_EQUAL(strncmp(key.data, kbuf, key.size), 0);
582 CU_ASSERT_EQUAL(strncmp(val.data, vbuf, val.size), 0);
583 iwkv_kv_dispose(&key, &val);
584
585 // Move to EQ 000
586 snprintf(kbuf, KBUFSZ, "%03d", 0);
587 snprintf(vbuf, VBUFSZ, "%03dval", 0);
588 key.data = kbuf;
589 key.size = strlen(kbuf);
590 rc2 = iwkv_cursor_to_key(cur1, IWKV_CURSOR_EQ, &key);
591 CU_ASSERT_EQUAL(rc2, IWKV_ERROR_NOTFOUND);
592
593 rc = iwkv_cursor_close(&cur1);
594 CU_ASSERT_EQUAL_FATAL(rc, 0);
595 } while (0);
596
597 rc = iwkv_close(&iwkv);
598 CU_ASSERT_EQUAL_FATAL(rc, 0);
599
600 rc = iwkv_open(&opts, &iwkv);
601 CU_ASSERT_EQUAL_FATAL(rc, 0);
602 rc = iwkv_db(iwkv, 1, 0, &db1);
603 CU_ASSERT_EQUAL_FATAL(rc, 0);
604
605 logstage(f, "state after reopen", db1);
606
607 // Put a big key
608 snprintf(kbuf, KBUFSZ, "abracadabrabracadabrabracadabrabracadabrabracadabrabracadabrabracadabr1");
609 key.size = strlen(kbuf);
610 snprintf(vbuf, VBUFSZ, "vabracadabrabracadabrabracadabrabracadabrabracadabrabracadabrabracadabr");
611 val.size = strlen(vbuf);
612 rc = iwkv_db(iwkv, 1, 0, &db1);
613 CU_ASSERT_EQUAL_FATAL(rc, 0);
614 rc = iwkv_put(db1, &key, &val, 0);
615 CU_ASSERT_EQUAL_FATAL(rc, 0);
616 rc = iwkv_get(db1, &key, &val);
617 CU_ASSERT_EQUAL_FATAL(rc, 0);
618 CU_ASSERT_EQUAL_FATAL(strncmp(val.data, vbuf, val.size), 0);
619 iwkv_kv_dispose(0, &val);
620
621 logstage(f, "a big key", db1);
622
623 // 061kkk:061val
624 // Set value with cursor
625 snprintf(kbuf, KBUFSZ, "%03dkkk", 61);
626 snprintf(vbuf, VBUFSZ, "%03dval2", 61);
627 key.data = kbuf;
628 key.size = strlen(kbuf);
629 val.data = vbuf;
630 val.size = strlen(vbuf);
631
632 // Cursor set
633 rc = iwkv_cursor_open(db1, &cur1, IWKV_CURSOR_EQ, &key);
634 CU_ASSERT_EQUAL_FATAL(rc, 0);
635 rc = iwkv_cursor_set(cur1, &val, 0);
636 CU_ASSERT_EQUAL_FATAL(rc, 0);
637 key.data = 0;
638 val.data = 0;
639 rc = iwkv_cursor_get(cur1, &key, &val);
640 CU_ASSERT_EQUAL_FATAL(rc, 0);
641 CU_ASSERT_EQUAL(strncmp(key.data, kbuf, key.size), 0);
642 CU_ASSERT_EQUAL(strncmp(val.data, vbuf, val.size), 0);
643 iwkv_kv_dispose(&key, &val);
644 rc = iwkv_cursor_close(&cur1);
645 CU_ASSERT_EQUAL_FATAL(rc, 0);
646
647 // Set in write mode
648 snprintf(kbuf, KBUFSZ, "%03dkkk", 61);
649 snprintf(vbuf, VBUFSZ, "%03dval3", 61);
650 key.data = kbuf;
651 key.size = strlen(kbuf);
652 val.data = vbuf;
653 val.size = strlen(vbuf);
654 rc = iwkv_cursor_open(db1, &cur1, IWKV_CURSOR_EQ, &key);
655 CU_ASSERT_EQUAL_FATAL(rc, 0);
656 rc = iwkv_cursor_set(cur1, &val, 0);
657 CU_ASSERT_EQUAL_FATAL(rc, 0);
658 key.data = 0;
659 val.data = 0;
660 rc = iwkv_cursor_get(cur1, &key, &val);
661 CU_ASSERT_EQUAL_FATAL(rc, 0);
662 CU_ASSERT_EQUAL(strncmp(key.data, kbuf, key.size), 0);
663 CU_ASSERT_EQUAL(strncmp(val.data, vbuf, val.size), 0);
664 iwkv_kv_dispose(&key, &val);
665 rc = iwkv_cursor_close(&cur1);
666 CU_ASSERT_EQUAL_FATAL(rc, 0);
667
668 rc = iwkv_close(&iwkv);
669 CU_ASSERT_EQUAL_FATAL(rc, 0);
670
671 // Compare logs with referenced
672 #ifndef _WIN32
673 FILE *r = fmt_version > 1 ? fopen("iwkv_test1_1_v2.ref", "r+") : fopen("iwkv_test1_1.ref", "r+");
674 #else
675 FILE *r = fmt_version > 1 ? fopen("iwkv_test1_1w_v2.ref", "r+") : fopen("iwkv_test1_1w.ref", "r+");
676 #endif
677 CU_ASSERT_PTR_NOT_NULL_FATAL(r);
678 int rci = cmp_files(r, f);
679 CU_ASSERT_EQUAL_FATAL(rci, 0);
680 fclose(r);
681 fclose(f);
682 }
683
iwkv_test1_v1()684 static void iwkv_test1_v1() {
685 iwkv_test1_impl(1);
686 }
687
iwkv_test1_v2()688 static void iwkv_test1_v2() {
689 iwkv_test1_impl(2);
690 }
691
iwkv_test8_impl(int fmt_version)692 static void iwkv_test8_impl(int fmt_version) {
693 IWKV_OPTS opts = {
694 .path = "iwkv_test1_8.db",
695 .oflags = IWKV_TRUNC,
696 .fmt_version = fmt_version
697 };
698 IWKV iwkv;
699 IWDB db1;
700 IWKV_cursor cur;
701 IWKV_val key;
702 IWKV_val val = {
703 .data = "foo",
704 .size = sizeof("foo") - 1
705 };
706 IWKV_val oval;
707 size_t ksz;
708 uint64_t llv = 1;
709 uint64_t llv2;
710
711 iwrc rc = iwkv_open(&opts, &iwkv);
712 CU_ASSERT_EQUAL_FATAL(rc, 0);
713
714 rc = iwkv_db(iwkv, 1, IWDB_VNUM64_KEYS, &db1);
715 CU_ASSERT_EQUAL_FATAL(rc, 0);
716
717 key.data = &llv;
718 key.size = sizeof(llv);
719
720 rc = iwkv_put(db1, &key, &val, 0);
721 CU_ASSERT_EQUAL_FATAL(rc, 0);
722
723 rc = iwkv_get(db1, &key, &oval);
724 CU_ASSERT_EQUAL_FATAL(rc, 0);
725 iwkv_val_dispose(&oval);
726
727 llv = 0xffffffffffffffe;
728 key.data = &llv;
729
730 rc = iwkv_put(db1, &key, &val, 0);
731 CU_ASSERT_EQUAL_FATAL(rc, 0);
732
733 rc = iwkv_get(db1, &key, &oval);
734 CU_ASSERT_EQUAL_FATAL(rc, 0);
735 iwkv_val_dispose(&oval);
736
737 rc = iwkv_get_copy(db1, &key, &llv2, sizeof(llv2), &ksz);
738 CU_ASSERT_EQUAL_FATAL(rc, 0);
739
740 rc = iwkv_cursor_open(db1, &cur, IWKV_CURSOR_EQ, &key);
741 CU_ASSERT_EQUAL_FATAL(rc, 0);
742
743 llv = 0xffffffffffffffffULL;
744 rc = iwkv_put(db1, &key, &val, 0);
745 CU_ASSERT_EQUAL(rc, IW_ERROR_OVERFLOW);
746
747
748 llv = 0;
749 int64_t compound;
750 rc = iwkv_cursor_copy_key(cur, &llv, sizeof(llv), &ksz, &compound);
751 CU_ASSERT_EQUAL_FATAL(rc, 0);
752 CU_ASSERT_EQUAL(llv, 0xffffffffffffffe);
753
754 llv = 0;
755 rc = iwkv_cursor_get(cur, &oval, 0);
756 CU_ASSERT_EQUAL_FATAL(rc, 0);
757 CU_ASSERT_EQUAL_FATAL(oval.size, sizeof(llv));
758 memcpy(&llv, oval.data, sizeof(llv));
759 CU_ASSERT_EQUAL(llv, 0xffffffffffffffe);
760 iwkv_val_dispose(&oval);
761
762 rc = iwkv_cursor_to(cur, IWKV_CURSOR_NEXT);
763 CU_ASSERT_EQUAL_FATAL(rc, 0);
764
765 llv = 0;
766 rc = iwkv_cursor_copy_key(cur, &llv, sizeof(llv), &ksz, &compound);
767 CU_ASSERT_EQUAL_FATAL(rc, 0);
768 CU_ASSERT_EQUAL(llv, 1);
769
770 iwkv_cursor_close(&cur);
771
772 rc = iwkv_close(&iwkv);
773 CU_ASSERT_EQUAL_FATAL(rc, 0);
774 }
775
iwkv_test8_v1()776 static void iwkv_test8_v1() {
777 iwkv_test1_impl(1);
778 }
779
iwkv_test8_v2()780 static void iwkv_test8_v2() {
781 iwkv_test1_impl(2);
782 }
783
iwkv_test7_impl(int fmt_version)784 static void iwkv_test7_impl(int fmt_version) {
785 IWKV_OPTS opts = {
786 .path = "iwkv_test1_7.db",
787 .oflags = IWKV_TRUNC,
788 .fmt_version = fmt_version
789 };
790 IWKV iwkv;
791 IWDB db1;
792 IWKV_val key, val;
793 int64_t llv;
794 key.data = "foo";
795 key.size = strlen(key.data);
796
797 iwrc rc = iwkv_open(&opts, &iwkv);
798 CU_ASSERT_EQUAL_FATAL(rc, 0);
799
800 rc = iwkv_db(iwkv, 1, 0, &db1);
801 CU_ASSERT_EQUAL_FATAL(rc, 0);
802
803 llv = 1;
804 val.data = &llv;
805 val.size = sizeof(llv);
806
807 rc = iwkv_put(db1, &key, &val, IWKV_VAL_INCREMENT);
808 CU_ASSERT_EQUAL_FATAL(rc, 0);
809
810 rc = iwkv_put(db1, &key, &val, IWKV_VAL_INCREMENT);
811 CU_ASSERT_EQUAL_FATAL(rc, 0);
812
813 rc = iwkv_put(db1, &key, &val, IWKV_VAL_INCREMENT);
814 CU_ASSERT_EQUAL_FATAL(rc, 0);
815
816 llv = 0;
817 val.data = 0;
818 val.size = 0;
819 rc = iwkv_get(db1, &key, &val);
820 CU_ASSERT_EQUAL_FATAL(rc, 0);
821 CU_ASSERT_EQUAL_FATAL(val.size, sizeof(llv));
822 memcpy(&llv, val.data, sizeof(llv));
823 llv = IW_ITOHLL(llv);
824 CU_ASSERT_EQUAL(llv, 3);
825 iwkv_val_dispose(&val);
826
827 rc = iwkv_close(&iwkv);
828 CU_ASSERT_EQUAL_FATAL(rc, 0);
829 }
830
iwkv_test7_v1()831 static void iwkv_test7_v1() {
832 iwkv_test7_impl(1) ;
833 }
834
iwkv_test7_v2()835 static void iwkv_test7_v2() {
836 iwkv_test7_impl(2) ;
837 }
838
iwkv_test6_impl(int fmt_version)839 static void iwkv_test6_impl(int fmt_version) {
840 IWKV_OPTS opts = {
841 .path = "iwkv_test1_6.db",
842 .oflags = IWKV_TRUNC,
843 .fmt_version = fmt_version
844 };
845 const int vbsiz = 1000 * 1000;
846 // Test open/close
847 char kbuf[100];
848 char *vbuf = malloc(vbsiz);
849 IWKV iwkv;
850 IWDB db1;
851 IWKV_val key, val;
852
853 iwrc rc = iwkv_open(&opts, &iwkv);
854 CU_ASSERT_EQUAL_FATAL(rc, 0);
855
856 rc = iwkv_db(iwkv, 1, 0, &db1);
857 CU_ASSERT_EQUAL_FATAL(rc, 0);
858 key.data = kbuf;
859 val.data = vbuf;
860 val.size = vbsiz;
861 for (int i = 0; i < 20; ++i) {
862 memset(vbuf, ' ' + i + 1, vbsiz);
863 snprintf(kbuf, sizeof(kbuf), "%016d", i);
864 key.size = strlen(kbuf);
865 rc = iwkv_put(db1, &key, &val, 0);
866 if (rc) {
867 iwlog_ecode_error3(rc);
868 }
869 CU_ASSERT_EQUAL_FATAL(rc, 0);
870 }
871 rc = iwkv_close(&iwkv);
872 CU_ASSERT_EQUAL_FATAL(rc, 0);
873 free(vbuf);
874 }
875
iwkv_test6_v1()876 static void iwkv_test6_v1() {
877 iwkv_test6_impl(1);
878 }
879
iwkv_test6_v2()880 static void iwkv_test6_v2() {
881 iwkv_test6_impl(2);
882 }
883
iwkv_test9(void)884 static void iwkv_test9(void) {
885 IWKV_OPTS opts = {
886 .path = "garbage.data",
887 };
888 // Test open/close
889 IWKV iwkv;
890 iwrc rc = iwkv_open(&opts, &iwkv);
891 CU_ASSERT_EQUAL(rc, IWFS_ERROR_INVALID_FILEMETA);
892 rc = iwkv_close(&iwkv);
893 CU_ASSERT_EQUAL(rc, IW_ERROR_INVALID_STATE);
894 }
895
main()896 int main() {
897 CU_pSuite pSuite = NULL;
898
899 /* Initialize the CUnit test registry */
900 if (CUE_SUCCESS != CU_initialize_registry()) return CU_get_error();
901
902 /* Add a suite to the registry */
903 pSuite = CU_add_suite("iwkv_test1", init_suite, clean_suite);
904
905 if (NULL == pSuite) {
906 CU_cleanup_registry();
907 return CU_get_error();
908 }
909
910 /* Add the tests to the suite */
911 if (
912 (NULL == CU_add_test(pSuite, "iwkv_test1_v1", iwkv_test1_v1)) ||
913 (NULL == CU_add_test(pSuite, "iwkv_test1_v2", iwkv_test1_v2)) ||
914 (NULL == CU_add_test(pSuite, "iwkv_test2_v1", iwkv_test2_v1)) ||
915 (NULL == CU_add_test(pSuite, "iwkv_test2_v2", iwkv_test2_v2)) ||
916 (NULL == CU_add_test(pSuite, "iwkv_test3_v1", iwkv_test3_v1)) ||
917 (NULL == CU_add_test(pSuite, "iwkv_test3_v2", iwkv_test3_v2)) ||
918
919 //- (NULL == CU_add_test(pSuite, "iwkv_test4", iwkv_test4)) ||
920 //- (NULL == CU_add_test(pSuite, "iwkv_test5", iwkv_test5)) ||
921
922 (NULL == CU_add_test(pSuite, "iwkv_test6_v1", iwkv_test6_v1)) ||
923 (NULL == CU_add_test(pSuite, "iwkv_test6_v2", iwkv_test6_v2)) ||
924 (NULL == CU_add_test(pSuite, "iwkv_test7_v1", iwkv_test7_v1)) ||
925 (NULL == CU_add_test(pSuite, "iwkv_test7_v2", iwkv_test7_v2)) ||
926 (NULL == CU_add_test(pSuite, "iwkv_test8_v1", iwkv_test8_v1)) ||
927 (NULL == CU_add_test(pSuite, "iwkv_test8_v2", iwkv_test8_v2)) ||
928 (NULL == CU_add_test(pSuite, "iwkv_test9", iwkv_test9))
929 ) {
930 CU_cleanup_registry();
931 return CU_get_error();
932 }
933
934 /* Run all tests using the CUnit Basic interface */
935 CU_basic_set_mode(CU_BRM_VERBOSE);
936 CU_basic_run_tests();
937 int ret = CU_get_error() || CU_get_number_of_failures();
938 CU_cleanup_registry();
939 return ret;
940 }
941