1 #include "ejdb_test.h"
2 #include <stdlib.h>
3 #include <CUnit/Basic.h>
4
init_suite()5 int init_suite() {
6 int rc = ejdb_init();
7 return rc;
8 }
9
clean_suite()10 int clean_suite() {
11 return 0;
12 }
13
14 // Test document sorting overflow on disk
ejdb_test2_2()15 static void ejdb_test2_2() {
16 EJDB_OPTS opts = {
17 .kv = {
18 .path = "ejdb_test2_2.db",
19 .oflags = IWKV_TRUNC
20 },
21 .document_buffer_sz = 16 * 1024, // 16K
22 .sort_buffer_sz = 1024 * 1024, // 1M
23 .no_wal = true
24 };
25 EJDB db;
26 EJDB_LIST list = 0;
27 const int vbufsz = 512 * 1024;
28 const int dbufsz = vbufsz + 128;
29 char *vbuf = malloc(vbufsz);
30 char *dbuf = malloc(dbufsz);
31 CU_ASSERT_PTR_NOT_NULL_FATAL(vbuf);
32 CU_ASSERT_PTR_NOT_NULL_FATAL(dbuf);
33 memset(vbuf, 'z', vbufsz);
34 vbuf[vbufsz - 1] = '\0';
35
36 iwrc rc = ejdb_open(&opts, &db);
37 CU_ASSERT_EQUAL_FATAL(rc, 0);
38
39 for (int i = 0; i < 6; ++i) {
40 snprintf(dbuf, dbufsz, "{\"f\":%d, \"d\":\"%s\"}", i, vbuf);
41 rc = put_json(db, "c1", dbuf);
42 CU_ASSERT_EQUAL_FATAL(rc, 0);
43 }
44 // Here is we will overflow sort buffer
45 rc = ejdb_list2(db, "c1", "/f | asc /f", 0, &list);
46 CU_ASSERT_EQUAL_FATAL(rc, 0);
47 int i = 0;
48 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
49 JBL jbl;
50 rc = jbl_at(doc->raw, "/f", &jbl);
51 CU_ASSERT_EQUAL_FATAL(rc, 0);
52 int64_t llv = jbl_get_i64(jbl);
53 jbl_destroy(&jbl);
54 CU_ASSERT_EQUAL(llv, i);
55 }
56 ejdb_list_destroy(&list);
57
58 rc = ejdb_close(&db);
59 CU_ASSERT_EQUAL_FATAL(rc, 0);
60 free(vbuf);
61 free(dbuf);
62 }
63
64 struct TEST21_1 {
65 int stage;
66 int cnt;
67 IWXSTR *xstr;
68 };
69
ejdb_test2_1_exec_visitor1(struct _EJDB_EXEC * ctx,const EJDB_DOC doc,int64_t * step)70 static iwrc ejdb_test2_1_exec_visitor1(struct _EJDB_EXEC *ctx, const EJDB_DOC doc, int64_t *step) {
71 struct TEST21_1 *tc = ctx->opaque;
72 JBL jbl;
73 iwrc rc = jbl_at(doc->raw, "/f", &jbl);
74 RCRET(rc);
75 int64_t llv = jbl_get_i64(jbl);
76 if (tc->cnt && (tc->stage == 0)) {
77 tc->stage = 1;
78 *step = 2;
79 } else if (tc->stage == 1) {
80 tc->stage = 2;
81 *step = -1;
82 }
83 jbl_destroy(&jbl);
84 iwxstr_printf(tc->xstr, "%lld", llv);
85 tc->cnt++;
86 return rc;
87 }
88
ejdb_test2_1()89 static void ejdb_test2_1() {
90 EJDB_OPTS opts = {
91 .kv = {
92 .path = "ejdb_test2_1.db",
93 .oflags = IWKV_TRUNC
94 },
95 .no_wal = true
96 };
97
98 EJDB db;
99 EJDB_LIST list = 0;
100 IWXSTR *xstr = iwxstr_new();
101 CU_ASSERT_PTR_NOT_NULL_FATAL(xstr);
102 int i = 0;
103
104 iwrc rc = ejdb_open(&opts, &db);
105 CU_ASSERT_EQUAL_FATAL(rc, 0);
106
107 rc = put_json(db, "a", "{'f':2}");
108 CU_ASSERT_EQUAL_FATAL(rc, 0);
109 rc = put_json(db, "a", "{'f':1}");
110 CU_ASSERT_EQUAL_FATAL(rc, 0);
111 rc = put_json(db, "a", "{'f':3}");
112 CU_ASSERT_EQUAL_FATAL(rc, 0);
113 rc = put_json(db, "a", "{'a':'foo'}");
114 CU_ASSERT_EQUAL_FATAL(rc, 0);
115 rc = put_json(db, "a", "{'a':'gaz'}");
116 CU_ASSERT_EQUAL_FATAL(rc, 0);
117 rc = put_json(db, "a", "{'a':'bar'}");
118 CU_ASSERT_EQUAL_FATAL(rc, 0);
119
120 rc = ejdb_list2(db, "not_exists", "/*", 0, &list);
121 CU_ASSERT_EQUAL_FATAL(rc, 0);
122 i = 0;
123 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
124 }
125 CU_ASSERT_EQUAL(i, 0);
126 ejdb_list_destroy(&list);
127
128 rc = ejdb_list2(db, "a", "/*", 0, &list);
129 CU_ASSERT_EQUAL_FATAL(rc, 0);
130 i = 0;
131 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
132 iwxstr_clear(xstr);
133 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
134 CU_ASSERT_EQUAL_FATAL(rc, 0);
135 switch (i) {
136 case 0:
137 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"a\":\"bar\"}");
138 break;
139 case 1:
140 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"a\":\"gaz\"}");
141 break;
142 case 2:
143 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"a\":\"foo\"}");
144 break;
145 case 5:
146 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":2}");
147 break;
148 }
149 }
150 CU_ASSERT_EQUAL(i, 6);
151 ejdb_list_destroy(&list);
152
153 rc = ejdb_list2(db, "a", "/*", 1, &list);
154 CU_ASSERT_EQUAL_FATAL(rc, 0);
155 i = 0;
156 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
157 }
158 CU_ASSERT_EQUAL(i, 1);
159 ejdb_list_destroy(&list);
160
161 rc = ejdb_list2(db, "a", "/f", 0, &list);
162 CU_ASSERT_EQUAL_FATAL(rc, 0);
163 i = 0;
164 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
165 }
166 CU_ASSERT_EQUAL(i, 3);
167 ejdb_list_destroy(&list);
168
169 rc = ejdb_list2(db, "a", "/* | skip 1", 0, &list);
170 CU_ASSERT_EQUAL_FATAL(rc, 0);
171 i = 0;
172 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
173 iwxstr_clear(xstr);
174 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
175 CU_ASSERT_EQUAL_FATAL(rc, 0);
176 switch (i) {
177 case 0:
178 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"a\":\"gaz\"}");
179 break;
180 }
181 }
182 CU_ASSERT_EQUAL(i, 5);
183 ejdb_list_destroy(&list);
184
185 rc = ejdb_list2(db, "a", "/* | skip 2 limit 3", 0, &list);
186 CU_ASSERT_EQUAL_FATAL(rc, 0);
187 i = 0;
188 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
189 iwxstr_clear(xstr);
190 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
191 CU_ASSERT_EQUAL_FATAL(rc, 0);
192 switch (i) {
193 case 0:
194 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"a\":\"foo\"}");
195 break;
196 }
197 }
198 CU_ASSERT_EQUAL(i, 3);
199 ejdb_list_destroy(&list);
200
201 // Add {f:5}, {f:6}
202 rc = put_json(db, "a", "{'f':5}");
203 CU_ASSERT_EQUAL_FATAL(rc, 0);
204
205 rc = put_json(db, "a", "{'f':6}");
206 CU_ASSERT_EQUAL_FATAL(rc, 0);
207
208 rc = ejdb_list2(db, "a", "/f | asc /f", 0, &list);
209 CU_ASSERT_EQUAL_FATAL(rc, 0);
210 i = 0;
211 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
212 iwxstr_clear(xstr);
213 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
214 CU_ASSERT_EQUAL_FATAL(rc, 0);
215 switch (i) {
216 case 0:
217 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":1}");
218 break;
219 case 1:
220 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":2}");
221 break;
222 case 2:
223 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":3}");
224 break;
225 case 3:
226 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":5}");
227 break;
228 case 4:
229 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":6}");
230 break;
231 }
232 }
233 CU_ASSERT_EQUAL(i, 5);
234 ejdb_list_destroy(&list);
235
236 rc = ejdb_list2(db, "a", "/f | desc /f", 0, &list);
237 CU_ASSERT_EQUAL_FATAL(rc, 0);
238 i = 0;
239 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
240 iwxstr_clear(xstr);
241 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
242 CU_ASSERT_EQUAL_FATAL(rc, 0);
243 switch (i) {
244 case 0:
245 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":6}");
246 break;
247 case 1:
248 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":5}");
249 break;
250 case 2:
251 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":3}");
252 break;
253 case 3:
254 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":2}");
255 break;
256 case 4:
257 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":1}");
258 break;
259 }
260 }
261 CU_ASSERT_EQUAL(i, 5);
262 ejdb_list_destroy(&list);
263
264 //
265 // Now test basic back/forward skips
266 //
267 JQL q;
268 struct TEST21_1 tc = { 0 };
269 tc.xstr = iwxstr_new();
270 rc = jql_create(&q, "a", "/f");
271 CU_ASSERT_EQUAL_FATAL(rc, 0);
272 EJDB_EXEC ux = {
273 .db = db,
274 .q = q,
275 .opaque = &tc,
276 .visitor = ejdb_test2_1_exec_visitor1
277 };
278 rc = ejdb_exec(&ux);
279 CU_ASSERT_EQUAL_FATAL(rc, 0);
280 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(tc.xstr), "65112");
281 jql_destroy(&q);
282 iwxstr_destroy(tc.xstr);
283
284 // back/forward skips for sorted output
285 memset(&tc, 0, sizeof(tc));
286 tc.xstr = iwxstr_new();
287 rc = jql_create(&q, "a", "/f | asc /f");
288 CU_ASSERT_EQUAL_FATAL(rc, 0);
289 ux.q = q;
290 rc = ejdb_exec(&ux);
291 CU_ASSERT_EQUAL_FATAL(rc, 0);
292 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(tc.xstr), "12556");
293 jql_destroy(&q);
294 iwxstr_destroy(tc.xstr);
295
296 rc = ejdb_close(&db);
297 CU_ASSERT_EQUAL_FATAL(rc, 0);
298 iwxstr_destroy(xstr);
299 }
300
main()301 int main() {
302 CU_pSuite pSuite = NULL;
303 if (CUE_SUCCESS != CU_initialize_registry()) {
304 return CU_get_error();
305 }
306 pSuite = CU_add_suite("ejdb_test1", init_suite, clean_suite);
307 if (NULL == pSuite) {
308 CU_cleanup_registry();
309 return CU_get_error();
310 }
311 if ( (NULL == CU_add_test(pSuite, "ejdb_test2_1", ejdb_test2_1))
312 || (NULL == CU_add_test(pSuite, "ejdb_test2_2", ejdb_test2_2))) {
313 CU_cleanup_registry();
314 return CU_get_error();
315 }
316 CU_basic_set_mode(CU_BRM_VERBOSE);
317 CU_basic_run_tests();
318 int ret = CU_get_error() || CU_get_number_of_failures();
319 CU_cleanup_registry();
320 return ret;
321 }
322