unit_test.c 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058
  1. /*
  2. * Copyright (c) 2004-2013 Sergey Lyubka <[email protected]>
  3. * Copyright (c) 2013 Cesanta Software Limited
  4. * All rights reserved
  5. *
  6. * This library is dual-licensed: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation. For the terms of this
  9. * license, see <http: *www.gnu.org/licenses/>.
  10. *
  11. * You are free to use this library under the terms of the GNU General
  12. * Public License, but WITHOUT ANY WARRANTY; without even the implied
  13. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. * See the GNU General Public License for more details.
  15. *
  16. * Alternatively, you can license this library under a commercial
  17. * license, as set out in <http://cesanta.com/products.html>.
  18. */
  19. /*
  20. * To unit test on Mac system, do
  21. *
  22. * g++ unit_test.c -o unit_test -W -Wall -g -O0 -fprofile-arcs -ftest-coverage
  23. * clang unit_test.c -o unit_test -W -Wall -g -O0 -fprofile-arcs -ftest-coverage
  24. * ./unit_test
  25. * gcov -a unit_test.c
  26. */
  27. #include "frozen.c"
  28. #include <float.h>
  29. #include <math.h>
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. const char *tok_type_names[] = {
  34. "INVALID", "STRING", "NUMBER", "TRUE", "FALSE",
  35. "NULL", "OBJECT_START", "OBJECT_END", "ARRAY_START", "ARRAY_END",
  36. };
  37. #define FAIL(str, line) \
  38. do { \
  39. fprintf(stderr, "Fail on line %d: [%s]\n", line, str); \
  40. return str; \
  41. } while (0)
  42. #define ASSERT(expr) \
  43. do { \
  44. static_num_tests++; \
  45. if (!(expr)) FAIL(#expr, __LINE__); \
  46. } while (0)
  47. #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
  48. #define RUN_TEST(test) \
  49. do { \
  50. const char *msg = test(); \
  51. if (msg) return msg; \
  52. } while (0)
  53. static int static_num_tests = 0;
  54. static const char *test_errors(void) {
  55. /* clang-format off */
  56. static const char *invalid_tests[] = {
  57. "p", "a:3", "\x01", "{:",
  58. " { 1", "{a:\"\n\"}", "{a:1x}", "{a:1e}",
  59. "{a:.1}", "{a:0.}", "{a:0.e}", "{a:0.e1}",
  60. "{a:0.1e}", "{a:\"\\u\" } ", "{a:\"\\yx\"}", "{a:\"\\u111r\"}",
  61. NULL};
  62. static const char *incomplete_tests[] = {"",
  63. " \r\n\t",
  64. "{",
  65. " { a",
  66. "{a:",
  67. "{a:\"",
  68. " { a : \"xx",
  69. "{a:12",
  70. "{a:\"\\uf",
  71. "{a:\"\\uff",
  72. "{a:\"\\ufff",
  73. "{a:\"\\uffff",
  74. "{a:\"\\uffff\"",
  75. "{a:\"\\uffff\" ,",
  76. "{a:n",
  77. "{a:nu",
  78. "{a:nul",
  79. "{a:null",
  80. NULL};
  81. /* clang-format on */
  82. static const struct {
  83. const char *str;
  84. int expected_len;
  85. } success_tests[] = {{"{}", 2},
  86. /* 2, 3, 4 byte utf-8 chars */
  87. {"{a:\"\xd0\xb1\xe3\x81\xaf\xf0\xa2\xb3\x82\"}", 15},
  88. {"{a:\"\\u0006\"}", 12},
  89. {" { } ", 4},
  90. {"{a:1}", 5},
  91. {"{a:1.23}", 8},
  92. {"{a:1e23}", 8},
  93. {"{a:1.23e2}", 10},
  94. {"{a:-123}", 8},
  95. {"{a:-1.3}", 8},
  96. {"{a:-1.3e-2}", 11},
  97. {"{a:\"\"}", 6},
  98. {"{a:\" \\n\\t\\r\"}", 13},
  99. {" {a:[1]} 123456", 8},
  100. {" {a:[]} 123456", 7},
  101. {" {a:[1,2]} 123456", 10},
  102. {"{a:1,b:2} xxxx", 9},
  103. {"{a:1,b:{},c:[{}]} xxxx", 17},
  104. {"{a:true,b:[false,null]} xxxx", 23},
  105. {"[1.23, 3, 5]", 12},
  106. {"[13, {\"a\":\"hi there\"}, 5]", 25},
  107. {NULL, 0}};
  108. const char *s1 =
  109. " { a: 1, b: \"hi there\", c: true, d: false, "
  110. " e : null, f: [ 1, -2, 3], g: { \"1\": [], h: [ 7 ] } } ";
  111. int i;
  112. ASSERT(json_walk(NULL, 0, NULL, 0) == JSON_STRING_INVALID);
  113. for (i = 0; invalid_tests[i] != NULL; i++) {
  114. ASSERT(json_walk(invalid_tests[i], strlen(invalid_tests[i]), NULL, NULL) ==
  115. JSON_STRING_INVALID);
  116. }
  117. for (i = 0; incomplete_tests[i] != NULL; i++) {
  118. ASSERT(json_walk(incomplete_tests[i], strlen(incomplete_tests[i]), NULL,
  119. NULL) == JSON_STRING_INCOMPLETE);
  120. }
  121. for (i = 0; success_tests[i].str != NULL; i++) {
  122. ASSERT(json_walk(success_tests[i].str, strlen(success_tests[i].str), NULL,
  123. NULL) == success_tests[i].expected_len);
  124. }
  125. ASSERT(json_walk("{}", 2, NULL, NULL) == 2);
  126. ASSERT(json_walk(s1, strlen(s1), NULL, 0) > 0);
  127. return NULL;
  128. }
  129. struct my_struct {
  130. int a, b;
  131. };
  132. static int print_my_struct(struct json_out *out, va_list *ap) {
  133. struct my_struct *p = va_arg(*ap, struct my_struct *);
  134. return json_printf(out, "{a: %d, b: %d}", p->a, p->b);
  135. }
  136. static const char *test_json_printf(void) {
  137. char buf[200] = "";
  138. {
  139. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  140. const char *result = "42 42";
  141. json_printf(&out, "%ld %d", 42, 42);
  142. ASSERT(strcmp(buf, result) == 0);
  143. }
  144. /* platform specific compatibility where it matters */
  145. {
  146. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  147. const char *result = "16045690985373621933 42";
  148. json_printf(&out, "%" UINT64_FMT " %d", 0xdeadbeeffee1deadUL, 42);
  149. ASSERT(strcmp(buf, result) == 0);
  150. }
  151. {
  152. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  153. const char *result = "12 42";
  154. size_t foo = 12;
  155. json_printf(&out, "%lu %d", foo, 42);
  156. ASSERT(strcmp(buf, result) == 0);
  157. }
  158. /* people live in the future today, %llu works even on recent windozes */
  159. {
  160. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  161. const char *result = "16045690985373621933 42";
  162. json_printf(&out, "%llu %d", 0xdeadbeeffee1deadUL, 42);
  163. ASSERT(strcmp(buf, result) == 0);
  164. }
  165. {
  166. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  167. const char *result = "12 42";
  168. size_t foo = 12;
  169. json_printf(&out, "%zu %d", foo, 42);
  170. ASSERT(strcmp(buf, result) == 0);
  171. }
  172. {
  173. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  174. const char *result = "{\"foo\": 123, \"x\": [false, true], \"y\": \"hi\"}";
  175. json_printf(&out, "{%Q: %d, x: [%B, %B], y: %Q}", "foo", 123, 0, -1, "hi");
  176. ASSERT(strcmp(buf, result) == 0);
  177. }
  178. {
  179. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  180. int arr[] = {-2387, 943478};
  181. json_printf(&out, "%M", json_printf_array, arr, sizeof(arr), sizeof(arr[0]),
  182. "%d");
  183. ASSERT(strcmp(buf, "[-2387, 943478]") == 0);
  184. }
  185. {
  186. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  187. double arr[] = {9.32156, 3.1415926};
  188. json_printf(&out, "%M", json_printf_array, arr, sizeof(arr), sizeof(arr[0]),
  189. "%.2lf");
  190. ASSERT(strcmp(buf, "[9.32, 3.14]") == 0);
  191. }
  192. {
  193. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  194. unsigned short arr[] = {65535, 777};
  195. const char *result = "{\"a\": [-1, 777], \"b\": 37}";
  196. json_printf(&out, "{a: %M, b: %d}", json_printf_array, arr, sizeof(arr),
  197. sizeof(arr[0]), "%hd", 37);
  198. ASSERT(strcmp(buf, result) == 0);
  199. }
  200. {
  201. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  202. const char *arr[] = {"hi", "there", NULL};
  203. const char *result = "[\"hi\", \"there\", null]";
  204. json_printf(&out, "%M", json_printf_array, arr, sizeof(arr), sizeof(arr[0]),
  205. "%Q");
  206. ASSERT(strcmp(buf, result) == 0);
  207. }
  208. {
  209. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  210. const char *result = "{\"a\": \"\\\"\\\\\\r\\nя\\t\\u0002\"}";
  211. json_printf(&out, "{a: %Q}", "\"\\\r\nя\t\x02");
  212. ASSERT(strcmp(buf, result) == 0);
  213. }
  214. {
  215. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  216. struct my_struct mys = {1, 2};
  217. const char *result = "{\"foo\": {\"a\": 1, \"b\": 2}, \"bar\": 3}";
  218. json_printf(&out, "{foo: %M, bar: %d}", print_my_struct, &mys, 3);
  219. ASSERT(strcmp(buf, result) == 0);
  220. }
  221. {
  222. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  223. out.u.buf.size = 3;
  224. memset(buf, 0, sizeof(buf));
  225. ASSERT(json_printf(&out, "{%d}", 123) == 5);
  226. ASSERT(memcmp(buf, "{1\x00\x00\x00", 5) == 0);
  227. }
  228. {
  229. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  230. const char *result = "\"foo\"";
  231. out.u.buf.size = 6;
  232. memset(buf, 0, sizeof(buf));
  233. ASSERT(json_printf(&out, "%.*Q", 3, "foobar") == 5);
  234. ASSERT(memcmp(buf, result, 5) == 0);
  235. }
  236. {
  237. /*
  238. * Check long string (which forces frozen to allocate a temporary buffer
  239. * from heap)
  240. */
  241. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  242. const char *result =
  243. "{\"foo\": "
  244. "\"12345678901234567890123456789012345678901234567890123456789012345678"
  245. "90123456789012345678901234567890\"}";
  246. const char *s =
  247. "\"123456789012345678901234567890123456789012345678901234567890"
  248. "1234567890123456789012345678901234567890\"";
  249. json_printf(&out, "{foo: %s}", s);
  250. ASSERT(strcmp(buf, result) == 0);
  251. }
  252. {
  253. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  254. const char *fmt = "{a: \"%s\"}", *result = "{\"a\": \"b\"}";
  255. memset(buf, 0, sizeof(buf));
  256. ASSERT(json_printf(&out, fmt, "b") > 0);
  257. ASSERT(strcmp(buf, result) == 0);
  258. }
  259. {
  260. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  261. memset(buf, 0, sizeof(buf));
  262. ASSERT(json_printf(&out, "%.*s %d", 2, "abc", 5) > 0);
  263. ASSERT(strcmp(buf, "ab 5") == 0);
  264. }
  265. {
  266. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  267. const char *result = "\"a_b0\": 1";
  268. memset(buf, 0, sizeof(buf));
  269. ASSERT(json_printf(&out, "a_b0: %d", 1) > 0);
  270. ASSERT(strcmp(buf, result) == 0);
  271. }
  272. #if JSON_ENABLE_BASE64
  273. {
  274. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  275. const char *result = "\"YTI=\"";
  276. memset(buf, 0, sizeof(buf));
  277. ASSERT(json_printf(&out, "%V", "a2", 2) > 0);
  278. ASSERT(strcmp(buf, result) == 0);
  279. }
  280. {
  281. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  282. const char *result = "\"ACABIAIgYWJj\"";
  283. memset(buf, 0, sizeof(buf));
  284. ASSERT(json_printf(&out, "%V", "\x00 \x01 \x02 abc", 9) > 0);
  285. ASSERT(strcmp(buf, result) == 0);
  286. }
  287. #endif /* JSON_ENABLE_BASE64 */
  288. #if JSON_ENABLE_HEX
  289. {
  290. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  291. const char *result = "\"002001200220616263\"";
  292. memset(buf, 0, sizeof(buf));
  293. ASSERT(json_printf(&out, "%H", 9, "\x00 \x01 \x02 abc") > 0);
  294. ASSERT(strcmp(buf, result) == 0);
  295. }
  296. #endif /* JSON_ENABLE_HEX */
  297. {
  298. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  299. memset(buf, 0, sizeof(buf));
  300. ASSERT(json_printf(&out, "%c", 0x53) > 0);
  301. ASSERT(strcmp(buf, "S") == 0);
  302. }
  303. {
  304. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  305. const char *result = "<\"array\">0f";
  306. memset(buf, 0, sizeof(buf));
  307. ASSERT(json_printf(&out, "<array>%02x", 15) > 0);
  308. ASSERT(strcmp(buf, result) == 0);
  309. }
  310. {
  311. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  312. double arr[] = {9.32156, 3.1415926};
  313. #if !defined(_MSC_VER) || _MSC_VER >= 1700
  314. const char *result = "[9.32e+00, 3.14e+00]"; // Modern compilers
  315. #else
  316. const char *result = "[9.32e+000, 3.14e+000]"; // Old VC98 compiler
  317. #endif
  318. json_printf(&out, "%M", json_printf_array, arr, sizeof(arr), sizeof(arr[0]),
  319. "%.2e");
  320. ASSERT(strcmp(buf, result) == 0);
  321. }
  322. {
  323. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  324. double arr[] = {9.32156, 3.1415926};
  325. json_printf(&out, "%M", json_printf_array, arr, sizeof(arr), sizeof(arr[0]),
  326. "%.4g");
  327. ASSERT(strcmp(buf, "[9.322, 3.142]") == 0);
  328. }
  329. return NULL;
  330. }
  331. static const char *test_system(void) {
  332. char buf[2020];
  333. uint64_t u = (uint64_t) 0xdeadbeeffee1dead;
  334. int64_t d = (int64_t) u;
  335. int res;
  336. snprintf(buf, sizeof(buf), "%" UINT64_FMT, u);
  337. ASSERT(strcmp(buf, "16045690985373621933") == 0);
  338. snprintf(buf, sizeof(buf), "%" INT64_FMT, d);
  339. ASSERT(strcmp(buf, "-2401053088335929683") == 0);
  340. res = snprintf(buf, 3, "foo");
  341. ASSERT(res == 3);
  342. ASSERT(buf[0] == 'f');
  343. ASSERT(buf[1] == 'o');
  344. ASSERT(buf[2] == '\0');
  345. return NULL;
  346. }
  347. static void cb(void *data, const char *name, size_t name_len, const char *path,
  348. const struct json_token *token) {
  349. char *buf = (char *) data;
  350. const char *snull = "<null>";
  351. sprintf(buf + strlen(buf), "name:'%.*s', path:'%s', type:%s, val:'%.*s'\n",
  352. (int) (name != NULL ? name_len : strlen(snull)),
  353. name != NULL ? name : snull, path, tok_type_names[token->type],
  354. (int) (token->ptr != NULL ? token->len : (int) strlen(snull)),
  355. token->ptr != NULL ? token->ptr : snull);
  356. }
  357. static const char *test_callback_api(void) {
  358. const char *s =
  359. "{\"c\":[\"foo\", \"bar\", {\"a\":9, \"b\": \"x\"}], "
  360. "\"mynull\": null, \"mytrue\": true, \"myfalse\": false}";
  361. const char *result =
  362. "name:'<null>', path:'', type:OBJECT_START, val:'<null>'\n"
  363. "name:'c', path:'.c', type:ARRAY_START, val:'<null>'\n"
  364. "name:'0', path:'.c[0]', type:STRING, val:'foo'\n"
  365. "name:'1', path:'.c[1]', type:STRING, val:'bar'\n"
  366. "name:'2', path:'.c[2]', type:OBJECT_START, val:'<null>'\n"
  367. "name:'a', path:'.c[2].a', type:NUMBER, val:'9'\n"
  368. "name:'b', path:'.c[2].b', type:STRING, val:'x'\n"
  369. "name:'<null>', path:'.c[2]', type:OBJECT_END, val:'{\"a\":9, \"b\": "
  370. "\"x\"}'\n"
  371. "name:'<null>', path:'.c', type:ARRAY_END, val:'[\"foo\", \"bar\", "
  372. "{\"a\":9, \"b\": \"x\"}]'\n"
  373. "name:'mynull', path:'.mynull', type:NULL, val:'null'\n"
  374. "name:'mytrue', path:'.mytrue', type:TRUE, val:'true'\n"
  375. "name:'myfalse', path:'.myfalse', type:FALSE, val:'false'\n"
  376. "name:'<null>', path:'', type:OBJECT_END, val:'{\"c\":[\"foo\", \"bar\", "
  377. "{\"a\":9, \"b\": \"x\"}], \"mynull\": null, \"mytrue\": true, "
  378. "\"myfalse\": false}'\n";
  379. char buf[4096] = "";
  380. ASSERT(json_walk(s, strlen(s), cb, buf) == (int) strlen(s));
  381. ASSERT(strcmp(buf, result) == 0);
  382. return NULL;
  383. }
  384. /*
  385. * Tests with the path which is longer than JSON_MAX_PATH_LEN (at the moment,
  386. * 60)
  387. */
  388. static const char *test_callback_api_long_path(void) {
  389. const char *s =
  390. "{\"MyWZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
  391. "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
  392. "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
  393. "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
  394. "ZZZZZZZZZZZZZZZZZvf\": {}, \"jYP-27917287424p\": {}}";
  395. const char *result =
  396. "name:'<null>', path:'', type:OBJECT_START, val:'<null>'\n"
  397. "name:'"
  398. "MyWZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
  399. "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
  400. "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
  401. "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZvf', "
  402. "path:'."
  403. "MyWZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
  404. "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
  405. "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
  406. "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ', "
  407. "type:OBJECT_START, val:'<null>'\n"
  408. "name:'<null>', "
  409. "path:'."
  410. "MyWZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
  411. "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
  412. "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
  413. "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ', "
  414. "type:OBJECT_END, val:'{}'\n"
  415. "name:'jYP-27917287424p', path:'.jYP-27917287424p', type:OBJECT_START, "
  416. "val:'<null>'\n"
  417. "name:'<null>', path:'.jYP-27917287424p', type:OBJECT_END, val:'{}'\n"
  418. "name:'<null>', path:'', type:OBJECT_END, "
  419. "val:'{"
  420. "\"MyWZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
  421. "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
  422. "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
  423. "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
  424. "ZZZZZZZZZZZZZZZZvf\": {}, \"jYP-27917287424p\": {}}'\n";
  425. char buf[4096] = "";
  426. ASSERT(json_walk(s, strlen(s), cb, buf) == (int) strlen(s));
  427. ASSERT(strcmp(buf, result) == 0);
  428. return NULL;
  429. }
  430. static void scan_array(const char *str, int len, void *user_data) {
  431. struct json_token t;
  432. int i;
  433. char *buf = (char *) user_data;
  434. for (i = 0; json_scanf_array_elem(str, len, ".x", i, &t) > 0; i++) {
  435. sprintf(buf + strlen(buf), "%d[%.*s] ", i, t.len, t.ptr);
  436. }
  437. }
  438. static const char *test_scanf(void) {
  439. char buf[100] = "";
  440. int a = 0, b = 0;
  441. char *d = NULL;
  442. const char *str =
  443. "{ a: 1234, b : true, \"c\": {x: [17, 78, -20]}, d: \"hi%20there\" }";
  444. ASSERT(json_scanf(str, strlen(str), "{a: %d, b: %B, c: [%M], d: %Q}", &a, &b,
  445. &scan_array, buf, &d) == 4);
  446. ASSERT(a == 1234);
  447. ASSERT(b == 1);
  448. ASSERT(strcmp(buf, "0[17] 1[78] 2[-20] ") == 0);
  449. ASSERT(d != NULL);
  450. ASSERT(strcmp(d, "hi%20there") == 0);
  451. free(d);
  452. {
  453. /* Test errors */
  454. const char *str = "{foo:1, bar:[2,3,4]}";
  455. size_t i;
  456. ASSERT(json_walk(str, strlen(str), NULL, NULL) == (int) strlen(str));
  457. for (i = 1; i < strlen(str); i++) {
  458. ASSERT(json_walk(str, i, NULL, NULL) == JSON_STRING_INCOMPLETE);
  459. }
  460. }
  461. {
  462. /* Test that paths are utf8 */
  463. const char *str = "{\"ы\": 123}";
  464. int x = 0;
  465. ASSERT(json_scanf(str, strlen(str), "{ы: %d}", &x) == 1);
  466. ASSERT(x == 123);
  467. }
  468. {
  469. /* Test that paths are utf8 */
  470. const char *str = "{a: 123, b: [1,2,3]}";
  471. struct json_token t;
  472. memset(&t, 0, sizeof(t));
  473. ASSERT(json_scanf(str, strlen(str), "{b: %T}", &t) == 1);
  474. ASSERT(t.type == JSON_TYPE_ARRAY_END);
  475. ASSERT(t.len == 7);
  476. ASSERT(strncmp(t.ptr, "[1,2,3]", t.len) == 0);
  477. }
  478. {
  479. /* Test zero termination */
  480. char *s = NULL;
  481. const char *str = "{a: \"foo\", b:123}";
  482. ASSERT(json_scanf(str, strlen(str), "{a: %Q}", &s) == 1);
  483. ASSERT(s != NULL);
  484. ASSERT(s[3] == '\0');
  485. free(s);
  486. }
  487. {
  488. /* Test for scalar value being a root element */
  489. int n = 0;
  490. const char *str = " true ";
  491. ASSERT(json_scanf(str, strlen(str), " %B ", &n) == 1);
  492. ASSERT(n == 1);
  493. }
  494. {
  495. /* Test array of objects */
  496. const char *str = " { \"a\": [ {\"b\": 123}, {\"b\": 345} ]} ";
  497. int i, value, len = strlen(str), values[] = {123, 345};
  498. struct json_token t;
  499. /* Scan each array element into a token */
  500. for (i = 0; json_scanf_array_elem(str, len, ".a", i, &t) > 0; i++) {
  501. /* Now scan each token */
  502. ASSERT(t.type == JSON_TYPE_OBJECT_END);
  503. ASSERT(json_scanf(t.ptr, t.len, "{b: %d}", &value) == 1);
  504. ASSERT((size_t) i < sizeof(values) / sizeof(values[0]));
  505. ASSERT(values[i] == value);
  506. }
  507. ASSERT(i == 2);
  508. }
  509. {
  510. const char *str = "{a : [\"foo\", \"\", \"a\"] }";
  511. struct json_token t;
  512. ASSERT(json_scanf_array_elem(str, strlen(str), ".a", 0, &t) == 3);
  513. ASSERT(json_scanf_array_elem(str, strlen(str), ".a", 1, &t) == 0);
  514. ASSERT(json_scanf_array_elem(str, strlen(str), ".a", 2, &t) == 1);
  515. ASSERT(json_scanf_array_elem(str, strlen(str), ".a", 3, &t) == -1);
  516. }
  517. {
  518. const char *str = "{a : \"foo\\b\\f\\n\\r\\t\\\\\" }";
  519. char *result;
  520. ASSERT(json_scanf(str, strlen(str), "{a: %Q}", &result) == 1);
  521. ASSERT(strcmp(result, "foo\b\f\n\r\t\\") == 0);
  522. free(result);
  523. ASSERT(json_scanf(str, 9, "{a: %Q}", &result) == 0);
  524. }
  525. {
  526. const char *str = "{a : \"привет\" }";
  527. char *result;
  528. ASSERT(json_scanf(str, strlen(str), "{a: %Q}", &result) == 1);
  529. ASSERT(strcmp(result, "привет") == 0);
  530. free(result);
  531. }
  532. #if JSON_ENABLE_BASE64
  533. {
  534. const char *str = "{a : \"YTI=\" }";
  535. int len;
  536. char *result;
  537. ASSERT(json_scanf(str, strlen(str), "{a: %V}", &result, &len) == 1);
  538. ASSERT(len == 2);
  539. ASSERT(strcmp(result, "a2") == 0);
  540. free(result);
  541. }
  542. {
  543. const char *str = "{a : \"0L/RgNC40LLQtdGC0Ys=\" }";
  544. int len;
  545. char *result;
  546. ASSERT(json_scanf(str, strlen(str), "{a: %V}", &result, &len) == 1);
  547. ASSERT(len == 14);
  548. ASSERT(strcmp(result, "приветы") == 0);
  549. free(result);
  550. }
  551. #endif /* JSON_ENABLE_BASE64 */
  552. #if JSON_ENABLE_HEX
  553. {
  554. const char *str = "{a : \"61626320\" }";
  555. int len = 0;
  556. char *result = NULL;
  557. ASSERT(json_scanf(str, strlen(str), "{a: %H}", &len, &result) == 1);
  558. ASSERT(len == 4);
  559. ASSERT(strcmp(result, "abc ") == 0);
  560. free(result);
  561. }
  562. #endif /* JSON_ENABLE_HEX */
  563. {
  564. const char *str = "{a : null }";
  565. char *result = (char *) 123;
  566. ASSERT(json_scanf(str, strlen(str), "{a: %Q}", &result) == 0);
  567. ASSERT(result == NULL);
  568. free(result);
  569. }
  570. {
  571. int a = 0;
  572. bool b = false;
  573. int c = 0xFFFFFFFF;
  574. const char *str = "{\"b\":true,\"c\":false,\"a\":2}";
  575. ASSERT(json_scanf(str, strlen(str), "{a:%d, b:%B, c:%B}", &a, &b, &c) == 3);
  576. ASSERT(a == 2);
  577. ASSERT(b == true);
  578. if (sizeof(bool) == 1) {
  579. ASSERT((char) c == false);
  580. } else {
  581. ASSERT(c == false);
  582. }
  583. }
  584. {
  585. const char *str = "{ fa: 1, fb: 2.34, fc: 5.67 }";
  586. const char *fmt = "{fa: %f, fb: %f, fc: %lf}";
  587. float fa = 0.0, fb = 0.0;
  588. double fc = 0.0;
  589. #if !JSON_MINIMAL
  590. float a = 1.0f, b = 2.34f;
  591. double c = 5.67;
  592. ASSERT(json_scanf(str, strlen(str), fmt, &fa, &fb, &fc) == 3);
  593. ASSERT(fa == a);
  594. ASSERT(fb == b);
  595. ASSERT(fabs(fc - c) < FLT_EPSILON);
  596. #else
  597. ASSERT(json_scanf(str, strlen(str), fmt, &fa, &fb, &fc) == 0);
  598. #endif
  599. }
  600. {
  601. int v = -1;
  602. long lv = -1;
  603. const char *s = "{\"v\": 0x12, \"lv\": 0x34}";
  604. ASSERT(json_scanf("0x", 2, "%i", &v) == 0); // Incomplete string
  605. ASSERT(json_scanf("0xe", 3, "%i", &v) == 1);
  606. ASSERT(v == 0xe);
  607. ASSERT(json_scanf("12", 2, "%i", &v) == 1);
  608. ASSERT(v == 12);
  609. // %d and %ld accept hex
  610. ASSERT(json_scanf(s, strlen(s), "{lv:%ld, v:%d}", &lv, &v) == 2);
  611. ASSERT(v == 0x12);
  612. ASSERT(lv == 0x34);
  613. }
  614. {
  615. unsigned int v = 0;
  616. unsigned long lv = 0;
  617. const char *s = "{\"v\": 0x12, \"lv\": 0x34}";
  618. // %u and %lu accept hex
  619. ASSERT(json_scanf(s, strlen(s), "{lv:%lu, v:%u}", &lv, &v) == 2);
  620. ASSERT(v == 0x12);
  621. ASSERT(lv == 0x34);
  622. }
  623. return NULL;
  624. }
  625. static const char *test_json_unescape(void) {
  626. char buf[1];
  627. ASSERT(json_unescape("foo", 3, NULL, 0) == 3);
  628. ASSERT(json_unescape("foo\\", 4, NULL, 0) == JSON_STRING_INCOMPLETE);
  629. ASSERT(json_unescape("foo\\x", 5, NULL, 0) == JSON_STRING_INVALID);
  630. ASSERT(json_unescape("\\ueeee", 5, NULL, 0) == JSON_STRING_INCOMPLETE);
  631. ASSERT(json_unescape("\\ueeee", 6, NULL, 0) == JSON_STRING_INVALID);
  632. // Simple one-byte escapes should work
  633. ASSERT(json_unescape("\\u0026", 2, NULL, 0) == JSON_STRING_INCOMPLETE);
  634. ASSERT(json_unescape("\\u0026", 3, NULL, 0) == JSON_STRING_INCOMPLETE);
  635. ASSERT(json_unescape("\\u0026", 4, NULL, 0) == JSON_STRING_INCOMPLETE);
  636. ASSERT(json_unescape("\\u0026", 5, NULL, 0) == JSON_STRING_INCOMPLETE);
  637. ASSERT(json_unescape("\\u0026", 6, buf, sizeof(buf)) == 1);
  638. ASSERT(buf[0] == '&');
  639. return NULL;
  640. }
  641. static void cb2(void *data, const char *name, size_t name_len, const char *path,
  642. const struct json_token *token) {
  643. struct json_token *pt = (struct json_token *) data;
  644. pt->ptr = token->ptr;
  645. pt->len = token->len;
  646. (void) path;
  647. (void) name_len;
  648. (void) name;
  649. }
  650. static const char *test_parse_string(void) {
  651. const char *str = " \" foo\\bar\"";
  652. const int str_len = strlen(str);
  653. struct json_token t;
  654. struct frozen f;
  655. memset(&f, 0, sizeof(f));
  656. f.end = str + str_len;
  657. f.cur = str;
  658. f.callback_data = (void *) &t;
  659. f.callback = cb2;
  660. ASSERT(json_parse_string(&f) == 0);
  661. ASSERT(strncmp(t.ptr, " foo\\bar", t.len) == 0);
  662. return NULL;
  663. }
  664. static const char *test_eos(void) {
  665. const char *s = "{\"a\": 12345}";
  666. size_t n = 999;
  667. char *buf = (char *) malloc(n);
  668. int s_len = strlen(s), a = 0;
  669. ASSERT(buf != NULL);
  670. memset(buf, 'x', n);
  671. memcpy(buf, s, s_len);
  672. ASSERT(json_scanf(buf, n, "{a:%d}", &a) == 1);
  673. ASSERT(a == 12345);
  674. free(buf);
  675. return NULL;
  676. }
  677. static int compare_file(const char *file_name, const char *s) {
  678. int res = -1;
  679. char *p = json_fread(file_name);
  680. if (p == NULL) return res;
  681. res = strcmp(p, s);
  682. free(p);
  683. return res == 0;
  684. }
  685. static const char *test_fprintf(void) {
  686. const char *fname = "a.json";
  687. const char *result = "{\"a\":123}\n";
  688. char *p;
  689. ASSERT(json_fprintf(fname, "{a:%d}", 123) > 0);
  690. p = json_fread(fname);
  691. ASSERT(p != NULL);
  692. ASSERT(strcmp(p, result) == 0);
  693. free(p);
  694. remove(fname);
  695. ASSERT(json_fread(fname) == NULL);
  696. return NULL;
  697. }
  698. static const char *test_json_setf(void) {
  699. char buf[200];
  700. const char *s1 = "{ \"a\": 123, \"b\": [ 1 ], \"c\": true }";
  701. {
  702. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  703. const char *s2 = "{ \"a\": 7, \"b\": [ 1 ], \"c\": true }";
  704. int res = json_setf(s1, strlen(s1), &out, ".a", "%d", 7);
  705. ASSERT(res == 1);
  706. ASSERT(strcmp(buf, s2) == 0);
  707. }
  708. {
  709. /* Add Key with length > 1 */
  710. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  711. const char *s2 =
  712. "{ \"a\": 123, \"b\": [ 1 ], \"c\": true,\"foo\":{\"bar\":42} }";
  713. int res = json_setf(s1, strlen(s1), &out, ".foo.bar", "%d", 42);
  714. ASSERT(res == 0);
  715. ASSERT(strcmp(buf, s2) == 0);
  716. }
  717. {
  718. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  719. const char *s2 = "{ \"a\": 123, \"b\": false, \"c\": true }";
  720. int res = json_setf(s1, strlen(s1), &out, ".b", "%B", 0);
  721. ASSERT(res == 1);
  722. ASSERT(strcmp(buf, s2) == 0);
  723. }
  724. {
  725. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  726. const char *s2 = "{ \"a\": 123, \"b\": [ 2 ], \"c\": true }";
  727. int res = json_setf(s1, strlen(s1), &out, ".b[0]", "%d", 2);
  728. ASSERT(res == 1);
  729. ASSERT(strcmp(buf, s2) == 0);
  730. }
  731. {
  732. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  733. const char *s2 = "{ \"b\": [ 1 ], \"c\": true }";
  734. int res = json_setf(s1, strlen(s1), &out, ".a", NULL);
  735. ASSERT(res == 1);
  736. ASSERT(strcmp(buf, s2) == 0);
  737. }
  738. {
  739. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  740. const char *s2 = "{ \"a\": 123, \"b\": [ 1 ] }";
  741. int res = json_setf(s1, strlen(s1), &out, ".c", NULL);
  742. ASSERT(res == 1);
  743. ASSERT(strcmp(buf, s2) == 0);
  744. }
  745. {
  746. /* Delete non-existent key */
  747. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  748. const char *s1 = "{\"a\":1}";
  749. int res = json_setf(s1, strlen(s1), &out, ".d", NULL);
  750. ASSERT(res == 0);
  751. ASSERT(strcmp(buf, s1) == 0);
  752. }
  753. {
  754. /* Delete non-existent key, spaces in obj */
  755. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  756. int res = json_setf(s1, strlen(s1), &out, ".d", NULL);
  757. ASSERT(res == 0);
  758. ASSERT(strcmp(buf, s1) == 0);
  759. }
  760. {
  761. /* Change the whole JSON object */
  762. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  763. const char *s2 = "123";
  764. int res = json_setf(s1, strlen(s1), &out, "", "%d", 123);
  765. ASSERT(res == 1);
  766. ASSERT(strcmp(buf, s2) == 0);
  767. }
  768. {
  769. /* Add missing keys */
  770. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  771. const char *s2 =
  772. "{ \"a\": 123, \"b\": [ 1 ], \"c\": true,\"d\":{\"e\":8} }";
  773. int res = json_setf(s1, strlen(s1), &out, ".d.e", "%d", 8);
  774. ASSERT(res == 0);
  775. ASSERT(strcmp(buf, s2) == 0);
  776. }
  777. {
  778. /* Append to arrays */
  779. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  780. const char *s2 = "{ \"a\": 123, \"b\": [ 1,2 ], \"c\": true }";
  781. int res = json_setf(s1, strlen(s1), &out, ".b[]", "%d", 2);
  782. ASSERT(res == 0);
  783. ASSERT(strcmp(buf, s2) == 0);
  784. }
  785. {
  786. /* Delete from array */
  787. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  788. const char *s2 = "{ \"a\": 123, \"b\": [ ], \"c\": true }";
  789. int res = json_setf(s1, strlen(s1), &out, ".b[0]", NULL);
  790. ASSERT(res == 1);
  791. ASSERT(strcmp(buf, s2) == 0);
  792. }
  793. {
  794. /* Create array and push value */
  795. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  796. const char *s2 = "{ \"a\": 123, \"b\": [ 1 ], \"c\": true,\"d\":[3] }";
  797. int res = json_setf(s1, strlen(s1), &out, ".d[]", "%d", 3);
  798. // printf("[%s]\n[%s]\n", buf, s2);
  799. ASSERT(res == 0);
  800. ASSERT(strcmp(buf, s2) == 0);
  801. }
  802. return NULL;
  803. }
  804. static const char *test_prettify(void) {
  805. const char *fname = "a.json";
  806. char buf[200];
  807. {
  808. const char *s1 = "{ \"a\": 1, \"b\":2,\"c\":[null,\"aa\",{},true]}";
  809. struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
  810. const char *s2 =
  811. "{\n \"a\": 1,\n \"b\": 2,\n \"c\": [\n null,\n \"aa\",\n "
  812. "{},\n true\n ]\n}";
  813. ASSERT(json_prettify(s1, strlen(s1), &out) > 0);
  814. ASSERT(strcmp(buf, s2) == 0);
  815. }
  816. {
  817. remove(fname);
  818. ASSERT(json_prettify_file(fname) == -1);
  819. }
  820. {
  821. ASSERT(compare_file(fname, "") == -1);
  822. json_fprintf(fname, "::");
  823. ASSERT(json_prettify_file(fname) == JSON_STRING_INVALID);
  824. ASSERT(compare_file(fname, "::\n"));
  825. remove(fname);
  826. }
  827. {
  828. ASSERT(compare_file(fname, "") == -1);
  829. json_fprintf(fname, "{");
  830. ASSERT(json_prettify_file(fname) == JSON_STRING_INCOMPLETE);
  831. ASSERT(compare_file(fname, "{\n"));
  832. remove(fname);
  833. }
  834. {
  835. ASSERT(compare_file(fname, "") == -1);
  836. json_fprintf(fname, "%d", 123);
  837. ASSERT(compare_file(fname, "123\n"));
  838. ASSERT(json_prettify_file(fname) > 0);
  839. ASSERT(compare_file(fname, "123\n"));
  840. remove(fname);
  841. }
  842. {
  843. const char *s = "{\n \"a\": 123\n}\n";
  844. ASSERT(compare_file(fname, "") == -1);
  845. json_fprintf(fname, "{a:%d}", 123);
  846. ASSERT(json_prettify_file(fname) > 0);
  847. ASSERT(compare_file(fname, s));
  848. (void) remove(fname);
  849. }
  850. return NULL;
  851. }
  852. static const char *test_json_next(void) {
  853. struct json_token key, val;
  854. char buf[100];
  855. {
  856. /* Traverse an object */
  857. void *h = NULL;
  858. int i = 0;
  859. const char *s = "{ \"a\": [], \"b\": [ 1, {} ], \"c\": true }";
  860. int len = strlen(s);
  861. const char *results[] = {"[a] -> [[]]", "[b] -> [[ 1, {} ]]",
  862. "[c] -> [true]"};
  863. while ((h = json_next_key(s, len, h, "", &key, &val)) != NULL) {
  864. snprintf(buf, sizeof(buf), "[%.*s] -> [%.*s]", key.len, key.ptr, val.len,
  865. val.ptr);
  866. ASSERT(strcmp(results[i], buf) == 0);
  867. i++;
  868. }
  869. ASSERT(i == 3);
  870. }
  871. {
  872. /* Traverse an array */
  873. void *h = NULL;
  874. int i = 0, idx;
  875. const char *s = "{ \"a\": [], \"b\": [ 1, {} ], \"c\": true }";
  876. int len = strlen(s);
  877. const char *results[] = {"[0] -> [1]", "[1] -> [{}]"};
  878. while ((h = json_next_elem(s, len, h, ".b", &idx, &val)) != NULL) {
  879. snprintf(buf, sizeof(buf), "[%d] -> [%.*s]", idx, val.len, val.ptr);
  880. ASSERT(strcmp(results[i], buf) == 0);
  881. i++;
  882. }
  883. ASSERT(i == 2);
  884. }
  885. {
  886. /* Traverse more complex object */
  887. const char *s = "{ \"a\": 123, \"b\": { \"c\": true, \"d\": 1234 } }";
  888. void *h = NULL;
  889. int i = 0;
  890. int len = strlen(s);
  891. const char *results[] = {"[c] -> [true]", "[d] -> [1234]"};
  892. while ((h = json_next_key(s, len, h, ".b", &key, &val)) != NULL) {
  893. snprintf(buf, sizeof(buf), "[%.*s] -> [%.*s]", key.len, key.ptr, val.len,
  894. val.ptr);
  895. ASSERT(strcmp(results[i], buf) == 0);
  896. i++;
  897. }
  898. ASSERT(i == 2);
  899. }
  900. return NULL;
  901. }
  902. static const char *test_json_printf_hex(void) {
  903. char *s = json_asprintf("%H", 3, "abc");
  904. #if JSON_ENABLE_HEX
  905. const char *r = "\"616263\"";
  906. ASSERT(strcmp(s, r) == 0);
  907. #else
  908. ASSERT(s == NULL);
  909. #endif
  910. free(s);
  911. return NULL;
  912. }
  913. static const char *test_json_printf_base64(void) {
  914. char *s = json_asprintf("{a:%d,b:%V}", 77, "hi", 2);
  915. #if JSON_ENABLE_BASE64
  916. const char *r = "{\"a\":77,\"b\":\"aGk=\"}";
  917. #else
  918. const char *r = "{\"a\":77,\"b\":}";
  919. #endif
  920. ASSERT(strcmp(s, r) == 0);
  921. free(s);
  922. return NULL;
  923. }
  924. static const char *run_all_tests(void) {
  925. RUN_TEST(test_json_printf_hex);
  926. RUN_TEST(test_json_printf_base64);
  927. RUN_TEST(test_json_next);
  928. RUN_TEST(test_prettify);
  929. RUN_TEST(test_eos);
  930. RUN_TEST(test_scanf);
  931. RUN_TEST(test_errors);
  932. RUN_TEST(test_json_printf);
  933. RUN_TEST(test_system);
  934. RUN_TEST(test_callback_api);
  935. RUN_TEST(test_callback_api_long_path);
  936. RUN_TEST(test_json_unescape);
  937. RUN_TEST(test_parse_string);
  938. RUN_TEST(test_fprintf);
  939. RUN_TEST(test_json_setf);
  940. return NULL;
  941. }
  942. int main(void) {
  943. const char *fail_msg = run_all_tests();
  944. printf("%s, tests run: %d\n", fail_msg ? "FAIL" : "PASS", static_num_tests);
  945. return fail_msg == NULL ? EXIT_SUCCESS : EXIT_FAILURE;
  946. }