• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "iwkv.h"
2 #include "iwlog.h"
3 #include "iwutils.h"
4 #include "iwcfg.h"
5 #include "iwkv_tests.h"
6 #include "iwkv_internal.h"
7 
8 uint32_t g_seed;
9 uint32_t g_rnd_data_pos;
10 #define RND_DATA_SZ (10*1048576)
11 char RND_DATA[RND_DATA_SZ];
12 
rndbuf_next(uint32_t len)13 static void *rndbuf_next(uint32_t len) {
14   assert(len <= RND_DATA_SZ);
15   if (g_rnd_data_pos + len > RND_DATA_SZ) {
16     g_rnd_data_pos = 0;
17   }
18   const char *ret = RND_DATA + g_rnd_data_pos;
19   g_rnd_data_pos += len;
20   return (void *) ret;
21 }
22 
init_suite(void)23 int init_suite(void) {
24   iwrc rc = iwkv_init();
25   RCRET(rc);
26   uint64_t ts;
27   iwp_current_time_ms(&ts, false);
28   ts = IW_SWAB64(ts);
29   ts >>= 32;
30   g_seed = ts;
31 
32   fprintf(stderr, "\nRandom seed: %u\n", g_seed);
33   iwu_rand_seed(g_seed);
34   for (int i = 0; i < RND_DATA_SZ; ++i) {
35     RND_DATA[i] = ' ' + iwu_rand_range(95); // ascii space ... ~
36   }
37   return rc;
38 }
39 
clean_suite(void)40 int clean_suite(void) {
41   return 0;
42 }
43 
iwkv_test4_4(void)44 static void iwkv_test4_4(void) {
45   char *path = "iwkv_test4_4.db";
46   IWKV iwkv;
47   IWDB db1;
48   IWKV_val key = {0};
49   IWKV_val val = {0};
50   IWKV_OPTS opts = {
51     .path = path,
52     .oflags = IWKV_TRUNC,
53     .random_seed = g_seed,
54     .wal = {
55       .enabled = true,
56       .savepoint_timeout_sec = 2,
57       .checkpoint_timeout_sec = 300
58     }
59   };
60   iwrc rc = iwkv_open(&opts, &iwkv);
61   CU_ASSERT_EQUAL_FATAL(rc, 0);
62   rc = iwkv_db(iwkv, 1, 0, &db1);
63   CU_ASSERT_EQUAL_FATAL(rc, 0);
64 
65   key.data = "key00001";
66   key.size = strlen(key.data);
67   val.data = "value00001";
68   val.size = strlen(val.data);
69   rc = iwkv_put(db1, &key, &val, 0);
70   CU_ASSERT_EQUAL_FATAL(rc, 0);
71 
72   CU_ASSERT_FALSE(iwal_synched(iwkv));
73 
74   sleep(4);
75 
76   CU_ASSERT_TRUE(iwal_synched(iwkv));
77 
78   rc = iwkv_close(&iwkv);
79   CU_ASSERT_EQUAL_FATAL(rc, 0);
80 }
81 
iwkv_test4_3_impl(int fmt_version)82 static void iwkv_test4_3_impl(int fmt_version) {
83   char *path = "iwkv_test4_3.db";
84   IWKV iwkv;
85   IWDB db1;
86   IWKV_val key = {0};
87   IWKV_val val = {0};
88   IWKV_OPTS opts = {
89     .path = path,
90     .oflags = IWKV_TRUNC | IWKV_NO_TRIM_ON_CLOSE,
91     .random_seed = g_seed,
92     .fmt_version = fmt_version,
93     .wal = {
94       .enabled = true,
95       .check_crc_on_checkpoint = true,
96       .savepoint_timeout_sec = UINT32_MAX
97     }
98   };
99   iwrc rc = iwkv_open(&opts, &iwkv);
100   CU_ASSERT_EQUAL_FATAL(rc, 0);
101   rc = iwkv_db(iwkv, 1, 0, &db1);
102   CU_ASSERT_EQUAL_FATAL(rc, 0);
103 
104   key.data = "key00001";
105   key.size = strlen(key.data);
106   val.data = "value00001";
107   val.size = strlen(val.data);
108   rc = iwkv_put(db1, &key, &val, 0);
109   CU_ASSERT_EQUAL_FATAL(rc, 0);
110 
111   rc = iwkv_sync(iwkv, 0);
112   CU_ASSERT_EQUAL_FATAL(rc, 0);
113 
114   key.data = "key00002";
115   key.size = strlen(key.data);
116   val.data = "value00002";
117   val.size = strlen(val.data);
118   rc = iwkv_put(db1, &key, &val, 0);
119   CU_ASSERT_EQUAL_FATAL(rc, 0);
120 
121   rc = iwkv_sync(iwkv, 0);
122   CU_ASSERT_EQUAL_FATAL(rc, 0);
123 
124   key.data = "key00003";
125   key.size = strlen(key.data);
126   val.data = "value00003";
127   val.size = strlen(val.data);
128   rc = iwkv_put(db1, &key, &val, 0);
129   CU_ASSERT_EQUAL_FATAL(rc, 0);
130 
131   iwkvd_trigger_xor(IWKVD_WAL_NO_CHECKPOINT_ON_CLOSE);
132 
133   rc = iwkv_close(&iwkv);
134   CU_ASSERT_EQUAL_FATAL(rc, 0);
135 
136   // Now reopen and roll WAL log
137 
138   iwkvd_trigger_xor(IWKVD_WAL_NO_CHECKPOINT_ON_CLOSE);
139 
140   opts.oflags &= ~IWKV_TRUNC;
141   rc = iwkv_open(&opts, &iwkv);
142   CU_ASSERT_EQUAL_FATAL(rc, 0);
143   rc = iwkv_db(iwkv, 1, 0, &db1);
144   CU_ASSERT_EQUAL_FATAL(rc, 0);
145 
146   key.data = "key00001";
147   key.size = strlen(key.data);
148   rc = iwkv_get(db1, &key, &val);
149   CU_ASSERT_EQUAL_FATAL(rc, 0); // !!!!
150   CU_ASSERT_NSTRING_EQUAL(val.data, "value00001", val.size);
151   iwkv_kv_dispose(0, &val);
152 
153   key.data = "key00002";
154   key.size = strlen(key.data);
155   rc = iwkv_get(db1, &key, &val);
156   CU_ASSERT_EQUAL_FATAL(rc, 0);
157   CU_ASSERT_NSTRING_EQUAL(val.data, "value00002", val.size);
158   iwkv_kv_dispose(0, &val);
159 
160   key.data = "key00003";
161   key.size = strlen(key.data);
162   rc = iwkv_get(db1, &key, &val);
163   CU_ASSERT_EQUAL_FATAL(rc, IWKV_ERROR_NOTFOUND);
164 
165   rc = iwkv_close(&iwkv);
166   CU_ASSERT_EQUAL_FATAL(rc, 0);
167 }
168 
iwkv_test4_3_v1()169 static void iwkv_test4_3_v1() {
170   iwkv_test4_3_impl(1);
171 }
172 
iwkv_test4_3_v2()173 static void iwkv_test4_3_v2() {
174   iwkv_test4_3_impl(2);
175 }
176 
iwkv_test2_impl(char * path,const char * walpath,uint32_t num,uint32_t vrange)177 static void iwkv_test2_impl(char *path, const char *walpath, uint32_t num, uint32_t vrange) {
178   g_rnd_data_pos = 0;
179   char kbuf[100];
180   iwrc rc;
181   IWKV iwkv;
182   IWDB db1;
183   if (walpath) {
184     unlink(walpath);
185   }
186   IWKV_val key = {0};
187   IWKV_val val = {0};
188   IWKV_OPTS opts = {
189     .path = path,
190     .oflags = IWKV_TRUNC,
191     .random_seed = g_seed,
192     .wal = {
193       .enabled = (walpath != NULL),
194       .check_crc_on_checkpoint = true,
195       .savepoint_timeout_sec = UINT32_MAX,
196       .wal_buffer_sz = 64 * 1024,
197       .checkpoint_buffer_sz = 32 * 1024 * 1024
198     }
199   };
200   rc = iwkv_open(&opts, &iwkv);
201   CU_ASSERT_EQUAL_FATAL(rc, 0);
202 
203   rc = iwkv_db(iwkv, 1, 0, &db1);
204   CU_ASSERT_EQUAL_FATAL(rc, 0);
205 
206   key.data = kbuf;
207 
208   for (int i = 0; i < num; ++i) {
209     int k = iwu_rand_range(num);
210     snprintf(key.data, sizeof(kbuf), "%016d", k);
211     key.size = strlen(key.data);
212     uint32_t value_size = iwu_rand_range(vrange + 1);
213     if (value_size == 0) {
214       value_size = 1;
215     }
216     val.data = rndbuf_next(value_size);
217     val.size = value_size;
218     rc = iwkv_put(db1, &key, &val, 0);
219     CU_ASSERT_EQUAL_FATAL(rc, 0);
220   }
221   rc = iwkv_close(&iwkv);
222   CU_ASSERT_EQUAL_FATAL(rc, 0);
223 }
224 
iwkv_test4_2(void)225 static void iwkv_test4_2(void) {
226   uint32_t num = 1000;
227   uint32_t vrange = 100000;
228   iwkv_test2_impl("iwkv_test4_2.db", NULL, num, vrange);
229   iwkv_test2_impl("iwkv_test4_2wal.db", "iwkv_test4_2wal.db-wal", num, vrange);
230   FILE *iw1 = fopen("iwkv_test4_2.db", "rb");
231   CU_ASSERT_PTR_NOT_NULL_FATAL(iw1);
232   FILE *iw2 = fopen("iwkv_test4_2wal.db", "rb");
233   CU_ASSERT_PTR_NOT_NULL_FATAL(iw2);
234   int ret = cmp_files(iw1, iw2);
235   CU_ASSERT_FALSE(ret);
236   fclose(iw1);
237   fclose(iw2);
238 }
239 
iwkv_test1_impl(char * path,const char * walpath)240 static void iwkv_test1_impl(char *path, const char *walpath)  {
241   iwrc rc;
242   IWKV iwkv;
243   IWDB db1, db2;
244   if (walpath) {
245     unlink(walpath);
246   }
247   IWKV_val key = {0};
248   IWKV_val val = {0};
249   IWKV_OPTS opts = {
250     .path = path,
251     .oflags = IWKV_TRUNC,
252     .wal = {
253       .enabled = (walpath != NULL),
254       .savepoint_timeout_sec = UINT32_MAX
255     }
256   };
257   rc = iwkv_open(&opts, &iwkv);
258   CU_ASSERT_EQUAL_FATAL(rc, 0);
259 
260   rc = iwkv_db(iwkv, 1, 0, &db1);
261   CU_ASSERT_EQUAL_FATAL(rc, 0);
262 
263   rc = iwkv_db(iwkv, 2, 0, &db2);
264   CU_ASSERT_EQUAL_FATAL(rc, 0);
265 
266   key.data = "foo";
267   key.size = strlen(key.data);
268   val.data = "bar";
269   val.size = strlen(val.data);
270   rc = iwkv_put(db1, &key, &val, 0);
271   CU_ASSERT_EQUAL_FATAL(rc, 0);
272 
273   key.data = "foozz";
274   key.size = strlen(key.data);
275   val.data = "bazz";
276   val.size = strlen(val.data);
277   rc = iwkv_put(db2, &key, &val, 0);
278   CU_ASSERT_EQUAL_FATAL(rc, 0);
279 
280   key.data = "foozz2";
281   key.size = strlen(key.data);
282   val.data = "bazzbazzbazzbazz";
283   val.size = strlen(val.data);
284   rc = iwkv_put(db2, &key, &val, 0);
285   CU_ASSERT_EQUAL_FATAL(rc, 0);
286 
287   key.data = "foozz";
288   key.size = strlen(key.data);
289   rc = iwkv_del(db2, &key, 0);
290   CU_ASSERT_EQUAL_FATAL(rc, 0);
291 
292   rc = iwkv_db_destroy(&db2);
293   CU_ASSERT_EQUAL_FATAL(rc, 0);
294 
295   rc = iwkv_close(&iwkv);
296   CU_ASSERT_EQUAL_FATAL(rc, 0);
297 }
298 
iwkv_test4_1(void)299 static void iwkv_test4_1(void) {
300   iwkv_test1_impl("iwkv_test4_1.db", NULL);
301   iwkv_test1_impl("iwkv_test4_1wal.db", "iwkv_test4_1wal.db-wal");
302   FILE *iw1 = fopen("iwkv_test4_1.db", "rb");
303   CU_ASSERT_PTR_NOT_NULL_FATAL(iw1);
304   FILE *iw2 = fopen("iwkv_test4_1wal.db", "rb");
305   CU_ASSERT_PTR_NOT_NULL_FATAL(iw2);
306   int ret = cmp_files(iw1, iw2);
307   CU_ASSERT_FALSE(ret);
308   fclose(iw1);
309   fclose(iw2);
310 }
311 
main()312 int main() {
313   CU_pSuite pSuite = NULL;
314 
315   /* Initialize the CUnit test registry */
316   if (CUE_SUCCESS != CU_initialize_registry()) return CU_get_error();
317 
318   /* Add a suite to the registry */
319   pSuite = CU_add_suite("iwkv_test4", init_suite, clean_suite);
320 
321   if (NULL == pSuite) {
322     CU_cleanup_registry();
323     return CU_get_error();
324   }
325   /* Add the tests to the suite */
326   if (
327     (NULL == CU_add_test(pSuite, "iwkv_test4_1", iwkv_test4_1)) ||
328     (NULL == CU_add_test(pSuite, "iwkv_test4_2", iwkv_test4_2)) ||
329     (NULL == CU_add_test(pSuite, "iwkv_test4_3_v1", iwkv_test4_3_v1)) ||
330     (NULL == CU_add_test(pSuite, "iwkv_test4_3_v2", iwkv_test4_3_v2)) ||
331     (NULL == CU_add_test(pSuite, "iwkv_test4_4", iwkv_test4_4))
332   )  {
333     CU_cleanup_registry();
334     return CU_get_error();
335   }
336 
337   /* Run all tests using the CUnit Basic interface */
338   CU_basic_set_mode(CU_BRM_VERBOSE);
339   CU_basic_run_tests();
340   int ret = CU_get_error() || CU_get_number_of_failures();
341   CU_cleanup_registry();
342   return ret;
343 }
344