1 #include "ejdb2.h"
2 #include <ejdb2/iowow/iwxstr.h>
3 #include <ejdb2/iowow/iwutils.h>
4
5 #include "jbl.h"
6 #include "jbl_internal.h"
7
8 #include <CUnit/Basic.h>
9
init_suite(void)10 int init_suite(void) {
11 int rc = ejdb_init();
12 return rc;
13 }
14
clean_suite(void)15 int clean_suite(void) {
16 return 0;
17 }
18
_jbl_test1_1(int num,iwrc expected,jbl_print_flags_t pf)19 void _jbl_test1_1(int num, iwrc expected, jbl_print_flags_t pf) {
20 iwrc rc;
21 char path[64];
22 char path_expected[64];
23 JBL_NODE node = 0;
24 IWPOOL *pool;
25 char *data;
26 char *edata = 0;
27 IWXSTR *res = iwxstr_new();
28 CU_ASSERT_PTR_NOT_NULL_FATAL(res);
29
30 snprintf(path, sizeof(path), "data%c%03d.json", IW_PATH_CHR, num);
31 snprintf(path_expected, sizeof(path_expected), "data%c%03d.expected.json", IW_PATH_CHR, num);
32 data = iwu_file_read_as_buf(path);
33 CU_ASSERT_PTR_NOT_NULL_FATAL(data);
34
35 pool = iwpool_create(1024);
36 CU_ASSERT_PTR_NOT_NULL_FATAL(pool);
37
38 rc = jbn_from_json(data, &node, pool);
39 if (rc) {
40 iwlog_ecode_error3(rc);
41 }
42 CU_ASSERT_EQUAL_FATAL(rc, expected);
43 CU_ASSERT_PTR_NOT_NULL_FATAL(node);
44 if (expected) {
45 goto finish;
46 }
47
48 rc = jbn_as_json(node, jbl_xstr_json_printer, res, pf);
49 CU_ASSERT_EQUAL_FATAL(rc, 0);
50
51 edata = iwu_file_read_as_buf(path_expected);
52 CU_ASSERT_PTR_NOT_NULL_FATAL(edata);
53
54 FILE *f1 = fopen("f1.txt", "w");
55 FILE *f2 = fopen("f2.txt", "w");
56 fprintf(f1, "\n%s", edata);
57 fprintf(f2, "\n%s", iwxstr_ptr(res));
58 fclose(f1);
59 fclose(f2);
60
61 fprintf(stderr, "ED %s\n", edata);
62 fprintf(stderr, "ED %s\n", iwxstr_ptr(res));
63
64 CU_ASSERT_EQUAL_FATAL(strcmp(edata, iwxstr_ptr(res)), 0);
65
66 finish:
67 if (edata) {
68 free(edata);
69 }
70 free(data);
71 iwpool_destroy(pool);
72 iwxstr_destroy(res);
73 }
74
jbl_test1_1()75 void jbl_test1_1() {
76 _jbl_test1_1(1, 0, JBL_PRINT_PRETTY);
77 _jbl_test1_1(2, 0, JBL_PRINT_PRETTY | JBL_PRINT_CODEPOINTS);
78 _jbl_test1_1(3, 0, JBL_PRINT_PRETTY);
79 _jbl_test1_1(4, 0, JBL_PRINT_PRETTY);
80 _jbl_test1_1(5, 0, JBL_PRINT_PRETTY);
81 }
82
jbl_test1_2()83 void jbl_test1_2() {
84 const char *data = "{\"foo\": \"b\\\"ar\", \"num1\":1223,"
85 "\"n\\\"um2\":10.1226222, "
86 "\"list\":[3,2.1,1,\"one\", \"two\", "
87 "{}, {\"z\":false, \"t\":true}]}";
88 JBL jbl;
89 iwrc rc = jbl_from_json(&jbl, data);
90 CU_ASSERT_EQUAL_FATAL(rc, 0);
91
92 IWXSTR *xstr = iwxstr_new();
93 CU_ASSERT_PTR_NOT_NULL_FATAL(xstr);
94
95 rc = jbl_as_json(jbl, jbl_xstr_json_printer, xstr, false);
96 CU_ASSERT_EQUAL_FATAL(rc, 0);
97
98 int res = strcmp(iwxstr_ptr(xstr),
99 "{\"foo\":\"b\\\"ar\",\"num1\":1223,\"n\\\"um2\":10.1226222,"
100 "\"list\":[3,2.1,1,\"one\",\"two\",{},{\"z\":false,\"t\":true}]}");
101 CU_ASSERT_EQUAL(res, 0);
102 jbl_destroy(&jbl);
103
104 //
105 rc = jbl_from_json(&jbl, "{ ");
106 CU_ASSERT_EQUAL_FATAL(rc, JBL_ERROR_PARSE_JSON);
107
108 iwxstr_destroy(xstr);
109 }
110
jbl_test1_3()111 void jbl_test1_3() {
112 JBL_PTR jp;
113 iwrc rc = jbl_ptr_alloc("/", &jp);
114 CU_ASSERT_EQUAL_FATAL(rc, 0);
115 CU_ASSERT_EQUAL(jp->cnt, 1);
116 CU_ASSERT_TRUE(*jp->n[0] == '\0')
117 free(jp);
118
119 rc = jbl_ptr_alloc("/foo", &jp);
120 CU_ASSERT_EQUAL_FATAL(rc, 0);
121 CU_ASSERT_EQUAL(jp->cnt, 1);
122 CU_ASSERT_FALSE(strcmp(jp->n[0], "foo"));
123 free(jp);
124
125 rc = jbl_ptr_alloc("/foo/bar", &jp);
126 CU_ASSERT_EQUAL_FATAL(rc, 0);
127 CU_ASSERT_EQUAL(jp->cnt, 2);
128 CU_ASSERT_FALSE(strcmp(jp->n[0], "foo"));
129 CU_ASSERT_FALSE(strcmp(jp->n[1], "bar"));
130 free(jp);
131
132 rc = jbl_ptr_alloc("/foo/bar/0/baz", &jp);
133 CU_ASSERT_EQUAL_FATAL(rc, 0);
134 CU_ASSERT_EQUAL(jp->cnt, 4);
135 CU_ASSERT_FALSE(strcmp(jp->n[0], "foo"));
136 CU_ASSERT_FALSE(strcmp(jp->n[1], "bar"));
137 CU_ASSERT_FALSE(strcmp(jp->n[2], "0"));
138 CU_ASSERT_FALSE(strcmp(jp->n[3], "baz"));
139 free(jp);
140
141 rc = jbl_ptr_alloc("/foo/b~0ar/0/b~1az", &jp);
142 CU_ASSERT_EQUAL_FATAL(rc, 0);
143 CU_ASSERT_EQUAL(jp->cnt, 4);
144 CU_ASSERT_FALSE(strcmp(jp->n[0], "foo"));
145 CU_ASSERT_FALSE(strcmp(jp->n[1], "b~ar"));
146 CU_ASSERT_FALSE(strcmp(jp->n[2], "0"));
147 CU_ASSERT_FALSE(strcmp(jp->n[3], "b/az"));
148 free(jp);
149
150 rc = jbl_ptr_alloc("/foo/", &jp);
151 CU_ASSERT_EQUAL(rc, JBL_ERROR_JSON_POINTER);
152 free(jp);
153
154 rc = jbl_ptr_alloc("//", &jp);
155 CU_ASSERT_EQUAL(rc, JBL_ERROR_JSON_POINTER);
156 free(jp);
157
158 rc = jbl_ptr_alloc("", &jp);
159 CU_ASSERT_EQUAL(rc, JBL_ERROR_JSON_POINTER);
160 free(jp);
161
162 rc = jbl_ptr_alloc("~", &jp);
163 CU_ASSERT_EQUAL(rc, JBL_ERROR_JSON_POINTER);
164 free(jp);
165 }
166
jbl_test1_4()167 void jbl_test1_4() {
168 // { "foo": "bar",
169 // "foo2": {
170 // "foo3": {
171 // "foo4": "bar4"
172 // },
173 // "foo5": "bar5"
174 // },
175 // "num1": 1,
176 // "list1": ["one", "two", {"three": 3}]
177 // }
178 char *data
179 = iwu_replace_char(
180 strdup("{'foo':'bar','foo2':{'foo3':{'foo4':'bar4'},'foo5':'bar5'},"
181 "'num1':1,'list1':['one','two',{'three':3}]}"),
182 '\'', '"');
183 JBL jbl, at, at2;
184 const char *sval;
185 int ival;
186 iwrc rc = jbl_from_json(&jbl, data);
187 CU_ASSERT_EQUAL_FATAL(rc, 0);
188
189 rc = jbl_at(jbl, "/foo", &at);
190 CU_ASSERT_EQUAL_FATAL(rc, 0);
191 CU_ASSERT_PTR_NOT_NULL_FATAL(at);
192
193 sval = jbl_get_str(at);
194 CU_ASSERT_PTR_NOT_NULL_FATAL(sval);
195 CU_ASSERT_STRING_EQUAL(sval, "bar");
196 jbl_destroy(&at);
197
198 rc = jbl_at(jbl, "/foo2/foo3", &at);
199 CU_ASSERT_EQUAL_FATAL(rc, 0);
200 CU_ASSERT_PTR_NOT_NULL_FATAL(at);
201 CU_ASSERT_TRUE(at->bn.type == BINN_OBJECT);
202 rc = jbl_at(at, "/foo4", &at2);
203 CU_ASSERT_EQUAL_FATAL(rc, 0);
204 CU_ASSERT_PTR_NOT_NULL_FATAL(at2);
205 sval = jbl_get_str(at2);
206 CU_ASSERT_PTR_NOT_NULL_FATAL(sval);
207 CU_ASSERT_STRING_EQUAL(sval, "bar4");
208 jbl_destroy(&at2);
209 jbl_destroy(&at);
210
211 at = (void*) 1;
212 rc = jbl_at(jbl, "/foo2/foo10", &at);
213 CU_ASSERT_EQUAL(rc, JBL_ERROR_PATH_NOTFOUND);
214 CU_ASSERT_PTR_NULL(at);
215 rc = 0;
216
217 rc = jbl_at(jbl, "/foo2/*/foo4", &at);
218 CU_ASSERT_EQUAL_FATAL(rc, 0);
219 CU_ASSERT_PTR_NOT_NULL_FATAL(at);
220 sval = jbl_get_str(at);
221 CU_ASSERT_PTR_NOT_NULL_FATAL(sval);
222 CU_ASSERT_STRING_EQUAL(sval, "bar4");
223 jbl_destroy(&at);
224
225 rc = jbl_at(jbl, "/list1/1", &at);
226 CU_ASSERT_EQUAL_FATAL(rc, 0);
227 CU_ASSERT_PTR_NOT_NULL_FATAL(at);
228 sval = jbl_get_str(at);
229 CU_ASSERT_STRING_EQUAL(sval, "two");
230 jbl_destroy(&at);
231
232 rc = jbl_at(jbl, "/list1/2/three", &at);
233 CU_ASSERT_EQUAL_FATAL(rc, 0);
234 CU_ASSERT_PTR_NOT_NULL_FATAL(at);
235 ival = jbl_get_i32(at);
236 CU_ASSERT_EQUAL(ival, 3);
237 jbl_destroy(&at);
238
239 rc = jbl_at(jbl, "/list1/*/three", &at);
240 CU_ASSERT_EQUAL_FATAL(rc, 0);
241 CU_ASSERT_PTR_NOT_NULL_FATAL(at);
242 ival = jbl_get_i32(at);
243 CU_ASSERT_EQUAL(ival, 3);
244 jbl_destroy(&at);
245
246 rc = jbl_at(jbl, "/list1/*/*", &at);
247 CU_ASSERT_EQUAL_FATAL(rc, 0);
248 CU_ASSERT_PTR_NOT_NULL_FATAL(at);
249 ival = jbl_get_i32(at);
250 CU_ASSERT_EQUAL(ival, 3);
251 jbl_destroy(&at);
252
253 jbl_destroy(&jbl);
254 free(data);
255 }
256
jbl_test1_5()257 void jbl_test1_5() {
258 IWXSTR *xstr = iwxstr_new();
259 CU_ASSERT_PTR_NOT_NULL_FATAL(xstr);
260
261 // { "foo": "bar",
262 // "foo2": {
263 // "foo3": {
264 // "foo4": "bar4"
265 // },
266 // "foo5": "bar5"
267 // },
268 // "num1": 1,
269 // "list1": ["one", "two", {"three": 3}]
270 // }
271 char *data
272 = iwu_replace_char(
273 strdup("{'foo':'bar','foo2':{'foo3':{'foo4':'bar4'},'foo5':'bar5'},"
274 "'num1':1,'list1':['one','two',{'three':3}]}"),
275 '\'', '"');
276 JBL jbl;
277 int res = 0;
278
279 // Remove ROOT
280 JBL_PATCH p1[] = { { .op = JBP_REMOVE, .path = "/" } };
281 iwrc rc = jbl_from_json(&jbl, data);
282 CU_ASSERT_EQUAL_FATAL(rc, 0);
283 rc = jbl_patch(jbl, p1, sizeof(p1) / sizeof(p1[0]));
284 CU_ASSERT_EQUAL_FATAL(rc, 0);
285 jbl_destroy(&jbl);
286
287
288 // Remove "/foo"
289 JBL_PATCH p2[] = { { .op = JBP_REMOVE, .path = "/foo" } };
290 rc = jbl_from_json(&jbl, data);
291 CU_ASSERT_EQUAL_FATAL(rc, 0);
292 rc = jbl_patch(jbl, p2, sizeof(p2) / sizeof(p2[0]));
293 CU_ASSERT_EQUAL_FATAL(rc, 0);
294 rc = jbl_as_json(jbl, jbl_xstr_json_printer, xstr, false);
295 CU_ASSERT_EQUAL_FATAL(rc, 0);
296 res = strcmp(iwxstr_ptr(
297 xstr),
298 "{\"foo2\":{\"foo3\":{\"foo4\":\"bar4\"},\"foo5\":\"bar5\"},\"num1\":1,\"list1\":[\"one\",\"two\",{\"three\":3}]}");
299 CU_ASSERT_EQUAL(res, 0);
300 jbl_destroy(&jbl);
301 iwxstr_clear(xstr);
302
303 // Remove /foo2/foo3/foo4
304 // Remove /list1/1
305 JBL_PATCH p3[] = {
306 { .op = JBP_REMOVE, .path = "/foo2/foo3/foo4" },
307 { .op = JBP_REMOVE, .path = "/list1/1" }
308 };
309 rc = jbl_from_json(&jbl, data);
310 CU_ASSERT_EQUAL_FATAL(rc, 0);
311 rc = jbl_patch(jbl, p3, sizeof(p3) / sizeof(p3[0]));
312 CU_ASSERT_EQUAL_FATAL(rc, 0);
313 rc = jbl_as_json(jbl, jbl_xstr_json_printer, xstr, false);
314 CU_ASSERT_EQUAL_FATAL(rc, 0);
315 res = strcmp(iwxstr_ptr(xstr),
316 "{\"foo\":\"bar\",\"foo2\":{\"foo3\":{},\"foo5\":\"bar5\"},\"num1\":1,\"list1\":[\"one\",{\"three\":3}]}");
317 CU_ASSERT_EQUAL(res, 0);
318 jbl_destroy(&jbl);
319 iwxstr_clear(xstr);
320 iwxstr_destroy(xstr);
321 free(data);
322 }
323
apply_patch(const char * data,const char * patch,const char * result,IWXSTR * xstr,iwrc * rcp)324 void apply_patch(const char *data, const char *patch, const char *result, IWXSTR *xstr, iwrc *rcp) {
325 CU_ASSERT_TRUE_FATAL(data && patch && xstr && rcp);
326 JBL jbl = 0;
327 char *data2 = iwu_replace_char(strdup(data), '\'', '"');
328 char *patch2 = iwu_replace_char(strdup(patch), '\'', '"');
329 char *result2 = result ? iwu_replace_char(strdup(result), '\'', '"') : 0;
330 CU_ASSERT_TRUE_FATAL(data2 && patch2);
331
332 iwrc rc = jbl_from_json(&jbl, data2);
333 RCGO(rc, finish);
334
335 rc = jbl_patch_from_json(jbl, patch2);
336 RCGO(rc, finish);
337
338 rc = jbl_as_json(jbl, jbl_xstr_json_printer, xstr, false);
339 RCGO(rc, finish);
340
341 if (result2) {
342 CU_ASSERT_STRING_EQUAL(result2, iwxstr_ptr(xstr));
343 }
344
345 finish:
346 if (data2) {
347 free(data2);
348 }
349 if (patch2) {
350 free(patch2);
351 }
352 if (result2) {
353 free(result2);
354 }
355 if (jbl) {
356 jbl_destroy(&jbl);
357 }
358 *rcp = rc;
359 }
360
apply_merge_patch(const char * data,const char * patch,const char * result,IWXSTR * xstr,iwrc * rcp)361 void apply_merge_patch(const char *data, const char *patch, const char *result, IWXSTR *xstr, iwrc *rcp) {
362 CU_ASSERT_TRUE_FATAL(data && patch && xstr && rcp);
363 JBL jbl = 0;
364 char *data2 = iwu_replace_char(strdup(data), '\'', '"');
365 char *patch2 = iwu_replace_char(strdup(patch), '\'', '"');
366 char *result2 = result ? iwu_replace_char(strdup(result), '\'', '"') : 0;
367 CU_ASSERT_TRUE_FATAL(data2 && patch2);
368
369 iwrc rc = jbl_from_json(&jbl, data2);
370 RCGO(rc, finish);
371
372 rc = jbl_merge_patch(jbl, patch2);
373 RCGO(rc, finish);
374
375 rc = jbl_as_json(jbl, jbl_xstr_json_printer, xstr, false);
376 RCGO(rc, finish);
377
378 if (result2) {
379 CU_ASSERT_STRING_EQUAL(result2, iwxstr_ptr(xstr));
380 }
381
382 finish:
383 if (data2) {
384 free(data2);
385 }
386 if (patch2) {
387 free(patch2);
388 }
389 if (result2) {
390 free(result2);
391 }
392 if (jbl) {
393 jbl_destroy(&jbl);
394 }
395 *rcp = rc;
396 }
397
398 // Run tests: https://github.com/json-patch/json-patch-tests/blob/master/spec_tests.json
jbl_test1_6()399 void jbl_test1_6() {
400 iwrc rc;
401 IWXSTR *xstr = iwxstr_new();
402 CU_ASSERT_PTR_NOT_NULL_FATAL(xstr);
403
404 apply_patch("{'foo':'bar','foo2':{'foo3':{'foo4':'bar4'},'foo5':'bar5'},'num1':1,'list1':['one','two',{'three':3}]}",
405 "[{'op':'remove', 'path':'/foo'}]",
406 "{'foo2':{'foo3':{'foo4':'bar4'},'foo5':'bar5'},'num1':1,'list1':['one','two',{'three':3}]}",
407 xstr, &rc);
408 CU_ASSERT_EQUAL_FATAL(rc, 0);
409 iwxstr_clear(xstr);
410
411 // 4.1. add with missing object
412 apply_patch("{ 'q': { 'bar': 2 } }",
413 "[ {'op': 'add', 'path': '/a/b', 'value': 1} ]",
414 0, xstr, &rc);
415 CU_ASSERT_EQUAL(rc, JBL_ERROR_PATCH_TARGET_INVALID);
416 iwxstr_clear(xstr);
417
418 // A.1. Adding an Object Member
419 apply_patch("{'foo': 'bar'}",
420 "[ { 'op': 'add', 'path': '/baz', 'value': 'qux' } ]",
421 "{'foo':'bar','baz':'qux'}", xstr, &rc);
422 CU_ASSERT_EQUAL_FATAL(rc, 0);
423 iwxstr_clear(xstr);
424
425 // A.2. Adding an Array Element
426 apply_patch("{'foo': [ 'bar', 'baz' ]}",
427 "[{ 'op': 'add', 'path': '/foo/1', 'value': 'qux' }]",
428 "{'foo':['bar','qux','baz']}", xstr, &rc);
429 CU_ASSERT_EQUAL_FATAL(rc, 0);
430 iwxstr_clear(xstr);
431
432 // A.3. Removing an Object Member
433 apply_patch("{'baz': 'qux','foo': 'bar'}",
434 "[{ 'op': 'remove', 'path': '/baz' }]",
435 "{'foo':'bar'}", xstr, &rc);
436 CU_ASSERT_EQUAL_FATAL(rc, 0);
437 iwxstr_clear(xstr);
438
439 // A.4. Removing an Array Element
440 apply_patch("{'foo': [ 'bar', 'qux', 'baz' ]}",
441 "[{ 'op': 'remove', 'path': '/foo/1' }]",
442 "{'foo':['bar','baz']}", xstr, &rc);
443 CU_ASSERT_EQUAL_FATAL(rc, 0);
444 iwxstr_clear(xstr);
445
446 // A.5. Replacing a Value
447 apply_patch("{'baz': 'qux','foo': 'bar'}",
448 "[{ 'op': 'replace', 'path': '/baz', 'value': 'boo' }]",
449 "{'foo':'bar','baz':'boo'}", xstr, &rc);
450 CU_ASSERT_EQUAL_FATAL(rc, 0);
451 iwxstr_clear(xstr);
452
453 // A.5.1 #232
454 apply_patch("{'a':{'c':'N','s':'F'}}",
455 "[{'op':'replace', 'path':'/a/s', 'value':'A'}]",
456 "{'a':{'c':'N','s':'A'}}", xstr, &rc);
457 CU_ASSERT_EQUAL_FATAL(rc, 0);
458 iwxstr_clear(xstr);
459
460 // A.6. Moving a Value
461 apply_patch("{'foo': {'bar': 'baz','waldo': 'fred'},'qux': {'corge': 'grault'}}",
462 "[{ 'op': 'move', 'from': '/foo/waldo', 'path': '/qux/thud' }]",
463 "{'foo':{'bar':'baz'},'qux':{'corge':'grault','thud':'fred'}}", xstr, &rc);
464 CU_ASSERT_EQUAL_FATAL(rc, 0);
465 iwxstr_clear(xstr);
466
467 // A.7. Moving an Array Element
468 apply_patch("{'foo': [ 'all', 'grass', 'cows', 'eat' ]}",
469 "[{ 'op': 'move', 'from': '/foo/1', 'path': '/foo/3' }]",
470 "{'foo':['all','cows','eat','grass']}", xstr, &rc);
471 CU_ASSERT_EQUAL_FATAL(rc, 0);
472 iwxstr_clear(xstr);
473
474 // A.8. Testing a Value: Success
475 apply_patch("{'baz': 'qux','foo': [ 'a', 2, 'c' ]}",
476 "["
477 "{ 'op': 'test', 'path': '/baz', 'value': 'qux' },"
478 "{ 'op': 'test', 'path': '/foo/1', 'value': 2 }"
479 "]",
480 "{'baz':'qux','foo':['a',2,'c']}", xstr, &rc);
481 CU_ASSERT_EQUAL_FATAL(rc, 0);
482 iwxstr_clear(xstr);
483
484 // A.8. Testing a Value Object
485 apply_patch(
486 "{'foo':'bar','foo2':{'zaz':25, 'foo3':{'foo4':'bar4'},'foo5':'bar5'},'num1':1,'list1':['one','two',{'three':3}]}",
487 "[{ 'op': 'test', 'path': '/foo2', 'value': {'foo5':'bar5', 'zaz':25, 'foo3':{'foo4':'bar4'}} }]",
488 0,
489 xstr,
490 &rc);
491 CU_ASSERT_EQUAL_FATAL(rc, 0);
492 iwxstr_clear(xstr);
493
494 apply_patch(
495 "{'foo':'bar','foo2':{'zaz':25, 'foo3':{'foo4':'bar4'},'foo5':'bar5'},'num1':1,'list1':['one','two',{'three':3}]}",
496 "[{ 'op': 'test', 'path': '/foo2', 'value': {'foo5':'bar5', 'zaz':25, 'foo3':{'foo41':'bar4'}} }]",
497 0,
498 xstr,
499 &rc);
500 CU_ASSERT_EQUAL_FATAL(rc, JBL_ERROR_PATCH_TEST_FAILED);
501 iwxstr_clear(xstr);
502
503 apply_patch(
504 "{'foo':'bar','foo2':{'zaz':25, 'foo3':{'foo4':'bar4'},'foo5':'bar5'},'num1':1,'list1':['one','two',{'three':3}]}",
505 "[{ 'op': 'test', 'path': '/', 'value': {'num1':1, 'foo2':{'foo3':{'foo4':'bar4'}, 'zaz':25, 'foo5':'bar5'},'list1':['one','two',{'three':3}],'foo':'bar'} }]",
506 0,
507 xstr,
508 &rc);
509 CU_ASSERT_EQUAL_FATAL(rc, 0);
510 iwxstr_clear(xstr);
511
512 apply_patch(
513 "{'foo':'bar','foo2':{'zaz':25, 'foo3':{'foo4':'bar4'},'foo5':'bar5'},'num1':1,'list1':['one','two',{'three':3}]}",
514 "[{ 'op': 'test', 'path': '/list1', 'value':['one','two',{'three':3}] }]",
515 0,
516 xstr,
517 &rc);
518 CU_ASSERT_EQUAL_FATAL(rc, 0);
519 iwxstr_clear(xstr);
520
521 apply_patch(
522 "{'foo':'bar','foo2':{'zaz':25, 'foo3':{'foo4':'bar4'},'foo5':'bar5'},'num1':1,'list1':['one','two',{'three':3}]}",
523 "[{ 'op': 'test', 'path': '/list1', 'value':['two','one',{'three':3}] }]",
524 0,
525 xstr,
526 &rc);
527 CU_ASSERT_EQUAL_FATAL(rc, JBL_ERROR_PATCH_TEST_FAILED);
528 iwxstr_clear(xstr);
529
530 // A.9. Testing a Value: Error
531 apply_patch("{ 'baz': 'qux'}",
532 "[{ 'op': 'test', 'path': '/baz', 'value': 'bar' }]",
533 0, xstr, &rc);
534 CU_ASSERT_EQUAL(rc, JBL_ERROR_PATCH_TEST_FAILED);
535 iwxstr_clear(xstr);
536
537 // A.10. Adding a nested Member Object
538 apply_patch("{'foo': 'bar'}",
539 "[{ 'op': 'add', 'path': '/child', 'value': { 'grandchild': { } } }]",
540 "{'foo':'bar','child':{'grandchild':{}}}", xstr, &rc);
541 CU_ASSERT_EQUAL_FATAL(rc, 0);
542 iwxstr_clear(xstr);
543
544 // A.11. Ignoring Unrecognized Elements
545 apply_patch("{'foo': 'bar'}",
546 "[{ 'op': 'add', 'path': '/baz', 'value': 'qux', 'xyz': 123 }]",
547 "{'foo':'bar','baz':'qux'}", xstr, &rc);
548 CU_ASSERT_EQUAL_FATAL(rc, 0);
549 iwxstr_clear(xstr);
550
551 // A.12. Adding to a Non-existent Target
552 apply_patch("{'foo': 'bar'}",
553 "[{ 'op': 'add', 'path': '/baz/bat', 'value': 'qux' }]",
554 0, xstr, &rc);
555 CU_ASSERT_EQUAL(rc, JBL_ERROR_PATCH_TARGET_INVALID);
556 iwxstr_clear(xstr);
557
558 // A.14. ~ Escape Ordering
559 apply_patch("{'/': 9,'~1': 10}",
560 "[{'op': 'test', 'path': '/~01', 'value': 10}]",
561 "{'/':9,'~1':10}", xstr, &rc);
562 CU_ASSERT_EQUAL_FATAL(rc, 0);
563 iwxstr_clear(xstr);
564
565 // A.15. Comparing Strings and Numbers
566 apply_patch("{'/': 9,'~1': 10}",
567 "[{'op': 'test', 'path': '/~01', 'value': '10'}]",
568 "{'/':9,'~1':10}", xstr, &rc);
569 CU_ASSERT_EQUAL(rc, JBL_ERROR_PATCH_TEST_FAILED);
570 iwxstr_clear(xstr);
571
572 // A.16. Adding an Array Value
573 apply_patch("{'foo': ['bar']}",
574 "[{'op': 'add', 'path': '/foo/-', 'value': ['abc', 'def'] }]",
575 "{'foo':['bar',['abc','def']]}", xstr, &rc);
576 CU_ASSERT_EQUAL_FATAL(rc, 0);
577 iwxstr_clear(xstr);
578
579 // Apply non standard `increment` patch
580 apply_patch("{'foo': 1}",
581 "[{'op': 'increment', 'path': '/foo', 'value': 2}]",
582 "{'foo':3}", xstr, &rc);
583 CU_ASSERT_EQUAL_FATAL(rc, 0);
584 iwxstr_clear(xstr);
585
586 // Apply non standard `swap` patch
587 apply_patch("{'foo': ['bar'], 'baz': {'gaz': 11}}",
588 "[{'op': 'swap', 'from': '/foo/0', 'path': '/baz/gaz'}]",
589 "{'foo':[11],'baz':{'gaz':'bar'}}", xstr, &rc);
590 CU_ASSERT_EQUAL_FATAL(rc, 0);
591 iwxstr_clear(xstr);
592
593 apply_patch("{'foo': ['bar'], 'baz': {'gaz': 11}}",
594 "[{'op': 'swap', 'from': '/foo/0', 'path': '/baz/zaz'}]",
595 "{'foo':[],'baz':{'gaz':11,'zaz':'bar'}}", xstr, &rc);
596
597 CU_ASSERT_EQUAL_FATAL(rc, 0);
598 iwxstr_clear(xstr);
599
600 apply_patch("{'foo': 1}",
601 "[{'op': 'increment', 'path': '/foo', 'value': true}]",
602 "{'foo':3}", xstr, &rc);
603 CU_ASSERT_EQUAL_FATAL(rc, JBL_ERROR_PATCH_INVALID_VALUE);
604 iwxstr_clear(xstr);
605
606 // Apply non standard add_create patch
607 apply_patch("{'foo': {'bar': 1}}",
608 "[{'op': 'add_create', 'path': '/foo/zaz/gaz', 'value': 22}]",
609 "{'foo':{'bar':1,'zaz':{'gaz':22}}}", xstr, &rc);
610 CU_ASSERT_EQUAL_FATAL(rc, 0);
611 iwxstr_clear(xstr);
612
613 apply_patch("{'foo': {'bar': 1}}",
614 "[{'op': 'add_create', 'path': '/foo/bar/gaz', 'value': 22}]",
615 "{}", xstr, &rc);
616 CU_ASSERT_EQUAL_FATAL(rc, JBL_ERROR_PATCH_TARGET_INVALID);
617 iwxstr_clear(xstr);
618
619 apply_patch("{'foo': {'bar': 1}}",
620 "[{'op': 'add_create', 'path': '/zaz/gaz', 'value': [1,2,3]}]",
621 "{'foo':{'bar':1},'zaz':{'gaz':[1,2,3]}}", xstr, &rc);
622 CU_ASSERT_EQUAL_FATAL(rc, 0);
623 iwxstr_clear(xstr);
624
625 iwxstr_destroy(xstr);
626 }
627
jbl_test1_7()628 void jbl_test1_7() {
629 iwrc rc;
630 IWXSTR *xstr = iwxstr_new();
631 CU_ASSERT_PTR_NOT_NULL_FATAL(xstr);
632
633 // #233
634 apply_merge_patch("{'n':'nv'}",
635 "{'a':{'c':'v','d':'k'}}",
636 "{'n':'nv','a':{'c':'v','d':'k'}}", xstr, &rc);
637 CU_ASSERT_EQUAL_FATAL(rc, 0);
638 iwxstr_clear(xstr);
639
640 apply_merge_patch("{'a':'b'}",
641 "{'a':'c'}",
642 "{'a':'c'}", xstr, &rc);
643 CU_ASSERT_EQUAL_FATAL(rc, 0);
644 iwxstr_clear(xstr);
645
646
647 apply_merge_patch("{'a':'b'}",
648 "{'b':'c'}",
649 "{'a':'b','b':'c'}", xstr, &rc);
650 CU_ASSERT_EQUAL_FATAL(rc, 0);
651 iwxstr_clear(xstr);
652
653 apply_merge_patch("{'a':'b'}",
654 "{'a':null}",
655 "{}", xstr, &rc);
656 CU_ASSERT_EQUAL_FATAL(rc, 0);
657 iwxstr_clear(xstr);
658
659 apply_merge_patch("{'a':'b','b':'c'}",
660 "{'a':null}",
661 "{'b':'c'}", xstr, &rc);
662 CU_ASSERT_EQUAL_FATAL(rc, 0);
663 iwxstr_clear(xstr);
664
665 apply_merge_patch("{'a':['b']}",
666 "{'a':'c'}",
667 "{'a':'c'}", xstr, &rc);
668 CU_ASSERT_EQUAL_FATAL(rc, 0);
669 iwxstr_clear(xstr);
670
671 apply_merge_patch("{'a':'c'}",
672 "{'a':['b']}",
673 "{'a':['b']}", xstr, &rc);
674 CU_ASSERT_EQUAL_FATAL(rc, 0);
675 iwxstr_clear(xstr);
676
677 apply_merge_patch("{'a':{'b':'c'}}",
678 "{'a':{'b':'d','c':null}}",
679 "{'a':{'b':'d'}}", xstr, &rc);
680 CU_ASSERT_EQUAL_FATAL(rc, 0);
681 iwxstr_clear(xstr);
682
683 apply_merge_patch("{'a':[{'b':'c'}]}",
684 "{'a':[1]}",
685 "{'a':[1]}", xstr, &rc);
686 CU_ASSERT_EQUAL_FATAL(rc, 0);
687 iwxstr_clear(xstr);
688
689 apply_merge_patch("['a','b']",
690 "['c','d']",
691 "['c','d']", xstr, &rc);
692 CU_ASSERT_EQUAL_FATAL(rc, 0);
693 iwxstr_clear(xstr);
694
695 apply_merge_patch("{'a':'b'}",
696 "['c']",
697 "['c']", xstr, &rc);
698 CU_ASSERT_EQUAL_FATAL(rc, 0);
699 iwxstr_clear(xstr);
700
701 apply_merge_patch("{'e':null}",
702 "{'a':1}",
703 "{'e':null,'a':1}", xstr, &rc);
704 CU_ASSERT_EQUAL_FATAL(rc, 0);
705 iwxstr_clear(xstr);
706
707 apply_merge_patch("[1,2]",
708 "{'a':'b','c':null}",
709 "{'a':'b'}", xstr, &rc);
710 CU_ASSERT_EQUAL_FATAL(rc, 0);
711 iwxstr_clear(xstr);
712
713 apply_merge_patch("{}",
714 "{'a':{'bb':{'ccc':null}}}",
715 "{'a':{'bb':{}}}", xstr, &rc);
716 CU_ASSERT_EQUAL_FATAL(rc, 0);
717 iwxstr_clear(xstr);
718
719
720 iwxstr_destroy(xstr);
721 }
722
jbl_test1_8()723 void jbl_test1_8() {
724 JBL jbl, nested, at;
725 iwrc rc = jbl_create_empty_object(&jbl);
726 CU_ASSERT_EQUAL_FATAL(rc, 0);
727
728 rc = jbl_create_empty_object(&nested);
729 CU_ASSERT_EQUAL_FATAL(rc, 0);
730
731 rc = jbl_set_int64(nested, "nnum", 2233);
732 CU_ASSERT_EQUAL_FATAL(rc, 0);
733
734 rc = jbl_set_int64(jbl, "mynum", 13223);
735 CU_ASSERT_EQUAL_FATAL(rc, 0);
736
737 rc = jbl_set_string(jbl, "foo", "bar");
738 CU_ASSERT_EQUAL_FATAL(rc, 0);
739
740 rc = jbl_set_nested(jbl, "nested", nested);
741 CU_ASSERT_EQUAL_FATAL(rc, 0);
742
743 rc = jbl_at(jbl, "/mynum", &at);
744 CU_ASSERT_EQUAL_FATAL(rc, 0);
745 CU_ASSERT_PTR_NOT_NULL_FATAL(at);
746 CU_ASSERT_EQUAL(jbl_get_i64(at), 13223);
747 jbl_destroy(&at);
748
749 rc = jbl_at(jbl, "/foo", &at);
750 CU_ASSERT_EQUAL_FATAL(rc, 0);
751 CU_ASSERT_PTR_NOT_NULL_FATAL(at);
752 CU_ASSERT_STRING_EQUAL(jbl_get_str(at), "bar");
753 jbl_destroy(&at);
754
755 rc = jbl_at(jbl, "/nested/nnum", &at);
756 CU_ASSERT_EQUAL_FATAL(rc, 0);
757 CU_ASSERT_PTR_NOT_NULL_FATAL(at);
758 CU_ASSERT_EQUAL(jbl_get_i64(at), 2233);
759 jbl_destroy(&at);
760
761 jbl_destroy(&jbl);
762 jbl_destroy(&nested);
763 }
764
jbl_test1_9(void)765 void jbl_test1_9(void) {
766 IWPOOL *pool = iwpool_create(512);
767 IWPOOL *cpool = iwpool_create(512);
768 CU_ASSERT_PTR_NOT_NULL_FATAL(pool);
769 CU_ASSERT_PTR_NOT_NULL_FATAL(cpool);
770 const char *data = "{\"foo\": \"b\\\"ar\", \"num1\":1223,"
771 "\"n\\\"um2\":10.1226222, "
772 "\"list\":[3,2.1,1,\"one\" \"two\", "
773 "{}, {\"z\":false, \"arr\":[9,8], \"t\":true}]}";
774
775 JBL_NODE n, cn;
776 iwrc rc = jbn_from_json(data, &n, pool);
777 CU_ASSERT_EQUAL_FATAL(rc, 0);
778
779 rc = jbn_clone(n, &cn, cpool);
780 CU_ASSERT_EQUAL_FATAL(rc, 0);
781
782 IWXSTR *xstr = iwxstr_new();
783 CU_ASSERT_PTR_NOT_NULL_FATAL(xstr);
784
785 iwpool_destroy(pool);
786
787 rc = jbn_as_json(cn, jbl_xstr_json_printer, xstr, 0);
788 CU_ASSERT_EQUAL_FATAL(rc, 0);
789
790 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(
791 xstr),
792 "{\"foo\":\"b\\\"ar\",\"num1\":1223,\"n\\\"um2\":10.1226222,\"list\":[3,2.1,1,\"one\",\"two\",{},{\"z\":false,\"arr\":[9,8],\"t\":true}]}"
793 );
794
795 iwpool_destroy(cpool);
796 iwxstr_destroy(xstr);
797 }
798
jbl_test1_10(void)799 void jbl_test1_10(void) {
800 IWPOOL *pool = iwpool_create(512);
801 IWPOOL *tpool = iwpool_create(512);
802 IWXSTR *xstr = iwxstr_new();
803
804 const char *src_data = "{\"foo\": \"b\\\"ar\", \"num1\":1223,"
805 "\"n\\\"um2\":10.1226222, "
806 "\"list\":[3,2.1,1,\"one\" \"two\", "
807 "{}, {\"z\":false, \"arr\":[9,8], \"t\":true}]}";
808 const char *tgt_data = "{\"test\":{\"nested1\":22}}";
809 JBL_NODE n1, n2;
810 iwrc rc = jbn_from_json(src_data, &n1, pool);
811 CU_ASSERT_EQUAL_FATAL(rc, 0);
812
813 rc = jbn_from_json(tgt_data, &n2, tpool);
814 CU_ASSERT_EQUAL_FATAL(rc, 0);
815
816 rc = jbn_copy_path(n1, "/list/6/arr", n2, "/test/nested1", false, false, tpool);
817 CU_ASSERT_EQUAL_FATAL(rc, 0);
818
819 rc = jbn_copy_path(n1, "/list/6/t", n2, "/test/t2", false, false, tpool);
820 CU_ASSERT_EQUAL_FATAL(rc, 0);
821
822 rc = jbn_copy_path(n1, "/foo", n2, "/bar", false, false, tpool);
823 CU_ASSERT_EQUAL_FATAL(rc, 0);
824
825 iwpool_destroy(pool);
826
827 rc = jbn_as_json(n2, jbl_xstr_json_printer, xstr, 0);
828 CU_ASSERT_EQUAL_FATAL(rc, 0);
829
830 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr),
831 "{\"test\":{\"nested1\":[9,8],\"t2\":true},\"bar\":\"b\\\"ar\"}");
832
833 iwpool_destroy(tpool);
834 iwxstr_destroy(xstr);
835 }
836
jbl_test1_11(void)837 void jbl_test1_11(void) {
838 IWPOOL *pool = iwpool_create(512);
839 IWXSTR *xstr = iwxstr_new();
840
841 const char *src_data = "{\"foo\": \"b\\\"ar\", \"num1\":1223,"
842 "\"n\\\"um2\":10.1226222, "
843 "\"list\":[3,2.1,1,\"one\" \"two\", "
844 "{}, {\"z\":false, \"arr\":[9,8], \"t\":true}]}";
845 const char *tgt_data = "{\"test\":{\"nested1\":22}, \"list\":[0,99]}";
846
847 JBL_NODE n1, n2;
848 iwrc rc = jbn_from_json(src_data, &n1, pool);
849 CU_ASSERT_EQUAL_FATAL(rc, 0);
850
851 rc = jbn_from_json(tgt_data, &n2, pool);
852 CU_ASSERT_EQUAL_FATAL(rc, 0);
853
854 const char *paths[] = { "/foo", "/list/1", 0 };
855 rc = jbn_copy_paths(n1, n2, paths, false, false, pool);
856 CU_ASSERT_EQUAL_FATAL(rc, 0);
857
858 rc = jbn_as_json(n2, jbl_xstr_json_printer, xstr, 0);
859 CU_ASSERT_EQUAL_FATAL(rc, 0);
860
861 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr),
862 "{\"test\":{\"nested1\":22},\"list\":[0,2.1],\"foo\":\"b\\\"ar\"}");
863
864 iwpool_destroy(pool);
865 iwxstr_destroy(xstr);
866 }
867
jbl_test1_12(void)868 void jbl_test1_12(void) {
869 }
870
main()871 int main() {
872 CU_pSuite pSuite = NULL;
873 if (CUE_SUCCESS != CU_initialize_registry()) {
874 return CU_get_error();
875 }
876 pSuite = CU_add_suite("jbl_test1", init_suite, clean_suite);
877 if (NULL == pSuite) {
878 CU_cleanup_registry();
879 return CU_get_error();
880 }
881 if ( (NULL == CU_add_test(pSuite, "jbl_test1_1", jbl_test1_1))
882 || (NULL == CU_add_test(pSuite, "jbl_test1_2", jbl_test1_2))
883 || (NULL == CU_add_test(pSuite, "jbl_test1_3", jbl_test1_3))
884 || (NULL == CU_add_test(pSuite, "jbl_test1_4", jbl_test1_4))
885 || (NULL == CU_add_test(pSuite, "jbl_test1_5", jbl_test1_5))
886 || (NULL == CU_add_test(pSuite, "jbl_test1_6", jbl_test1_6))
887 || (NULL == CU_add_test(pSuite, "jbl_test1_7", jbl_test1_7))
888 || (NULL == CU_add_test(pSuite, "jbl_test1_8", jbl_test1_8))
889 || (NULL == CU_add_test(pSuite, "jbl_test1_9", jbl_test1_9))
890 || (NULL == CU_add_test(pSuite, "jbl_test1_10", jbl_test1_10))
891 || (NULL == CU_add_test(pSuite, "jbl_test1_11", jbl_test1_11))) {
892 CU_cleanup_registry();
893 return CU_get_error();
894 }
895 CU_basic_set_mode(CU_BRM_VERBOSE);
896 CU_basic_run_tests();
897 int ret = CU_get_error() || CU_get_number_of_failures();
898 CU_cleanup_registry();
899 return ret;
900 }
901