• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "jqp.h"
2 #include "ejdb2_internal.h"
3 #include <ejdb2/iowow/iwxstr.h>
4 #include <ejdb2/iowow/iwutils.h>
5 #include <CUnit/Basic.h>
6 #include <stdlib.h>
7 
init_suite(void)8 int init_suite(void) {
9   int rc = ejdb_init();
10   return rc;
11 }
12 
clean_suite(void)13 int clean_suite(void) {
14   return 0;
15 }
16 
_jql_test1_1(int num,iwrc expected)17 void _jql_test1_1(int num, iwrc expected) {
18   fprintf(stderr, "%03d.jql\n", num);
19 
20   iwrc rc;
21   char path[64];
22   char path_expected[64];
23   JQP_AUX *aux;
24   char *data, *edata = 0;
25   IWXSTR *res = iwxstr_new();
26   CU_ASSERT_PTR_NOT_NULL_FATAL(res);
27 
28   snprintf(path, sizeof(path), "data%c%03d.jql", IW_PATH_CHR, num);
29   snprintf(path_expected, sizeof(path_expected), "data%c%03d.expected.jql", IW_PATH_CHR, num);
30   data = iwu_file_read_as_buf(path);
31   CU_ASSERT_PTR_NOT_NULL_FATAL(data);
32 
33   rc = jqp_aux_create(&aux, data);
34   CU_ASSERT_EQUAL_FATAL(rc, 0);
35 
36   rc = jqp_parse(aux);
37   CU_ASSERT_EQUAL_FATAL(rc, expected);
38   if (expected) {
39     goto finish;
40   }
41 
42   CU_ASSERT_PTR_NOT_NULL_FATAL(aux->query);
43 
44   edata = iwu_file_read_as_buf(path_expected);
45   CU_ASSERT_PTR_NOT_NULL_FATAL(edata);
46   rc = jqp_print_query(aux->query, jbl_xstr_json_printer, res);
47   CU_ASSERT_EQUAL_FATAL(rc, 0);
48 
49   // fprintf(stderr, "%s\n", iwxstr_ptr(res));
50   // fprintf(stderr, "%s\n", path_expected);
51   // fprintf(stderr, "%s\n", edata);
52 
53   //  fprintf(stderr, "%d\n", strcmp(edata, iwxstr_ptr(res)));
54   //  FILE *out = fopen("out.txt", "w+");
55   //  fprintf(out, "%s", iwxstr_ptr(res));
56   //  fclose(out);
57 
58   CU_ASSERT_EQUAL_FATAL(strcmp(edata, iwxstr_ptr(res)), 0);
59 
60 finish:
61   if (edata) {
62     free(edata);
63   }
64   free(data);
65   iwxstr_destroy(res);
66   jqp_aux_destroy(&aux);
67 }
68 
jql_test1_1()69 void jql_test1_1() {
70 
71   _jql_test1_1(22, 0);
72 
73   for (int i = 0; i <= 10; ++i) {
74     _jql_test1_1(i, 0);
75   }
76   for (int i = 11; i <= 13; ++i) {
77     _jql_test1_1(i, JQL_ERROR_QUERY_PARSE);
78   }
79   for (int i = 14; i <= 22; ++i) {
80     _jql_test1_1(i, 0);
81   }
82 }
83 
_jql_test1_2(const char * jsondata,const char * q,bool match)84 static void _jql_test1_2(const char *jsondata, const char *q, bool match) {
85   JBL jbl;
86   JQL jql;
87   char *json = iwu_replace_char(strdup(jsondata), '\'', '"');
88   CU_ASSERT_PTR_NOT_NULL_FATAL(json);
89   iwrc rc = jql_create(&jql, "c1", q);
90   CU_ASSERT_EQUAL_FATAL(rc, 0);
91   rc = jbl_from_json(&jbl, json);
92   CU_ASSERT_EQUAL_FATAL(rc, 0);
93   bool m = false;
94   rc = jql_matched(jql, jbl, &m);
95   CU_ASSERT_EQUAL_FATAL(rc, 0);
96   CU_ASSERT_EQUAL_FATAL(m, match);
97 
98   jql_destroy(&jql);
99   jbl_destroy(&jbl);
100   free(json);
101 }
102 
jql_test1_2()103 void jql_test1_2() {
104   _jql_test1_2("{}", "/*", true);
105   _jql_test1_2("{}", "/**", true);
106   _jql_test1_2("{'foo':{'bar':22}}", "/*", true);
107   _jql_test1_2("{'foo':{'bar':22}}", "/**", true);
108   _jql_test1_2("{'foo':{'bar':22}}", "/foo/bar", true);
109   _jql_test1_2("{'foo':{'bar':22}}", "/foo/baz", false);
110   _jql_test1_2("{'foo':{'bar':22}}", "/foo/bar and /foo/bar or /foo", true);
111   _jql_test1_2("{'foo':{'bar':22}}", "/foo/baz or /foo", true);
112   _jql_test1_2("{'foo':{'bar':22}}", "/foo/baz and (/foo/daz or /foo/bar)", false);
113   _jql_test1_2("{'foo':{'bar':22}}", "(/boo or /foo) and (/foo/daz or /foo/bar)", true);
114   _jql_test1_2("{'foo':{'bar':22, 'bar2':'vvv2'}}", "/foo/bar2", true);
115 
116   _jql_test1_2("{'foo':{'bar':22}}", "/foo/[bar = 22]", true);
117   _jql_test1_2("{'foo':{'bar':22}}", "/foo/[bar eq 22]", true);
118   _jql_test1_2("{'foo':{'bar':22}}", "/foo/[bar !eq 22]", false);
119   _jql_test1_2("{'foo':{'bar':22}}", "/foo/[bar != 22]", false);
120   _jql_test1_2("{'foo':{'bar':22}}", "/foo/[bar >= 22]", true);
121   _jql_test1_2("{'foo':{'bar':22}}", "/*/[bar >= 22]", true);
122   _jql_test1_2("{'foo':{'bar':22}}", "/foo/[bar > 21]", true);
123   _jql_test1_2("{'foo':{'bar':22}}", "/foo/[bar > 22]", false);
124   _jql_test1_2("{'foo':{'bar':22}}", "/foo/[bar < 23]", true);
125   _jql_test1_2("{'foo':{'bar':22}}", "/foo/[bar <= 22]", true);
126   _jql_test1_2("{'foo':{'bar':22}}", "/foo/[bar < 22]", false);
127   _jql_test1_2("{'foo':{'bar':22}}", "/*/[bar < 22]", false);
128   _jql_test1_2("{'foo':{'bar':22}}", "/*/[bar > 20 and bar <= 23]", true);
129   _jql_test1_2("{'foo':{'bar':22}}", "/*/[bar > 22 and bar <= 23]", false);
130   _jql_test1_2("{'foo':{'bar':22}}", "/*/[bar > 23 or bar < 23]", true);
131   _jql_test1_2("{'foo':{'bar':22}}", "/*/[bar < 23 or bar > 23]", true);
132   _jql_test1_2("{'foo':{'bar':22}}", "/foo/[[* = bar] = 22]", true);
133   _jql_test1_2("{'foo':{'bar':22}}", "/foo/[[* = bar] != 23]", true);
134   _jql_test1_2("{'foo':{'bar':22}}", "/[* = foo]/[[* = bar] != 23]", true);
135   _jql_test1_2("{'foo':{'bar':22}}", "/[* != foo]/[[* = bar] != 23]", false);
136 
137   // regexp
138   _jql_test1_2("{'foo':{'bar':22}}", "/[* re \"foo\"]", true);
139   _jql_test1_2("{'foo':{'bar':22}}", "/[* re fo]", true);
140   _jql_test1_2("{'foo':{'bar':22}}", "/[* re ^foo$]", true);
141   _jql_test1_2("{'foo':{'bar':22}}", "/[* re ^fo$]", false);
142   _jql_test1_2("{'foo':{'bar':22}}", "/[* not re ^fo$]", true);
143   _jql_test1_2("{'foo':{'bar':22}}", "/foo/[bar re 22]", true);
144   _jql_test1_2("{'foo':{'bar':22}}", "/foo/[bar re \"2+\"]", true);
145 
146   // in
147   _jql_test1_2("{'foo':{'bar':22}}", "/foo/[bar in [21, \"22\"]]", true);
148   _jql_test1_2("{'foo':{'bar':22}}", "/foo/[bar in [21, 23]]", false);
149   _jql_test1_2("{'foo':{'bar':22}}", "/[* in [\"foo\"]]/[bar in [21, 22]]", true);
150   _jql_test1_2("{'foo':{'bar':22}}", "/[* not in [\"foo\"]]/[bar in [21, 22]]", false);
151 
152   // Array element
153   _jql_test1_2("{'tags':['bar', 'foo']}", "/tags/[** in [\"bar\", \"baz\"]]", true);
154   _jql_test1_2("{'tags':['bar', 'foo']}", "/tags/[** in [\"zaz\", \"gaz\"]]", false);
155 
156   // /**
157   _jql_test1_2("{'foo':{'bar':22}}", "/**", true);
158   _jql_test1_2("{'foo':{'bar':22}}", "/**/bar", true);
159   _jql_test1_2("{'foo':{'bar':22}}", "/**/baz", false);
160   _jql_test1_2("{'foo':{'bar':22}}", "/**/**/bar", true);
161   _jql_test1_2("{'foo':{'bar':22, 'baz':{'zaz':33}}}", "/foo/**/zaz", true);
162   _jql_test1_2("{'foo':{'bar':22, 'baz':{'zaz':33}}}", "/foo/**/[zaz > 30]", true);
163   _jql_test1_2("{'foo':{'bar':22, 'baz':{'zaz':33}}}", "/foo/**/[zaz < 30]", false);
164 
165   // arr/obj
166   _jql_test1_2("{'foo':[1,2]}", "/[foo = [1,2]]", true);
167   _jql_test1_2("{'foo':[1,2]}", "/[foo ni 2]", true);
168   _jql_test1_2("{'foo':[1,2]}", "/[foo in [[1,2]]]", true);
169   _jql_test1_2("{'foo':{'arr':[1,2,3,4]}}", "/foo/[arr = [1,2,3,4]]", true);
170   _jql_test1_2("{'foo':{'arr':[1,2,3,4]}}", "/foo/**/[arr = [1,2,3,4]]", true);
171   _jql_test1_2("{'foo':{'arr':[1,2,3,4]}}", "/foo/*/[arr = [1,2,3,4]]", false);
172   _jql_test1_2("{'foo':{'arr':[1,2,3,4]}}", "/foo/[arr = [1,2,3]]", false);
173   _jql_test1_2("{'foo':{'arr':[1,2,3,4]}}", "/foo/[arr = [1,12,3,4]]", false);
174   _jql_test1_2("{'foo':{'obj':{'f':'d','e':'j'}}}", "/foo/[obj = {\"e\":\"j\",\"f\":\"d\"}]", true);
175   _jql_test1_2("{'foo':{'obj':{'f':'d','e':'j'}}}", "/foo/[obj = {\"e\":\"j\",\"f\":\"dd\"}]", false);
176 
177   _jql_test1_2("{'f':22}", "/f", true);
178   _jql_test1_2("{'a':'bar'}", "/f | asc /f", false);
179 
180   // PK
181   _jql_test1_2("{'f':22}", "/=22", true);
182   _jql_test1_2("{'f':22}", "@mycoll/=22", true);
183 
184   //
185   const char *doc
186     = "{"
187       " 'foo':{"
188       "   'bar': {'baz':{'zaz':33}},"
189       "   'sas': {'gaz':{'zaz':44, 'zarr':[42]}},"
190       "   'arr': [1,2,3,4]"
191       " }"
192       "}";
193   _jql_test1_2(doc, "/foo/sas/gaz/zaz", true);
194   _jql_test1_2(doc, "/foo/sas/gaz/[zaz = 44]", true);
195   _jql_test1_2(doc, "/**/[zaz = 44]", true);
196   _jql_test1_2(doc, "/foo/**/[zaz = 44]", true);
197   _jql_test1_2(doc, "/foo/*/*/[zaz = 44]", true);
198   _jql_test1_2(doc, "/foo/[arr ni 3]", true);
199   _jql_test1_2(doc, "/**/[zarr ni 42]", true);
200   _jql_test1_2(doc, "/**/[[* in [\"zarr\"]] in [[42]]]", true);
201 }
202 
_jql_test1_3(bool has_apply_or_project,const char * jsondata,const char * q,const char * eq)203 static void _jql_test1_3(bool has_apply_or_project, const char *jsondata, const char *q, const char *eq) {
204   JBL jbl;
205   JQL jql;
206   JBL_NODE out = 0, eqn = 0;
207   IWPOOL *pool = iwpool_create(512);
208 
209   char *json = iwu_replace_char(strdup(jsondata), '\'', '"');
210   CU_ASSERT_PTR_NOT_NULL_FATAL(json);
211   char *eqjson = iwu_replace_char(strdup(eq), '\'', '"');
212   CU_ASSERT_PTR_NOT_NULL_FATAL(eqjson);
213   char *qstr = iwu_replace_char(strdup(q), '\'', '"');
214   CU_ASSERT_PTR_NOT_NULL_FATAL(qstr);
215 
216   iwrc rc = jql_create(&jql, "c1", qstr);
217   CU_ASSERT_EQUAL_FATAL(rc, 0);
218   rc = jbl_from_json(&jbl, json);
219   CU_ASSERT_EQUAL_FATAL(rc, 0);
220   bool m = false;
221   rc = jql_matched(jql, jbl, &m);
222   CU_ASSERT_EQUAL_FATAL(rc, 0);
223   CU_ASSERT_EQUAL_FATAL(m, true);
224 
225   bool hapl = jql_has_apply(jql) || jql_has_projection(jql);
226   CU_ASSERT_EQUAL_FATAL(hapl, has_apply_or_project);
227   if (!hapl) {
228     goto finish;
229   }
230 
231   CU_ASSERT_PTR_NOT_NULL_FATAL(pool);
232   rc = jql_apply_and_project(jql, jbl, &out, 0, pool);
233   CU_ASSERT_EQUAL_FATAL(rc, 0);
234   CU_ASSERT_PTR_NOT_NULL_FATAL(out);
235 
236   rc = jbn_from_json(eqjson, &eqn, pool);
237   CU_ASSERT_EQUAL_FATAL(rc, 0);
238 
239   int cmp = jbn_compare_nodes(out, eqn, &rc);
240   CU_ASSERT_EQUAL_FATAL(rc, 0);
241   CU_ASSERT_EQUAL_FATAL(cmp, 0);
242 
243 finish:
244   jql_destroy(&jql);
245   jbl_destroy(&jbl);
246   free(json);
247   free(eqjson);
248   free(qstr);
249   iwpool_destroy(pool);
250 }
251 
jql_test1_3()252 void jql_test1_3() {
253 
254   _jql_test1_3(true, "{'foo':{'bar':22}}",
255                "/foo/bar | apply [{'op':'add', 'path':'/baz', 'value':'qux'}]",
256                "{'foo':{'bar':22},'baz':'qux'}");
257 
258   _jql_test1_3(true, "{'foo':{'bar':22}}",
259                "/foo/bar | apply {'baz':'qux'}",
260                "{'foo':{'bar':22},'baz':'qux'}");
261 }
262 
263 // Test projections
jql_test_1_4()264 void jql_test_1_4() {
265 
266   _jql_test1_3(false, "{'foo':{'bar':22}}", "/** | all", "{'foo':{'bar':22}}");
267   _jql_test1_3(false, "{'foo':{'bar':22}}", "/** | all+all + all", "{'foo':{'bar':22}}");
268   _jql_test1_3(true, "{'foo':{'bar':22}}", "/** | all - all", "{}");
269   _jql_test1_3(true, "{'foo':{'bar':22}}", "/** | all-all +all", "{}");
270   _jql_test1_3(true, "{'foo':{'bar':22}}", "/** | /foo/bar", "{'foo':{'bar':22}}");
271   _jql_test1_3(true, "{'foo':{'bar':22, 'baz':'gaz'}}", "/** | /foo/bar", "{'foo':{'bar':22}}");
272   _jql_test1_3(true, "{'foo':{'bar':22, 'baz':'gaz'}}", "/** | /foo/{daz,bar}", "{'foo':{'bar':22}}");
273   _jql_test1_3(true, "{'foo':{'bar':22, 'baz':{'gaz':444, 'zaz':555}}}", "/** | /foo/bar + /foo/baz/zaz",
274                "{'foo':{'bar':22, 'baz':{'zaz':555}}}");
275   _jql_test1_3(true, "{'foo':{'bar':22, 'baz':{'gaz':444, 'zaz':555}}}", "/** | /foo/bar + /foo/baz/zaz - /*/bar",
276                "{'foo':{'baz':{'zaz':555}}}");
277   _jql_test1_3(true, "{'foo':{'bar':22, 'baz':{'gaz':444, 'zaz':555}}}", "/** | all + /foo/bar + /foo/baz/zaz - /*/bar",
278                "{'foo':{'baz':{'zaz':555}}}");
279   _jql_test1_3(true, "{'foo':{'bar':22}}", "/** | /zzz", "{}");
280   _jql_test1_3(true, "{'foo':{'bar':22}}", "/** | /fooo", "{}");
281   _jql_test1_3(true, "{'foo':{'bar':22},'name':'test'}", "/** | all - /name", "{'foo':{'bar':22}}");
282 }
283 
main()284 int main() {
285   CU_pSuite pSuite = NULL;
286   if (CUE_SUCCESS != CU_initialize_registry()) {
287     return CU_get_error();
288   }
289   pSuite = CU_add_suite("jql_test1", init_suite, clean_suite);
290   if (NULL == pSuite) {
291     CU_cleanup_registry();
292     return CU_get_error();
293   }
294   if (  (NULL == CU_add_test(pSuite, "jql_test1_1", jql_test1_1))
295      || (NULL == CU_add_test(pSuite, "jql_test1_2", jql_test1_2))
296      || (NULL == CU_add_test(pSuite, "jql_test1_3", jql_test1_3))
297      || (NULL == CU_add_test(pSuite, "jql_test1_4", jql_test_1_4))) {
298     CU_cleanup_registry();
299     return CU_get_error();
300   }
301   CU_basic_set_mode(CU_BRM_VERBOSE);
302   CU_basic_run_tests();
303   int ret = CU_get_error() || CU_get_number_of_failures();
304   CU_cleanup_registry();
305   return ret;
306 }
307