check-qjson.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795
  1. /*
  2. * Copyright IBM, Corp. 2009
  3. *
  4. * Authors:
  5. * Anthony Liguori <aliguori@us.ibm.com>
  6. *
  7. * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
  8. * See the COPYING.LIB file in the top-level directory.
  9. *
  10. */
  11. #include <check.h>
  12. #include "qstring.h"
  13. #include "qint.h"
  14. #include "qdict.h"
  15. #include "qlist.h"
  16. #include "qfloat.h"
  17. #include "qbool.h"
  18. #include "qjson.h"
  19. #include "qemu-common.h"
  20. START_TEST(escaped_string)
  21. {
  22. int i;
  23. struct {
  24. const char *encoded;
  25. const char *decoded;
  26. int skip;
  27. } test_cases[] = {
  28. { "\"\\b\"", "\b" },
  29. { "\"\\f\"", "\f" },
  30. { "\"\\n\"", "\n" },
  31. { "\"\\r\"", "\r" },
  32. { "\"\\t\"", "\t" },
  33. { "\"/\"", "/" },
  34. { "\"\\/\"", "/", .skip = 1 },
  35. { "\"\\\\\"", "\\" },
  36. { "\"\\\"\"", "\"" },
  37. { "\"hello world \\\"embedded string\\\"\"",
  38. "hello world \"embedded string\"" },
  39. { "\"hello world\\nwith new line\"", "hello world\nwith new line" },
  40. { "\"single byte utf-8 \\u0020\"", "single byte utf-8 ", .skip = 1 },
  41. { "\"double byte utf-8 \\u00A2\"", "double byte utf-8 \xc2\xa2" },
  42. { "\"triple byte utf-8 \\u20AC\"", "triple byte utf-8 \xe2\x82\xac" },
  43. {}
  44. };
  45. for (i = 0; test_cases[i].encoded; i++) {
  46. QObject *obj;
  47. QString *str;
  48. obj = qobject_from_json(test_cases[i].encoded);
  49. fail_unless(obj != NULL);
  50. fail_unless(qobject_type(obj) == QTYPE_QSTRING);
  51. str = qobject_to_qstring(obj);
  52. fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0,
  53. "%s != %s\n", qstring_get_str(str), test_cases[i].decoded);
  54. if (test_cases[i].skip == 0) {
  55. str = qobject_to_json(obj);
  56. fail_unless(strcmp(qstring_get_str(str),test_cases[i].encoded) == 0,
  57. "%s != %s\n", qstring_get_str(str),
  58. test_cases[i].encoded);
  59. qobject_decref(obj);
  60. }
  61. QDECREF(str);
  62. }
  63. }
  64. END_TEST
  65. START_TEST(simple_string)
  66. {
  67. int i;
  68. struct {
  69. const char *encoded;
  70. const char *decoded;
  71. } test_cases[] = {
  72. { "\"hello world\"", "hello world" },
  73. { "\"the quick brown fox jumped over the fence\"",
  74. "the quick brown fox jumped over the fence" },
  75. {}
  76. };
  77. for (i = 0; test_cases[i].encoded; i++) {
  78. QObject *obj;
  79. QString *str;
  80. obj = qobject_from_json(test_cases[i].encoded);
  81. fail_unless(obj != NULL);
  82. fail_unless(qobject_type(obj) == QTYPE_QSTRING);
  83. str = qobject_to_qstring(obj);
  84. fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
  85. str = qobject_to_json(obj);
  86. fail_unless(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
  87. qobject_decref(obj);
  88. QDECREF(str);
  89. }
  90. }
  91. END_TEST
  92. START_TEST(single_quote_string)
  93. {
  94. int i;
  95. struct {
  96. const char *encoded;
  97. const char *decoded;
  98. } test_cases[] = {
  99. { "'hello world'", "hello world" },
  100. { "'the quick brown fox \\' jumped over the fence'",
  101. "the quick brown fox ' jumped over the fence" },
  102. {}
  103. };
  104. for (i = 0; test_cases[i].encoded; i++) {
  105. QObject *obj;
  106. QString *str;
  107. obj = qobject_from_json(test_cases[i].encoded);
  108. fail_unless(obj != NULL);
  109. fail_unless(qobject_type(obj) == QTYPE_QSTRING);
  110. str = qobject_to_qstring(obj);
  111. fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
  112. QDECREF(str);
  113. }
  114. }
  115. END_TEST
  116. START_TEST(vararg_string)
  117. {
  118. int i;
  119. struct {
  120. const char *decoded;
  121. } test_cases[] = {
  122. { "hello world" },
  123. { "the quick brown fox jumped over the fence" },
  124. {}
  125. };
  126. for (i = 0; test_cases[i].decoded; i++) {
  127. QObject *obj;
  128. QString *str;
  129. obj = qobject_from_jsonf("%s", test_cases[i].decoded);
  130. fail_unless(obj != NULL);
  131. fail_unless(qobject_type(obj) == QTYPE_QSTRING);
  132. str = qobject_to_qstring(obj);
  133. fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
  134. QDECREF(str);
  135. }
  136. }
  137. END_TEST
  138. START_TEST(simple_number)
  139. {
  140. int i;
  141. struct {
  142. const char *encoded;
  143. int64_t decoded;
  144. int skip;
  145. } test_cases[] = {
  146. { "0", 0 },
  147. { "1234", 1234 },
  148. { "1", 1 },
  149. { "-32", -32 },
  150. { "-0", 0, .skip = 1 },
  151. { },
  152. };
  153. for (i = 0; test_cases[i].encoded; i++) {
  154. QObject *obj;
  155. QInt *qint;
  156. obj = qobject_from_json(test_cases[i].encoded);
  157. fail_unless(obj != NULL);
  158. fail_unless(qobject_type(obj) == QTYPE_QINT);
  159. qint = qobject_to_qint(obj);
  160. fail_unless(qint_get_int(qint) == test_cases[i].decoded);
  161. if (test_cases[i].skip == 0) {
  162. QString *str;
  163. str = qobject_to_json(obj);
  164. fail_unless(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
  165. QDECREF(str);
  166. }
  167. QDECREF(qint);
  168. }
  169. }
  170. END_TEST
  171. START_TEST(float_number)
  172. {
  173. int i;
  174. struct {
  175. const char *encoded;
  176. double decoded;
  177. int skip;
  178. } test_cases[] = {
  179. { "32.43", 32.43 },
  180. { "0.222", 0.222 },
  181. { "-32.12313", -32.12313 },
  182. { "-32.20e-10", -32.20e-10, .skip = 1 },
  183. { },
  184. };
  185. for (i = 0; test_cases[i].encoded; i++) {
  186. QObject *obj;
  187. QFloat *qfloat;
  188. obj = qobject_from_json(test_cases[i].encoded);
  189. fail_unless(obj != NULL);
  190. fail_unless(qobject_type(obj) == QTYPE_QFLOAT);
  191. qfloat = qobject_to_qfloat(obj);
  192. fail_unless(qfloat_get_double(qfloat) == test_cases[i].decoded);
  193. if (test_cases[i].skip == 0) {
  194. QString *str;
  195. str = qobject_to_json(obj);
  196. fail_unless(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
  197. QDECREF(str);
  198. }
  199. QDECREF(qfloat);
  200. }
  201. }
  202. END_TEST
  203. START_TEST(vararg_number)
  204. {
  205. QObject *obj;
  206. QInt *qint;
  207. QFloat *qfloat;
  208. int value = 0x2342;
  209. int64_t value64 = 0x2342342343LL;
  210. double valuef = 2.323423423;
  211. obj = qobject_from_jsonf("%d", value);
  212. fail_unless(obj != NULL);
  213. fail_unless(qobject_type(obj) == QTYPE_QINT);
  214. qint = qobject_to_qint(obj);
  215. fail_unless(qint_get_int(qint) == value);
  216. QDECREF(qint);
  217. obj = qobject_from_jsonf("%" PRId64, value64);
  218. fail_unless(obj != NULL);
  219. fail_unless(qobject_type(obj) == QTYPE_QINT);
  220. qint = qobject_to_qint(obj);
  221. fail_unless(qint_get_int(qint) == value64);
  222. QDECREF(qint);
  223. obj = qobject_from_jsonf("%f", valuef);
  224. fail_unless(obj != NULL);
  225. fail_unless(qobject_type(obj) == QTYPE_QFLOAT);
  226. qfloat = qobject_to_qfloat(obj);
  227. fail_unless(qfloat_get_double(qfloat) == valuef);
  228. QDECREF(qfloat);
  229. }
  230. END_TEST
  231. START_TEST(keyword_literal)
  232. {
  233. QObject *obj;
  234. QBool *qbool;
  235. QString *str;
  236. obj = qobject_from_json("true");
  237. fail_unless(obj != NULL);
  238. fail_unless(qobject_type(obj) == QTYPE_QBOOL);
  239. qbool = qobject_to_qbool(obj);
  240. fail_unless(qbool_get_int(qbool) != 0);
  241. str = qobject_to_json(obj);
  242. fail_unless(strcmp(qstring_get_str(str), "true") == 0);
  243. QDECREF(str);
  244. QDECREF(qbool);
  245. obj = qobject_from_json("false");
  246. fail_unless(obj != NULL);
  247. fail_unless(qobject_type(obj) == QTYPE_QBOOL);
  248. qbool = qobject_to_qbool(obj);
  249. fail_unless(qbool_get_int(qbool) == 0);
  250. str = qobject_to_json(obj);
  251. fail_unless(strcmp(qstring_get_str(str), "false") == 0);
  252. QDECREF(str);
  253. QDECREF(qbool);
  254. obj = qobject_from_jsonf("%i", false);
  255. fail_unless(obj != NULL);
  256. fail_unless(qobject_type(obj) == QTYPE_QBOOL);
  257. qbool = qobject_to_qbool(obj);
  258. fail_unless(qbool_get_int(qbool) == 0);
  259. QDECREF(qbool);
  260. obj = qobject_from_jsonf("%i", true);
  261. fail_unless(obj != NULL);
  262. fail_unless(qobject_type(obj) == QTYPE_QBOOL);
  263. qbool = qobject_to_qbool(obj);
  264. fail_unless(qbool_get_int(qbool) != 0);
  265. QDECREF(qbool);
  266. }
  267. END_TEST
  268. typedef struct LiteralQDictEntry LiteralQDictEntry;
  269. typedef struct LiteralQObject LiteralQObject;
  270. struct LiteralQObject
  271. {
  272. int type;
  273. union {
  274. int64_t qint;
  275. const char *qstr;
  276. LiteralQDictEntry *qdict;
  277. LiteralQObject *qlist;
  278. } value;
  279. };
  280. struct LiteralQDictEntry
  281. {
  282. const char *key;
  283. LiteralQObject value;
  284. };
  285. #define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
  286. #define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
  287. #define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
  288. #define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
  289. typedef struct QListCompareHelper
  290. {
  291. int index;
  292. LiteralQObject *objs;
  293. int result;
  294. } QListCompareHelper;
  295. static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs);
  296. static void compare_helper(QObject *obj, void *opaque)
  297. {
  298. QListCompareHelper *helper = opaque;
  299. if (helper->result == 0) {
  300. return;
  301. }
  302. if (helper->objs[helper->index].type == QTYPE_NONE) {
  303. helper->result = 0;
  304. return;
  305. }
  306. helper->result = compare_litqobj_to_qobj(&helper->objs[helper->index++], obj);
  307. }
  308. static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
  309. {
  310. if (lhs->type != qobject_type(rhs)) {
  311. return 0;
  312. }
  313. switch (lhs->type) {
  314. case QTYPE_QINT:
  315. return lhs->value.qint == qint_get_int(qobject_to_qint(rhs));
  316. case QTYPE_QSTRING:
  317. return (strcmp(lhs->value.qstr, qstring_get_str(qobject_to_qstring(rhs))) == 0);
  318. case QTYPE_QDICT: {
  319. int i;
  320. for (i = 0; lhs->value.qdict[i].key; i++) {
  321. QObject *obj = qdict_get(qobject_to_qdict(rhs), lhs->value.qdict[i].key);
  322. if (!compare_litqobj_to_qobj(&lhs->value.qdict[i].value, obj)) {
  323. return 0;
  324. }
  325. }
  326. return 1;
  327. }
  328. case QTYPE_QLIST: {
  329. QListCompareHelper helper;
  330. helper.index = 0;
  331. helper.objs = lhs->value.qlist;
  332. helper.result = 1;
  333. qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper);
  334. return helper.result;
  335. }
  336. default:
  337. break;
  338. }
  339. return 0;
  340. }
  341. START_TEST(simple_dict)
  342. {
  343. int i;
  344. struct {
  345. const char *encoded;
  346. LiteralQObject decoded;
  347. } test_cases[] = {
  348. {
  349. .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
  350. .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
  351. { "foo", QLIT_QINT(42) },
  352. { "bar", QLIT_QSTR("hello world") },
  353. { }
  354. })),
  355. }, {
  356. .encoded = "{}",
  357. .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
  358. { }
  359. })),
  360. }, {
  361. .encoded = "{\"foo\": 43}",
  362. .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
  363. { "foo", QLIT_QINT(43) },
  364. { }
  365. })),
  366. },
  367. { }
  368. };
  369. for (i = 0; test_cases[i].encoded; i++) {
  370. QObject *obj;
  371. QString *str;
  372. obj = qobject_from_json(test_cases[i].encoded);
  373. fail_unless(obj != NULL);
  374. fail_unless(qobject_type(obj) == QTYPE_QDICT);
  375. fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
  376. str = qobject_to_json(obj);
  377. qobject_decref(obj);
  378. obj = qobject_from_json(qstring_get_str(str));
  379. fail_unless(obj != NULL);
  380. fail_unless(qobject_type(obj) == QTYPE_QDICT);
  381. fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
  382. qobject_decref(obj);
  383. QDECREF(str);
  384. }
  385. }
  386. END_TEST
  387. START_TEST(simple_list)
  388. {
  389. int i;
  390. struct {
  391. const char *encoded;
  392. LiteralQObject decoded;
  393. } test_cases[] = {
  394. {
  395. .encoded = "[43,42]",
  396. .decoded = QLIT_QLIST(((LiteralQObject[]){
  397. QLIT_QINT(43),
  398. QLIT_QINT(42),
  399. { }
  400. })),
  401. },
  402. {
  403. .encoded = "[43]",
  404. .decoded = QLIT_QLIST(((LiteralQObject[]){
  405. QLIT_QINT(43),
  406. { }
  407. })),
  408. },
  409. {
  410. .encoded = "[]",
  411. .decoded = QLIT_QLIST(((LiteralQObject[]){
  412. { }
  413. })),
  414. },
  415. {
  416. .encoded = "[{}]",
  417. .decoded = QLIT_QLIST(((LiteralQObject[]){
  418. QLIT_QDICT(((LiteralQDictEntry[]){
  419. {},
  420. })),
  421. {},
  422. })),
  423. },
  424. { }
  425. };
  426. for (i = 0; test_cases[i].encoded; i++) {
  427. QObject *obj;
  428. QString *str;
  429. obj = qobject_from_json(test_cases[i].encoded);
  430. fail_unless(obj != NULL);
  431. fail_unless(qobject_type(obj) == QTYPE_QLIST);
  432. fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
  433. str = qobject_to_json(obj);
  434. qobject_decref(obj);
  435. obj = qobject_from_json(qstring_get_str(str));
  436. fail_unless(obj != NULL);
  437. fail_unless(qobject_type(obj) == QTYPE_QLIST);
  438. fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
  439. qobject_decref(obj);
  440. QDECREF(str);
  441. }
  442. }
  443. END_TEST
  444. START_TEST(simple_whitespace)
  445. {
  446. int i;
  447. struct {
  448. const char *encoded;
  449. LiteralQObject decoded;
  450. } test_cases[] = {
  451. {
  452. .encoded = " [ 43 , 42 ]",
  453. .decoded = QLIT_QLIST(((LiteralQObject[]){
  454. QLIT_QINT(43),
  455. QLIT_QINT(42),
  456. { }
  457. })),
  458. },
  459. {
  460. .encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
  461. .decoded = QLIT_QLIST(((LiteralQObject[]){
  462. QLIT_QINT(43),
  463. QLIT_QDICT(((LiteralQDictEntry[]){
  464. { "h", QLIT_QSTR("b") },
  465. { }})),
  466. QLIT_QLIST(((LiteralQObject[]){
  467. { }})),
  468. QLIT_QINT(42),
  469. { }
  470. })),
  471. },
  472. {
  473. .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
  474. .decoded = QLIT_QLIST(((LiteralQObject[]){
  475. QLIT_QINT(43),
  476. QLIT_QDICT(((LiteralQDictEntry[]){
  477. { "h", QLIT_QSTR("b") },
  478. { "a", QLIT_QINT(32) },
  479. { }})),
  480. QLIT_QLIST(((LiteralQObject[]){
  481. { }})),
  482. QLIT_QINT(42),
  483. { }
  484. })),
  485. },
  486. { }
  487. };
  488. for (i = 0; test_cases[i].encoded; i++) {
  489. QObject *obj;
  490. QString *str;
  491. obj = qobject_from_json(test_cases[i].encoded);
  492. fail_unless(obj != NULL);
  493. fail_unless(qobject_type(obj) == QTYPE_QLIST);
  494. fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
  495. str = qobject_to_json(obj);
  496. qobject_decref(obj);
  497. obj = qobject_from_json(qstring_get_str(str));
  498. fail_unless(obj != NULL);
  499. fail_unless(qobject_type(obj) == QTYPE_QLIST);
  500. fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
  501. qobject_decref(obj);
  502. QDECREF(str);
  503. }
  504. }
  505. END_TEST
  506. START_TEST(simple_varargs)
  507. {
  508. QObject *embedded_obj;
  509. QObject *obj;
  510. LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){
  511. QLIT_QINT(1),
  512. QLIT_QINT(2),
  513. QLIT_QLIST(((LiteralQObject[]){
  514. QLIT_QINT(32),
  515. QLIT_QINT(42),
  516. {}})),
  517. {}}));
  518. embedded_obj = qobject_from_json("[32, 42]");
  519. fail_unless(embedded_obj != NULL);
  520. obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
  521. fail_unless(obj != NULL);
  522. fail_unless(compare_litqobj_to_qobj(&decoded, obj) == 1);
  523. qobject_decref(obj);
  524. }
  525. END_TEST
  526. START_TEST(empty_input)
  527. {
  528. const char *empty = "";
  529. QObject *obj = qobject_from_json(empty);
  530. fail_unless(obj == NULL);
  531. }
  532. END_TEST
  533. START_TEST(unterminated_string)
  534. {
  535. QObject *obj = qobject_from_json("\"abc");
  536. fail_unless(obj == NULL);
  537. }
  538. END_TEST
  539. START_TEST(unterminated_sq_string)
  540. {
  541. QObject *obj = qobject_from_json("'abc");
  542. fail_unless(obj == NULL);
  543. }
  544. END_TEST
  545. START_TEST(unterminated_escape)
  546. {
  547. QObject *obj = qobject_from_json("\"abc\\\"");
  548. fail_unless(obj == NULL);
  549. }
  550. END_TEST
  551. START_TEST(unterminated_array)
  552. {
  553. QObject *obj = qobject_from_json("[32");
  554. fail_unless(obj == NULL);
  555. }
  556. END_TEST
  557. START_TEST(unterminated_array_comma)
  558. {
  559. QObject *obj = qobject_from_json("[32,");
  560. fail_unless(obj == NULL);
  561. }
  562. END_TEST
  563. START_TEST(invalid_array_comma)
  564. {
  565. QObject *obj = qobject_from_json("[32,}");
  566. fail_unless(obj == NULL);
  567. }
  568. END_TEST
  569. START_TEST(unterminated_dict)
  570. {
  571. QObject *obj = qobject_from_json("{'abc':32");
  572. fail_unless(obj == NULL);
  573. }
  574. END_TEST
  575. START_TEST(unterminated_dict_comma)
  576. {
  577. QObject *obj = qobject_from_json("{'abc':32,");
  578. fail_unless(obj == NULL);
  579. }
  580. END_TEST
  581. #if 0
  582. START_TEST(invalid_dict_comma)
  583. {
  584. QObject *obj = qobject_from_json("{'abc':32,}");
  585. fail_unless(obj == NULL);
  586. }
  587. END_TEST
  588. START_TEST(unterminated_literal)
  589. {
  590. QObject *obj = qobject_from_json("nul");
  591. fail_unless(obj == NULL);
  592. }
  593. END_TEST
  594. #endif
  595. static Suite *qjson_suite(void)
  596. {
  597. Suite *suite;
  598. TCase *string_literals, *number_literals, *keyword_literals;
  599. TCase *dicts, *lists, *whitespace, *varargs, *errors;
  600. string_literals = tcase_create("String Literals");
  601. tcase_add_test(string_literals, simple_string);
  602. tcase_add_test(string_literals, escaped_string);
  603. tcase_add_test(string_literals, single_quote_string);
  604. tcase_add_test(string_literals, vararg_string);
  605. number_literals = tcase_create("Number Literals");
  606. tcase_add_test(number_literals, simple_number);
  607. tcase_add_test(number_literals, float_number);
  608. tcase_add_test(number_literals, vararg_number);
  609. keyword_literals = tcase_create("Keywords");
  610. tcase_add_test(keyword_literals, keyword_literal);
  611. dicts = tcase_create("Objects");
  612. tcase_add_test(dicts, simple_dict);
  613. lists = tcase_create("Lists");
  614. tcase_add_test(lists, simple_list);
  615. whitespace = tcase_create("Whitespace");
  616. tcase_add_test(whitespace, simple_whitespace);
  617. varargs = tcase_create("Varargs");
  618. tcase_add_test(varargs, simple_varargs);
  619. errors = tcase_create("Invalid JSON");
  620. tcase_add_test(errors, empty_input);
  621. tcase_add_test(errors, unterminated_string);
  622. tcase_add_test(errors, unterminated_escape);
  623. tcase_add_test(errors, unterminated_sq_string);
  624. tcase_add_test(errors, unterminated_array);
  625. tcase_add_test(errors, unterminated_array_comma);
  626. tcase_add_test(errors, invalid_array_comma);
  627. tcase_add_test(errors, unterminated_dict);
  628. tcase_add_test(errors, unterminated_dict_comma);
  629. #if 0
  630. /* FIXME: this print parse error messages on stderr. */
  631. tcase_add_test(errors, invalid_dict_comma);
  632. tcase_add_test(errors, unterminated_literal);
  633. #endif
  634. suite = suite_create("QJSON test-suite");
  635. suite_add_tcase(suite, string_literals);
  636. suite_add_tcase(suite, number_literals);
  637. suite_add_tcase(suite, keyword_literals);
  638. suite_add_tcase(suite, dicts);
  639. suite_add_tcase(suite, lists);
  640. suite_add_tcase(suite, whitespace);
  641. suite_add_tcase(suite, varargs);
  642. suite_add_tcase(suite, errors);
  643. return suite;
  644. }
  645. int main(void)
  646. {
  647. int nf;
  648. Suite *s;
  649. SRunner *sr;
  650. s = qjson_suite();
  651. sr = srunner_create(s);
  652. srunner_run_all(sr, CK_NORMAL);
  653. nf = srunner_ntests_failed(sr);
  654. srunner_free(sr);
  655. return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
  656. }