2
0

test-keyval.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  1. /*
  2. * Unit tests for parsing of KEY=VALUE,... strings
  3. *
  4. * Copyright (C) 2017 Red Hat Inc.
  5. *
  6. * Authors:
  7. * Markus Armbruster <armbru@redhat.com>,
  8. *
  9. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  10. * See the COPYING file in the top-level directory.
  11. */
  12. #include "qemu/osdep.h"
  13. #include "qemu/units.h"
  14. #include "qapi/error.h"
  15. #include "qapi/qmp/qdict.h"
  16. #include "qapi/qmp/qlist.h"
  17. #include "qapi/qmp/qstring.h"
  18. #include "qapi/qobject-input-visitor.h"
  19. #include "test-qapi-visit.h"
  20. #include "qemu/cutils.h"
  21. #include "qemu/option.h"
  22. static void test_keyval_parse(void)
  23. {
  24. Error *err = NULL;
  25. QDict *qdict, *sub_qdict;
  26. char long_key[129];
  27. char *params;
  28. /* Nothing */
  29. qdict = keyval_parse("", NULL, &error_abort);
  30. g_assert_cmpuint(qdict_size(qdict), ==, 0);
  31. qobject_unref(qdict);
  32. /* Empty key (qemu_opts_parse() accepts this) */
  33. qdict = keyval_parse("=val", NULL, &err);
  34. error_free_or_abort(&err);
  35. g_assert(!qdict);
  36. /* Empty key fragment */
  37. qdict = keyval_parse(".", NULL, &err);
  38. error_free_or_abort(&err);
  39. g_assert(!qdict);
  40. qdict = keyval_parse("key.", NULL, &err);
  41. error_free_or_abort(&err);
  42. g_assert(!qdict);
  43. /* Invalid non-empty key (qemu_opts_parse() doesn't care) */
  44. qdict = keyval_parse("7up=val", NULL, &err);
  45. error_free_or_abort(&err);
  46. g_assert(!qdict);
  47. /* Overlong key */
  48. memset(long_key, 'a', 127);
  49. long_key[127] = 'z';
  50. long_key[128] = 0;
  51. params = g_strdup_printf("k.%s=v", long_key);
  52. qdict = keyval_parse(params + 2, NULL, &err);
  53. error_free_or_abort(&err);
  54. g_assert(!qdict);
  55. /* Overlong key fragment */
  56. qdict = keyval_parse(params, NULL, &err);
  57. error_free_or_abort(&err);
  58. g_assert(!qdict);
  59. g_free(params);
  60. /* Long key (qemu_opts_parse() accepts and truncates silently) */
  61. params = g_strdup_printf("k.%s=v", long_key + 1);
  62. qdict = keyval_parse(params + 2, NULL, &error_abort);
  63. g_assert_cmpuint(qdict_size(qdict), ==, 1);
  64. g_assert_cmpstr(qdict_get_try_str(qdict, long_key + 1), ==, "v");
  65. qobject_unref(qdict);
  66. /* Long key fragment */
  67. qdict = keyval_parse(params, NULL, &error_abort);
  68. g_assert_cmpuint(qdict_size(qdict), ==, 1);
  69. sub_qdict = qdict_get_qdict(qdict, "k");
  70. g_assert(sub_qdict);
  71. g_assert_cmpuint(qdict_size(sub_qdict), ==, 1);
  72. g_assert_cmpstr(qdict_get_try_str(sub_qdict, long_key + 1), ==, "v");
  73. qobject_unref(qdict);
  74. g_free(params);
  75. /* Crap after valid key */
  76. qdict = keyval_parse("key[0]=val", NULL, &err);
  77. error_free_or_abort(&err);
  78. g_assert(!qdict);
  79. /* Multiple keys, last one wins */
  80. qdict = keyval_parse("a=1,b=2,,x,a=3", NULL, &error_abort);
  81. g_assert_cmpuint(qdict_size(qdict), ==, 2);
  82. g_assert_cmpstr(qdict_get_try_str(qdict, "a"), ==, "3");
  83. g_assert_cmpstr(qdict_get_try_str(qdict, "b"), ==, "2,x");
  84. qobject_unref(qdict);
  85. /* Even when it doesn't in qemu_opts_parse() */
  86. qdict = keyval_parse("id=foo,id=bar", NULL, &error_abort);
  87. g_assert_cmpuint(qdict_size(qdict), ==, 1);
  88. g_assert_cmpstr(qdict_get_try_str(qdict, "id"), ==, "bar");
  89. qobject_unref(qdict);
  90. /* Dotted keys */
  91. qdict = keyval_parse("a.b.c=1,a.b.c=2,d=3", NULL, &error_abort);
  92. g_assert_cmpuint(qdict_size(qdict), ==, 2);
  93. sub_qdict = qdict_get_qdict(qdict, "a");
  94. g_assert(sub_qdict);
  95. g_assert_cmpuint(qdict_size(sub_qdict), ==, 1);
  96. sub_qdict = qdict_get_qdict(sub_qdict, "b");
  97. g_assert(sub_qdict);
  98. g_assert_cmpuint(qdict_size(sub_qdict), ==, 1);
  99. g_assert_cmpstr(qdict_get_try_str(sub_qdict, "c"), ==, "2");
  100. g_assert_cmpstr(qdict_get_try_str(qdict, "d"), ==, "3");
  101. qobject_unref(qdict);
  102. /* Inconsistent dotted keys */
  103. qdict = keyval_parse("a.b=1,a=2", NULL, &err);
  104. error_free_or_abort(&err);
  105. g_assert(!qdict);
  106. qdict = keyval_parse("a.b=1,a.b.c=2", NULL, &err);
  107. error_free_or_abort(&err);
  108. g_assert(!qdict);
  109. /* Trailing comma is ignored */
  110. qdict = keyval_parse("x=y,", NULL, &error_abort);
  111. g_assert_cmpuint(qdict_size(qdict), ==, 1);
  112. g_assert_cmpstr(qdict_get_try_str(qdict, "x"), ==, "y");
  113. qobject_unref(qdict);
  114. /* Except when it isn't */
  115. qdict = keyval_parse(",", NULL, &err);
  116. error_free_or_abort(&err);
  117. g_assert(!qdict);
  118. /* Value containing ,id= not misinterpreted as qemu_opts_parse() does */
  119. qdict = keyval_parse("x=,,id=bar", NULL, &error_abort);
  120. g_assert_cmpuint(qdict_size(qdict), ==, 1);
  121. g_assert_cmpstr(qdict_get_try_str(qdict, "x"), ==, ",id=bar");
  122. qobject_unref(qdict);
  123. /* Anti-social ID is left to caller (qemu_opts_parse() rejects it) */
  124. qdict = keyval_parse("id=666", NULL, &error_abort);
  125. g_assert_cmpuint(qdict_size(qdict), ==, 1);
  126. g_assert_cmpstr(qdict_get_try_str(qdict, "id"), ==, "666");
  127. qobject_unref(qdict);
  128. /* Implied value not supported (unlike qemu_opts_parse()) */
  129. qdict = keyval_parse("an,noaus,noaus=", NULL, &err);
  130. error_free_or_abort(&err);
  131. g_assert(!qdict);
  132. /* Implied value, key "no" (qemu_opts_parse(): negated empty key) */
  133. qdict = keyval_parse("no", NULL, &err);
  134. error_free_or_abort(&err);
  135. g_assert(!qdict);
  136. /* Implied key */
  137. qdict = keyval_parse("an,aus=off,noaus=", "implied", &error_abort);
  138. g_assert_cmpuint(qdict_size(qdict), ==, 3);
  139. g_assert_cmpstr(qdict_get_try_str(qdict, "implied"), ==, "an");
  140. g_assert_cmpstr(qdict_get_try_str(qdict, "aus"), ==, "off");
  141. g_assert_cmpstr(qdict_get_try_str(qdict, "noaus"), ==, "");
  142. qobject_unref(qdict);
  143. /* Implied dotted key */
  144. qdict = keyval_parse("val", "eins.zwei", &error_abort);
  145. g_assert_cmpuint(qdict_size(qdict), ==, 1);
  146. sub_qdict = qdict_get_qdict(qdict, "eins");
  147. g_assert(sub_qdict);
  148. g_assert_cmpuint(qdict_size(sub_qdict), ==, 1);
  149. g_assert_cmpstr(qdict_get_try_str(sub_qdict, "zwei"), ==, "val");
  150. qobject_unref(qdict);
  151. /* Implied key with empty value (qemu_opts_parse() accepts this) */
  152. qdict = keyval_parse(",", "implied", &err);
  153. error_free_or_abort(&err);
  154. g_assert(!qdict);
  155. /* Likewise (qemu_opts_parse(): implied key with comma value) */
  156. qdict = keyval_parse(",,,a=1", "implied", &err);
  157. error_free_or_abort(&err);
  158. g_assert(!qdict);
  159. /* Empty key is not an implied key */
  160. qdict = keyval_parse("=val", "implied", &err);
  161. error_free_or_abort(&err);
  162. g_assert(!qdict);
  163. }
  164. static void check_list012(QList *qlist)
  165. {
  166. static const char *expected[] = { "null", "eins", "zwei" };
  167. int i;
  168. QString *qstr;
  169. g_assert(qlist);
  170. for (i = 0; i < ARRAY_SIZE(expected); i++) {
  171. qstr = qobject_to(QString, qlist_pop(qlist));
  172. g_assert(qstr);
  173. g_assert_cmpstr(qstring_get_str(qstr), ==, expected[i]);
  174. qobject_unref(qstr);
  175. }
  176. g_assert(qlist_empty(qlist));
  177. }
  178. static void test_keyval_parse_list(void)
  179. {
  180. Error *err = NULL;
  181. QDict *qdict, *sub_qdict;
  182. /* Root can't be a list */
  183. qdict = keyval_parse("0=1", NULL, &err);
  184. error_free_or_abort(&err);
  185. g_assert(!qdict);
  186. /* List elements need not be in order */
  187. qdict = keyval_parse("list.0=null,list.2=zwei,list.1=eins",
  188. NULL, &error_abort);
  189. g_assert_cmpint(qdict_size(qdict), ==, 1);
  190. check_list012(qdict_get_qlist(qdict, "list"));
  191. qobject_unref(qdict);
  192. /* Multiple indexes, last one wins */
  193. qdict = keyval_parse("list.1=goner,list.0=null,list.01=eins,list.2=zwei",
  194. NULL, &error_abort);
  195. g_assert_cmpint(qdict_size(qdict), ==, 1);
  196. check_list012(qdict_get_qlist(qdict, "list"));
  197. qobject_unref(qdict);
  198. /* List at deeper nesting */
  199. qdict = keyval_parse("a.list.1=eins,a.list.00=null,a.list.2=zwei",
  200. NULL, &error_abort);
  201. g_assert_cmpint(qdict_size(qdict), ==, 1);
  202. sub_qdict = qdict_get_qdict(qdict, "a");
  203. g_assert_cmpint(qdict_size(sub_qdict), ==, 1);
  204. check_list012(qdict_get_qlist(sub_qdict, "list"));
  205. qobject_unref(qdict);
  206. /* Inconsistent dotted keys: both list and dictionary */
  207. qdict = keyval_parse("a.b.c=1,a.b.0=2", NULL, &err);
  208. error_free_or_abort(&err);
  209. g_assert(!qdict);
  210. qdict = keyval_parse("a.0.c=1,a.b.c=2", NULL, &err);
  211. error_free_or_abort(&err);
  212. g_assert(!qdict);
  213. /* Missing list indexes */
  214. qdict = keyval_parse("list.1=lonely", NULL, &err);
  215. error_free_or_abort(&err);
  216. g_assert(!qdict);
  217. qdict = keyval_parse("list.0=null,list.2=eins,list.02=zwei", NULL, &err);
  218. error_free_or_abort(&err);
  219. g_assert(!qdict);
  220. }
  221. static void test_keyval_visit_bool(void)
  222. {
  223. Error *err = NULL;
  224. Visitor *v;
  225. QDict *qdict;
  226. bool b;
  227. qdict = keyval_parse("bool1=on,bool2=off", NULL, &error_abort);
  228. v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
  229. qobject_unref(qdict);
  230. visit_start_struct(v, NULL, NULL, 0, &error_abort);
  231. visit_type_bool(v, "bool1", &b, &error_abort);
  232. g_assert(b);
  233. visit_type_bool(v, "bool2", &b, &error_abort);
  234. g_assert(!b);
  235. visit_check_struct(v, &error_abort);
  236. visit_end_struct(v, NULL);
  237. visit_free(v);
  238. qdict = keyval_parse("bool1=offer", NULL, &error_abort);
  239. v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
  240. qobject_unref(qdict);
  241. visit_start_struct(v, NULL, NULL, 0, &error_abort);
  242. visit_type_bool(v, "bool1", &b, &err);
  243. error_free_or_abort(&err);
  244. visit_end_struct(v, NULL);
  245. visit_free(v);
  246. }
  247. static void test_keyval_visit_number(void)
  248. {
  249. Error *err = NULL;
  250. Visitor *v;
  251. QDict *qdict;
  252. uint64_t u;
  253. /* Lower limit zero */
  254. qdict = keyval_parse("number1=0", NULL, &error_abort);
  255. v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
  256. qobject_unref(qdict);
  257. visit_start_struct(v, NULL, NULL, 0, &error_abort);
  258. visit_type_uint64(v, "number1", &u, &error_abort);
  259. g_assert_cmpuint(u, ==, 0);
  260. visit_check_struct(v, &error_abort);
  261. visit_end_struct(v, NULL);
  262. visit_free(v);
  263. /* Upper limit 2^64-1 */
  264. qdict = keyval_parse("number1=18446744073709551615,number2=-1",
  265. NULL, &error_abort);
  266. v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
  267. qobject_unref(qdict);
  268. visit_start_struct(v, NULL, NULL, 0, &error_abort);
  269. visit_type_uint64(v, "number1", &u, &error_abort);
  270. g_assert_cmphex(u, ==, UINT64_MAX);
  271. visit_type_uint64(v, "number2", &u, &error_abort);
  272. g_assert_cmphex(u, ==, UINT64_MAX);
  273. visit_check_struct(v, &error_abort);
  274. visit_end_struct(v, NULL);
  275. visit_free(v);
  276. /* Above upper limit */
  277. qdict = keyval_parse("number1=18446744073709551616",
  278. NULL, &error_abort);
  279. v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
  280. qobject_unref(qdict);
  281. visit_start_struct(v, NULL, NULL, 0, &error_abort);
  282. visit_type_uint64(v, "number1", &u, &err);
  283. error_free_or_abort(&err);
  284. visit_end_struct(v, NULL);
  285. visit_free(v);
  286. /* Below lower limit */
  287. qdict = keyval_parse("number1=-18446744073709551616",
  288. NULL, &error_abort);
  289. v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
  290. qobject_unref(qdict);
  291. visit_start_struct(v, NULL, NULL, 0, &error_abort);
  292. visit_type_uint64(v, "number1", &u, &err);
  293. error_free_or_abort(&err);
  294. visit_end_struct(v, NULL);
  295. visit_free(v);
  296. /* Hex and octal */
  297. qdict = keyval_parse("number1=0x2a,number2=052",
  298. NULL, &error_abort);
  299. v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
  300. qobject_unref(qdict);
  301. visit_start_struct(v, NULL, NULL, 0, &error_abort);
  302. visit_type_uint64(v, "number1", &u, &error_abort);
  303. g_assert_cmpuint(u, ==, 42);
  304. visit_type_uint64(v, "number2", &u, &error_abort);
  305. g_assert_cmpuint(u, ==, 42);
  306. visit_check_struct(v, &error_abort);
  307. visit_end_struct(v, NULL);
  308. visit_free(v);
  309. /* Trailing crap */
  310. qdict = keyval_parse("number1=3.14,number2=08",
  311. NULL, &error_abort);
  312. v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
  313. qobject_unref(qdict);
  314. visit_start_struct(v, NULL, NULL, 0, &error_abort);
  315. visit_type_uint64(v, "number1", &u, &err);
  316. error_free_or_abort(&err);
  317. visit_type_uint64(v, "number2", &u, &err);
  318. error_free_or_abort(&err);
  319. visit_end_struct(v, NULL);
  320. visit_free(v);
  321. }
  322. static void test_keyval_visit_size(void)
  323. {
  324. Error *err = NULL;
  325. Visitor *v;
  326. QDict *qdict;
  327. uint64_t sz;
  328. /* Lower limit zero */
  329. qdict = keyval_parse("sz1=0", NULL, &error_abort);
  330. v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
  331. qobject_unref(qdict);
  332. visit_start_struct(v, NULL, NULL, 0, &error_abort);
  333. visit_type_size(v, "sz1", &sz, &error_abort);
  334. g_assert_cmpuint(sz, ==, 0);
  335. visit_check_struct(v, &error_abort);
  336. visit_end_struct(v, NULL);
  337. visit_free(v);
  338. /* Note: precision is 53 bits since we're parsing with strtod() */
  339. /* Around limit of precision: 2^53-1, 2^53, 2^53+1 */
  340. qdict = keyval_parse("sz1=9007199254740991,"
  341. "sz2=9007199254740992,"
  342. "sz3=9007199254740993",
  343. NULL, &error_abort);
  344. v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
  345. qobject_unref(qdict);
  346. visit_start_struct(v, NULL, NULL, 0, &error_abort);
  347. visit_type_size(v, "sz1", &sz, &error_abort);
  348. g_assert_cmphex(sz, ==, 0x1fffffffffffff);
  349. visit_type_size(v, "sz2", &sz, &error_abort);
  350. g_assert_cmphex(sz, ==, 0x20000000000000);
  351. visit_type_size(v, "sz3", &sz, &error_abort);
  352. g_assert_cmphex(sz, ==, 0x20000000000000);
  353. visit_check_struct(v, &error_abort);
  354. visit_end_struct(v, NULL);
  355. visit_free(v);
  356. /* Close to signed upper limit 0x7ffffffffffffc00 (53 msbs set) */
  357. qdict = keyval_parse("sz1=9223372036854774784," /* 7ffffffffffffc00 */
  358. "sz2=9223372036854775295", /* 7ffffffffffffdff */
  359. NULL, &error_abort);
  360. v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
  361. qobject_unref(qdict);
  362. visit_start_struct(v, NULL, NULL, 0, &error_abort);
  363. visit_type_size(v, "sz1", &sz, &error_abort);
  364. g_assert_cmphex(sz, ==, 0x7ffffffffffffc00);
  365. visit_type_size(v, "sz2", &sz, &error_abort);
  366. g_assert_cmphex(sz, ==, 0x7ffffffffffffc00);
  367. visit_check_struct(v, &error_abort);
  368. visit_end_struct(v, NULL);
  369. visit_free(v);
  370. /* Close to actual upper limit 0xfffffffffffff800 (53 msbs set) */
  371. qdict = keyval_parse("sz1=18446744073709549568," /* fffffffffffff800 */
  372. "sz2=18446744073709550591", /* fffffffffffffbff */
  373. NULL, &error_abort);
  374. v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
  375. qobject_unref(qdict);
  376. visit_start_struct(v, NULL, NULL, 0, &error_abort);
  377. visit_type_size(v, "sz1", &sz, &error_abort);
  378. g_assert_cmphex(sz, ==, 0xfffffffffffff800);
  379. visit_type_size(v, "sz2", &sz, &error_abort);
  380. g_assert_cmphex(sz, ==, 0xfffffffffffff800);
  381. visit_check_struct(v, &error_abort);
  382. visit_end_struct(v, NULL);
  383. visit_free(v);
  384. /* Beyond limits */
  385. qdict = keyval_parse("sz1=-1,"
  386. "sz2=18446744073709550592", /* fffffffffffffc00 */
  387. NULL, &error_abort);
  388. v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
  389. qobject_unref(qdict);
  390. visit_start_struct(v, NULL, NULL, 0, &error_abort);
  391. visit_type_size(v, "sz1", &sz, &err);
  392. error_free_or_abort(&err);
  393. visit_type_size(v, "sz2", &sz, &err);
  394. error_free_or_abort(&err);
  395. visit_end_struct(v, NULL);
  396. visit_free(v);
  397. /* Suffixes */
  398. qdict = keyval_parse("sz1=8b,sz2=1.5k,sz3=2M,sz4=0.1G,sz5=16777215T",
  399. NULL, &error_abort);
  400. v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
  401. qobject_unref(qdict);
  402. visit_start_struct(v, NULL, NULL, 0, &error_abort);
  403. visit_type_size(v, "sz1", &sz, &error_abort);
  404. g_assert_cmpuint(sz, ==, 8);
  405. visit_type_size(v, "sz2", &sz, &error_abort);
  406. g_assert_cmpuint(sz, ==, 1536);
  407. visit_type_size(v, "sz3", &sz, &error_abort);
  408. g_assert_cmphex(sz, ==, 2 * MiB);
  409. visit_type_size(v, "sz4", &sz, &error_abort);
  410. g_assert_cmphex(sz, ==, GiB / 10);
  411. visit_type_size(v, "sz5", &sz, &error_abort);
  412. g_assert_cmphex(sz, ==, 16777215ULL * TiB);
  413. visit_check_struct(v, &error_abort);
  414. visit_end_struct(v, NULL);
  415. visit_free(v);
  416. /* Beyond limit with suffix */
  417. qdict = keyval_parse("sz1=16777216T", NULL, &error_abort);
  418. v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
  419. qobject_unref(qdict);
  420. visit_start_struct(v, NULL, NULL, 0, &error_abort);
  421. visit_type_size(v, "sz1", &sz, &err);
  422. error_free_or_abort(&err);
  423. visit_end_struct(v, NULL);
  424. visit_free(v);
  425. /* Trailing crap */
  426. qdict = keyval_parse("sz1=16E,sz2=16Gi", NULL, &error_abort);
  427. v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
  428. qobject_unref(qdict);
  429. visit_start_struct(v, NULL, NULL, 0, &error_abort);
  430. visit_type_size(v, "sz1", &sz, &err);
  431. error_free_or_abort(&err);
  432. visit_type_size(v, "sz2", &sz, &err);
  433. error_free_or_abort(&err);
  434. visit_end_struct(v, NULL);
  435. visit_free(v);
  436. }
  437. static void test_keyval_visit_dict(void)
  438. {
  439. Error *err = NULL;
  440. Visitor *v;
  441. QDict *qdict;
  442. int64_t i;
  443. qdict = keyval_parse("a.b.c=1,a.b.c=2,d=3", NULL, &error_abort);
  444. v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
  445. qobject_unref(qdict);
  446. visit_start_struct(v, NULL, NULL, 0, &error_abort);
  447. visit_start_struct(v, "a", NULL, 0, &error_abort);
  448. visit_start_struct(v, "b", NULL, 0, &error_abort);
  449. visit_type_int(v, "c", &i, &error_abort);
  450. g_assert_cmpint(i, ==, 2);
  451. visit_check_struct(v, &error_abort);
  452. visit_end_struct(v, NULL);
  453. visit_check_struct(v, &error_abort);
  454. visit_end_struct(v, NULL);
  455. visit_type_int(v, "d", &i, &error_abort);
  456. g_assert_cmpint(i, ==, 3);
  457. visit_check_struct(v, &error_abort);
  458. visit_end_struct(v, NULL);
  459. visit_free(v);
  460. qdict = keyval_parse("a.b=", NULL, &error_abort);
  461. v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
  462. qobject_unref(qdict);
  463. visit_start_struct(v, NULL, NULL, 0, &error_abort);
  464. visit_start_struct(v, "a", NULL, 0, &error_abort);
  465. visit_type_int(v, "c", &i, &err); /* a.c missing */
  466. error_free_or_abort(&err);
  467. visit_check_struct(v, &err);
  468. error_free_or_abort(&err); /* a.b unexpected */
  469. visit_end_struct(v, NULL);
  470. visit_check_struct(v, &error_abort);
  471. visit_end_struct(v, NULL);
  472. visit_free(v);
  473. }
  474. static void test_keyval_visit_list(void)
  475. {
  476. Error *err = NULL;
  477. Visitor *v;
  478. QDict *qdict;
  479. char *s;
  480. qdict = keyval_parse("a.0=,a.1=I,a.2.0=II", NULL, &error_abort);
  481. /* TODO empty list */
  482. v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
  483. qobject_unref(qdict);
  484. visit_start_struct(v, NULL, NULL, 0, &error_abort);
  485. visit_start_list(v, "a", NULL, 0, &error_abort);
  486. visit_type_str(v, NULL, &s, &error_abort);
  487. g_assert_cmpstr(s, ==, "");
  488. g_free(s);
  489. visit_type_str(v, NULL, &s, &error_abort);
  490. g_assert_cmpstr(s, ==, "I");
  491. g_free(s);
  492. visit_start_list(v, NULL, NULL, 0, &error_abort);
  493. visit_type_str(v, NULL, &s, &error_abort);
  494. g_assert_cmpstr(s, ==, "II");
  495. g_free(s);
  496. visit_check_list(v, &error_abort);
  497. visit_end_list(v, NULL);
  498. visit_check_list(v, &error_abort);
  499. visit_end_list(v, NULL);
  500. visit_check_struct(v, &error_abort);
  501. visit_end_struct(v, NULL);
  502. visit_free(v);
  503. qdict = keyval_parse("a.0=,b.0.0=head", NULL, &error_abort);
  504. v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
  505. qobject_unref(qdict);
  506. visit_start_struct(v, NULL, NULL, 0, &error_abort);
  507. visit_start_list(v, "a", NULL, 0, &error_abort);
  508. visit_check_list(v, &err); /* a[0] unexpected */
  509. error_free_or_abort(&err);
  510. visit_end_list(v, NULL);
  511. visit_start_list(v, "b", NULL, 0, &error_abort);
  512. visit_start_list(v, NULL, NULL, 0, &error_abort);
  513. visit_type_str(v, NULL, &s, &error_abort);
  514. g_assert_cmpstr(s, ==, "head");
  515. g_free(s);
  516. visit_type_str(v, NULL, &s, &err); /* b[0][1] missing */
  517. error_free_or_abort(&err);
  518. visit_end_list(v, NULL);
  519. visit_end_list(v, NULL);
  520. visit_check_struct(v, &error_abort);
  521. visit_end_struct(v, NULL);
  522. visit_free(v);
  523. }
  524. static void test_keyval_visit_optional(void)
  525. {
  526. Visitor *v;
  527. QDict *qdict;
  528. bool present;
  529. int64_t i;
  530. qdict = keyval_parse("a.b=1", NULL, &error_abort);
  531. v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
  532. qobject_unref(qdict);
  533. visit_start_struct(v, NULL, NULL, 0, &error_abort);
  534. visit_optional(v, "b", &present);
  535. g_assert(!present); /* b missing */
  536. visit_optional(v, "a", &present);
  537. g_assert(present); /* a present */
  538. visit_start_struct(v, "a", NULL, 0, &error_abort);
  539. visit_optional(v, "b", &present);
  540. g_assert(present); /* a.b present */
  541. visit_type_int(v, "b", &i, &error_abort);
  542. g_assert_cmpint(i, ==, 1);
  543. visit_optional(v, "a", &present);
  544. g_assert(!present); /* a.a missing */
  545. visit_check_struct(v, &error_abort);
  546. visit_end_struct(v, NULL);
  547. visit_check_struct(v, &error_abort);
  548. visit_end_struct(v, NULL);
  549. visit_free(v);
  550. }
  551. static void test_keyval_visit_alternate(void)
  552. {
  553. Error *err = NULL;
  554. Visitor *v;
  555. QDict *qdict;
  556. AltStrObj *aso;
  557. AltNumEnum *ane;
  558. AltEnumBool *aeb;
  559. /*
  560. * Can't do scalar alternate variants other than string. You get
  561. * the string variant if there is one, else an error.
  562. * TODO make it work for unambiguous cases like AltEnumBool below
  563. */
  564. qdict = keyval_parse("a=1,b=2,c=on", NULL, &error_abort);
  565. v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
  566. qobject_unref(qdict);
  567. visit_start_struct(v, NULL, NULL, 0, &error_abort);
  568. visit_type_AltStrObj(v, "a", &aso, &error_abort);
  569. g_assert_cmpint(aso->type, ==, QTYPE_QSTRING);
  570. g_assert_cmpstr(aso->u.s, ==, "1");
  571. qapi_free_AltStrObj(aso);
  572. visit_type_AltNumEnum(v, "b", &ane, &err);
  573. error_free_or_abort(&err);
  574. visit_type_AltEnumBool(v, "c", &aeb, &err);
  575. error_free_or_abort(&err);
  576. visit_end_struct(v, NULL);
  577. visit_free(v);
  578. }
  579. static void test_keyval_visit_any(void)
  580. {
  581. Visitor *v;
  582. QDict *qdict;
  583. QObject *any;
  584. QList *qlist;
  585. QString *qstr;
  586. qdict = keyval_parse("a.0=null,a.1=1", NULL, &error_abort);
  587. v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
  588. qobject_unref(qdict);
  589. visit_start_struct(v, NULL, NULL, 0, &error_abort);
  590. visit_type_any(v, "a", &any, &error_abort);
  591. qlist = qobject_to(QList, any);
  592. g_assert(qlist);
  593. qstr = qobject_to(QString, qlist_pop(qlist));
  594. g_assert_cmpstr(qstring_get_str(qstr), ==, "null");
  595. qobject_unref(qstr);
  596. qstr = qobject_to(QString, qlist_pop(qlist));
  597. g_assert_cmpstr(qstring_get_str(qstr), ==, "1");
  598. g_assert(qlist_empty(qlist));
  599. qobject_unref(qstr);
  600. qobject_unref(any);
  601. visit_check_struct(v, &error_abort);
  602. visit_end_struct(v, NULL);
  603. visit_free(v);
  604. }
  605. int main(int argc, char *argv[])
  606. {
  607. g_test_init(&argc, &argv, NULL);
  608. g_test_add_func("/keyval/keyval_parse", test_keyval_parse);
  609. g_test_add_func("/keyval/keyval_parse/list", test_keyval_parse_list);
  610. g_test_add_func("/keyval/visit/bool", test_keyval_visit_bool);
  611. g_test_add_func("/keyval/visit/number", test_keyval_visit_number);
  612. g_test_add_func("/keyval/visit/size", test_keyval_visit_size);
  613. g_test_add_func("/keyval/visit/dict", test_keyval_visit_dict);
  614. g_test_add_func("/keyval/visit/list", test_keyval_visit_list);
  615. g_test_add_func("/keyval/visit/optional", test_keyval_visit_optional);
  616. g_test_add_func("/keyval/visit/alternate", test_keyval_visit_alternate);
  617. g_test_add_func("/keyval/visit/any", test_keyval_visit_any);
  618. g_test_run();
  619. return 0;
  620. }