• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "iwkv.h"
2 #include "iwlog.h"
3 #include "iwutils.h"
4 #include "iwkv_tests.h"
5 #include "iwkv_internal.h"
6 #include "iwth.h"
7 
8 iwrc iwal_test_checkpoint(IWKV iwkv);
9 
10 #define KBUFSZ 1024
11 #define VBUFSZ 1024
12 static char kbuf[KBUFSZ];
13 static char vbuf[VBUFSZ];
14 
init_suite(void)15 int init_suite(void) {
16   unlink("./iwkv_test8_1_bkp.db-wal");
17   unlink("./iwkv_test8_1.db-wal");
18   unlink("./iwkv_test8_2_bkp.db-wal");
19   unlink("./iwkv_test8_2_check.db-wal");
20   unlink("./iwkv_test8_2.db-wal");
21   unlink("./iwkv_test8_1_bkp.db");
22   unlink("./iwkv_test8_2_bkp.db");
23   unlink("./iwkv_test8_2_check.db");
24   unlink("./iwkv_test8_2.db");
25   return iwkv_init();
26 }
27 
clean_suite(void)28 int clean_suite(void) {
29   return 0;
30 }
31 
iwkv_test8_1()32 static void iwkv_test8_1() {
33   IWKV iwkv;
34   IWDB db;
35   IWKV_val key = {0};
36   IWKV_val val = {0};
37   IWKV_OPTS opts = {
38     .path = "iwkv_test8_1.db",
39     .oflags = IWKV_TRUNC,
40     .wal = {
41       .enabled = true
42     }
43   };
44   uint64_t ts;
45 
46   iwrc rc = iwkv_open(&opts, &iwkv);
47   CU_ASSERT_EQUAL_FATAL(rc, 0);
48   rc = iwkv_db(iwkv, 1, 0, &db);
49   CU_ASSERT_EQUAL_FATAL(rc, 0);
50 
51   for (int i = 0; i < 1000; ++i) {
52     snprintf(kbuf, KBUFSZ, "%d", i);
53     snprintf(vbuf, VBUFSZ, "%03dval", i);
54     key.data = kbuf;
55     key.size = strlen(key.data);
56     val.data = vbuf;
57     val.size = strlen(val.data);
58     rc = iwkv_put(db, &key, &val, 0);
59     CU_ASSERT_EQUAL_FATAL(rc, 0);
60   }
61   rc = iwkv_close(&iwkv);
62   CU_ASSERT_EQUAL_FATAL(rc, 0);
63 
64   // Now reopen
65   opts.oflags &= ~IWKV_TRUNC;
66   rc = iwkv_open(&opts, &iwkv);
67   CU_ASSERT_EQUAL_FATAL(rc, 0);
68   rc = iwkv_online_backup(iwkv, &ts, "iwkv_test8_1_bkp.db");
69   if (rc) iwlog_ecode_error3(rc);
70   CU_ASSERT_EQUAL_FATAL(rc, 0);
71   rc = iwkv_close(&iwkv);
72   CU_ASSERT_EQUAL_FATAL(rc, 0);
73 
74   // Open backup
75   opts.path = "iwkv_test8_1_bkp.db";
76   rc = iwkv_open(&opts, &iwkv);
77   CU_ASSERT_EQUAL_FATAL(rc, 0);
78   rc = iwkv_db(iwkv, 1, 0, &db);
79   CU_ASSERT_EQUAL_FATAL(rc, 0);
80   for (int i = 0; i < 1000; ++i) {
81     int cret = 0;
82     snprintf(kbuf, KBUFSZ, "%d", i);
83     snprintf(vbuf, VBUFSZ, "%03dval", i);
84     key.data = kbuf;
85     key.size = strlen(key.data);
86     int vlen = strlen(vbuf);
87     rc = iwkv_get(db, &key, &val);
88     CU_ASSERT_EQUAL_FATAL(rc, 0);
89     IW_CMP(cret, vbuf, vlen, val.data, val.size);
90     CU_ASSERT_EQUAL_FATAL(cret, 0);
91     iwkv_val_dispose(&val);
92   }
93   rc = iwkv_close(&iwkv);
94   CU_ASSERT_EQUAL_FATAL(rc, 0);
95 }
96 
97 typedef struct T82 {
98   pthread_t t;
99   pthread_barrier_t barrier;
100   pthread_cond_t cond;
101   pthread_mutex_t mtx;
102   IWKV iwkv;
103   IWKV iwkvcheck;
104 } T82;
105 
t82(void * ctx_)106 static void *t82(void *ctx_) {
107   T82 *ctx = ctx_;
108   IWKV_val key = {0};
109   IWKV_val val = {0};
110 
111   iwrc rc = iwkv_open(&(IWKV_OPTS) {
112     .path = "iwkv_test8_2_check.db",
113     .oflags = IWKV_TRUNC,
114   }, &ctx->iwkvcheck);
115   CU_ASSERT_EQUAL_FATAL(rc, 0);
116 
117   IWDB db, dbc;
118   rc = iwkv_db(ctx->iwkv, 1, 0, &db);
119   CU_ASSERT_EQUAL_FATAL(rc, 0);
120 
121   rc = iwkv_db(ctx->iwkvcheck, 1, 0, &dbc);
122   CU_ASSERT_EQUAL_FATAL(rc, 0);
123 
124   int i = 0;
125   for (; i < 500000; ++i) {
126     snprintf(kbuf, KBUFSZ, "%dkey", i);
127     key.data = kbuf;
128     key.size = strlen(key.data);
129 
130     uint64_t ts;
131     rc = iwp_current_time_ms(&ts, false);
132     CU_ASSERT_EQUAL_FATAL(rc, 0);
133     val.data = &ts;
134     val.size = sizeof(ts);
135 
136     rc = iwkv_put(db, &key, &val, 0);
137     CU_ASSERT_EQUAL_FATAL(rc, 0);
138 
139     rc = iwkv_put(dbc, &key, &val, 0);
140     CU_ASSERT_EQUAL_FATAL(rc, 0);
141   }
142 
143   pthread_barrier_wait(&ctx->barrier);
144 
145   int c = i + 10000;
146   for (; i < c; ++i) {
147 
148     if (i == c - 9800) { // Force checkpoint during online-backup
149       rc = iwal_test_checkpoint(ctx->iwkv);
150       CU_ASSERT_EQUAL_FATAL(rc, 0);
151     }
152 
153     snprintf(kbuf, KBUFSZ, "%dkey", i);
154     key.data = kbuf;
155     key.size = strlen(key.data);
156 
157     uint64_t ts;
158     rc = iwp_current_time_ms(&ts, false);
159     CU_ASSERT_EQUAL_FATAL(rc, 0);
160     val.data = &ts;
161     val.size = sizeof(ts);
162 
163     rc = iwkv_put(db, &key, &val, 0);
164     CU_ASSERT_EQUAL_FATAL(rc, 0);
165 
166     rc = iwkv_put(dbc, &key, &val, 0);
167     CU_ASSERT_EQUAL_FATAL(rc, 0);
168   }
169 
170   rc = iwkv_close(&ctx->iwkvcheck);
171   CU_ASSERT_EQUAL_FATAL(rc, 0);
172   return 0;
173 }
174 
iwkv_test8_2()175 static void iwkv_test8_2() {
176   IWKV_OPTS opts = {
177     .path = "iwkv_test8_2.db",
178     .oflags = IWKV_TRUNC,
179     .wal = {
180       .enabled = true
181     }
182   };
183 
184   T82 ctx = {0};
185   iwrc rc = iwkv_open(&opts, &ctx.iwkv);
186   CU_ASSERT_EQUAL_FATAL(rc, 0);
187 
188   int rci = pthread_barrier_init(&ctx.barrier, 0, 2);
189   CU_ASSERT_EQUAL_FATAL(rci, 0);
190   rci = pthread_create(&ctx.t, 0, t82, &ctx);
191   CU_ASSERT_EQUAL_FATAL(rci, 0);
192 
193   pthread_barrier_wait(&ctx.barrier);
194 
195   uint64_t bkts = 0, ts = 0;
196   rc = iwkv_online_backup(ctx.iwkv, &bkts, "iwkv_test8_2_bkp.db");
197   CU_ASSERT_EQUAL_FATAL(rc, 0);
198 
199 
200   pthread_join(ctx.t, 0);
201   rc = iwkv_close(&ctx.iwkv);
202   CU_ASSERT_EQUAL_FATAL(rc, 0);
203 
204   size_t sp;
205   int cnt1 = 0, cnt2 = 0;
206   IWKV iwkv;
207   IWKV_cursor cur;
208   IWDB db;
209 
210   // Now restore our backup
211   opts.path = "iwkv_test8_2_bkp.db";
212   opts.oflags &= ~IWKV_TRUNC;
213   rc = iwkv_open(&opts, &iwkv);
214   CU_ASSERT_EQUAL_FATAL(rc, 0);
215   rc = iwkv_db(iwkv, 1, 0, &db);
216   CU_ASSERT_EQUAL_FATAL(rc, 0);
217   rc = iwkv_cursor_open(db, &cur, IWKV_CURSOR_BEFORE_FIRST, 0);
218   CU_ASSERT_EQUAL_FATAL(rc, 0);
219   do {
220     rc = iwkv_cursor_to(cur, IWKV_CURSOR_NEXT);
221     if (!rc) {
222       iwkv_cursor_copy_val(cur, &ts, sizeof(ts), &sp);
223       CU_ASSERT_EQUAL_FATAL(sp, sizeof(ts));
224       if (ts < bkts) {
225         cnt1++;
226       }
227     }
228   } while (!rc);
229   CU_ASSERT_EQUAL_FATAL(rc, IWKV_ERROR_NOTFOUND);
230   iwkv_cursor_close(&cur);
231   rc = iwkv_close(&iwkv);
232   CU_ASSERT_EQUAL_FATAL(rc, 0);
233 
234   // Check DB
235   opts.path = "iwkv_test8_2_check.db";
236   rc = iwkv_open(&opts, &iwkv);
237   CU_ASSERT_EQUAL_FATAL(rc, 0);
238   rc = iwkv_db(iwkv, 1, 0, &db);
239   CU_ASSERT_EQUAL_FATAL(rc, 0);
240   rc = iwkv_cursor_open(db, &cur, IWKV_CURSOR_BEFORE_FIRST, 0);
241   CU_ASSERT_EQUAL_FATAL(rc, 0);
242   do {
243     rc = iwkv_cursor_to(cur, IWKV_CURSOR_NEXT);
244     if (!rc) {
245       iwkv_cursor_copy_val(cur, &ts, sizeof(ts), &sp);
246       CU_ASSERT_EQUAL_FATAL(sp, sizeof(ts));
247       if (ts < bkts) {
248         cnt2++;
249       }
250     }
251   } while (!rc);
252   CU_ASSERT_EQUAL_FATAL(rc, IWKV_ERROR_NOTFOUND);
253   iwkv_cursor_close(&cur);
254   rc = iwkv_close(&iwkv);
255   CU_ASSERT_EQUAL_FATAL(rc, 0);
256 
257   fprintf(stderr, "\n%d", cnt1);
258   fprintf(stderr, "\n%d\n", cnt2);
259 
260   CU_ASSERT_TRUE(cnt1 > 500000);
261   CU_ASSERT_EQUAL(cnt1, cnt2);
262 
263   pthread_barrier_destroy(&ctx.barrier);
264 }
265 
main()266 int main() {
267   CU_pSuite pSuite = NULL;
268 
269   /* Initialize the CUnit test registry */
270   if (CUE_SUCCESS != CU_initialize_registry()) return CU_get_error();
271 
272   /* Add a suite to the registry */
273   pSuite = CU_add_suite("iwkv_test8", init_suite, clean_suite);
274 
275   if (NULL == pSuite) {
276     CU_cleanup_registry();
277     return CU_get_error();
278   }
279 
280   /* Add the tests to the suite */
281   if (
282     (NULL == CU_add_test(pSuite, "iwkv_test8_1", iwkv_test8_1)) ||
283     (NULL == CU_add_test(pSuite, "iwkv_test8_2", iwkv_test8_2))
284     ) {
285     CU_cleanup_registry();
286     return CU_get_error();
287   }
288 
289   /* Run all tests using the CUnit Basic interface */
290   CU_basic_set_mode(CU_BRM_VERBOSE);
291   CU_basic_run_tests();
292   int ret = CU_get_error() || CU_get_number_of_failures();
293   CU_cleanup_registry();
294   return ret;
295 }
296