test-qemu-opts.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000
  1. /*
  2. * QemuOpts unit-tests.
  3. *
  4. * Copyright (C) 2014 Leandro Dorileo <l@dorileo.org>
  5. *
  6. * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
  7. * See the COPYING.LIB file in the top-level directory.
  8. */
  9. #include "qemu/osdep.h"
  10. #include "qemu/units.h"
  11. #include "qemu/option.h"
  12. #include "qemu/option_int.h"
  13. #include "qapi/error.h"
  14. #include "qapi/qmp/qdict.h"
  15. #include "qapi/qmp/qstring.h"
  16. #include "qemu/config-file.h"
  17. static QemuOptsList opts_list_01 = {
  18. .name = "opts_list_01",
  19. .head = QTAILQ_HEAD_INITIALIZER(opts_list_01.head),
  20. .desc = {
  21. {
  22. .name = "str1",
  23. .type = QEMU_OPT_STRING,
  24. .help = "Help texts are preserved in qemu_opts_append",
  25. .def_value_str = "default",
  26. },{
  27. .name = "str2",
  28. .type = QEMU_OPT_STRING,
  29. },{
  30. .name = "str3",
  31. .type = QEMU_OPT_STRING,
  32. },{
  33. .name = "number1",
  34. .type = QEMU_OPT_NUMBER,
  35. .help = "Having help texts only for some options is okay",
  36. },{
  37. .name = "number2",
  38. .type = QEMU_OPT_NUMBER,
  39. },
  40. { /* end of list */ }
  41. },
  42. };
  43. static QemuOptsList opts_list_02 = {
  44. .name = "opts_list_02",
  45. .head = QTAILQ_HEAD_INITIALIZER(opts_list_02.head),
  46. .desc = {
  47. {
  48. .name = "str1",
  49. .type = QEMU_OPT_STRING,
  50. },{
  51. .name = "str2",
  52. .type = QEMU_OPT_STRING,
  53. },{
  54. .name = "bool1",
  55. .type = QEMU_OPT_BOOL,
  56. },{
  57. .name = "bool2",
  58. .type = QEMU_OPT_BOOL,
  59. },{
  60. .name = "size1",
  61. .type = QEMU_OPT_SIZE,
  62. },{
  63. .name = "size2",
  64. .type = QEMU_OPT_SIZE,
  65. },{
  66. .name = "size3",
  67. .type = QEMU_OPT_SIZE,
  68. },
  69. { /* end of list */ }
  70. },
  71. };
  72. static QemuOptsList opts_list_03 = {
  73. .name = "opts_list_03",
  74. .implied_opt_name = "implied",
  75. .head = QTAILQ_HEAD_INITIALIZER(opts_list_03.head),
  76. .desc = {
  77. /* no elements => accept any params */
  78. { /* end of list */ }
  79. },
  80. };
  81. static void register_opts(void)
  82. {
  83. qemu_add_opts(&opts_list_01);
  84. qemu_add_opts(&opts_list_02);
  85. qemu_add_opts(&opts_list_03);
  86. }
  87. static void test_find_unknown_opts(void)
  88. {
  89. QemuOptsList *list;
  90. Error *err = NULL;
  91. /* should not return anything, we don't have an "unknown" option */
  92. list = qemu_find_opts_err("unknown", &err);
  93. g_assert(list == NULL);
  94. error_free_or_abort(&err);
  95. }
  96. static void test_qemu_find_opts(void)
  97. {
  98. QemuOptsList *list;
  99. /* we have an "opts_list_01" option, should return it */
  100. list = qemu_find_opts("opts_list_01");
  101. g_assert(list != NULL);
  102. g_assert_cmpstr(list->name, ==, "opts_list_01");
  103. }
  104. static void test_qemu_opts_create(void)
  105. {
  106. QemuOptsList *list;
  107. QemuOpts *opts;
  108. list = qemu_find_opts("opts_list_01");
  109. g_assert(list != NULL);
  110. g_assert(QTAILQ_EMPTY(&list->head));
  111. g_assert_cmpstr(list->name, ==, "opts_list_01");
  112. /* should not find anything at this point */
  113. opts = qemu_opts_find(list, NULL);
  114. g_assert(opts == NULL);
  115. /* create the opts */
  116. opts = qemu_opts_create(list, NULL, 0, &error_abort);
  117. g_assert(opts != NULL);
  118. g_assert(!QTAILQ_EMPTY(&list->head));
  119. /* now we've create the opts, must find it */
  120. opts = qemu_opts_find(list, NULL);
  121. g_assert(opts != NULL);
  122. qemu_opts_del(opts);
  123. /* should not find anything at this point */
  124. opts = qemu_opts_find(list, NULL);
  125. g_assert(opts == NULL);
  126. }
  127. static void test_qemu_opt_get(void)
  128. {
  129. QemuOptsList *list;
  130. QemuOpts *opts;
  131. const char *opt = NULL;
  132. list = qemu_find_opts("opts_list_01");
  133. g_assert(list != NULL);
  134. g_assert(QTAILQ_EMPTY(&list->head));
  135. g_assert_cmpstr(list->name, ==, "opts_list_01");
  136. /* should not find anything at this point */
  137. opts = qemu_opts_find(list, NULL);
  138. g_assert(opts == NULL);
  139. /* create the opts */
  140. opts = qemu_opts_create(list, NULL, 0, &error_abort);
  141. g_assert(opts != NULL);
  142. g_assert(!QTAILQ_EMPTY(&list->head));
  143. /* haven't set anything to str2 yet */
  144. opt = qemu_opt_get(opts, "str2");
  145. g_assert(opt == NULL);
  146. qemu_opt_set(opts, "str2", "value", &error_abort);
  147. /* now we have set str2, should know about it */
  148. opt = qemu_opt_get(opts, "str2");
  149. g_assert_cmpstr(opt, ==, "value");
  150. qemu_opt_set(opts, "str2", "value2", &error_abort);
  151. /* having reset the value, the returned should be the reset one */
  152. opt = qemu_opt_get(opts, "str2");
  153. g_assert_cmpstr(opt, ==, "value2");
  154. qemu_opts_del(opts);
  155. /* should not find anything at this point */
  156. opts = qemu_opts_find(list, NULL);
  157. g_assert(opts == NULL);
  158. }
  159. static void test_qemu_opt_get_bool(void)
  160. {
  161. Error *err = NULL;
  162. QemuOptsList *list;
  163. QemuOpts *opts;
  164. bool opt;
  165. list = qemu_find_opts("opts_list_02");
  166. g_assert(list != NULL);
  167. g_assert(QTAILQ_EMPTY(&list->head));
  168. g_assert_cmpstr(list->name, ==, "opts_list_02");
  169. /* should not find anything at this point */
  170. opts = qemu_opts_find(list, NULL);
  171. g_assert(opts == NULL);
  172. /* create the opts */
  173. opts = qemu_opts_create(list, NULL, 0, &error_abort);
  174. g_assert(opts != NULL);
  175. g_assert(!QTAILQ_EMPTY(&list->head));
  176. /* haven't set anything to bool1 yet, so defval should be returned */
  177. opt = qemu_opt_get_bool(opts, "bool1", false);
  178. g_assert(opt == false);
  179. qemu_opt_set_bool(opts, "bool1", true, &err);
  180. g_assert(!err);
  181. /* now we have set bool1, should know about it */
  182. opt = qemu_opt_get_bool(opts, "bool1", false);
  183. g_assert(opt == true);
  184. /* having reset the value, opt should be the reset one not defval */
  185. qemu_opt_set_bool(opts, "bool1", false, &err);
  186. g_assert(!err);
  187. opt = qemu_opt_get_bool(opts, "bool1", true);
  188. g_assert(opt == false);
  189. qemu_opts_del(opts);
  190. /* should not find anything at this point */
  191. opts = qemu_opts_find(list, NULL);
  192. g_assert(opts == NULL);
  193. }
  194. static void test_qemu_opt_get_number(void)
  195. {
  196. Error *err = NULL;
  197. QemuOptsList *list;
  198. QemuOpts *opts;
  199. uint64_t opt;
  200. list = qemu_find_opts("opts_list_01");
  201. g_assert(list != NULL);
  202. g_assert(QTAILQ_EMPTY(&list->head));
  203. g_assert_cmpstr(list->name, ==, "opts_list_01");
  204. /* should not find anything at this point */
  205. opts = qemu_opts_find(list, NULL);
  206. g_assert(opts == NULL);
  207. /* create the opts */
  208. opts = qemu_opts_create(list, NULL, 0, &error_abort);
  209. g_assert(opts != NULL);
  210. g_assert(!QTAILQ_EMPTY(&list->head));
  211. /* haven't set anything to number1 yet, so defval should be returned */
  212. opt = qemu_opt_get_number(opts, "number1", 5);
  213. g_assert(opt == 5);
  214. qemu_opt_set_number(opts, "number1", 10, &err);
  215. g_assert(!err);
  216. /* now we have set number1, should know about it */
  217. opt = qemu_opt_get_number(opts, "number1", 5);
  218. g_assert(opt == 10);
  219. /* having reset it, the returned should be the reset one not defval */
  220. qemu_opt_set_number(opts, "number1", 15, &err);
  221. g_assert(!err);
  222. opt = qemu_opt_get_number(opts, "number1", 5);
  223. g_assert(opt == 15);
  224. qemu_opts_del(opts);
  225. /* should not find anything at this point */
  226. opts = qemu_opts_find(list, NULL);
  227. g_assert(opts == NULL);
  228. }
  229. static void test_qemu_opt_get_size(void)
  230. {
  231. QemuOptsList *list;
  232. QemuOpts *opts;
  233. uint64_t opt;
  234. QDict *dict;
  235. list = qemu_find_opts("opts_list_02");
  236. g_assert(list != NULL);
  237. g_assert(QTAILQ_EMPTY(&list->head));
  238. g_assert_cmpstr(list->name, ==, "opts_list_02");
  239. /* should not find anything at this point */
  240. opts = qemu_opts_find(list, NULL);
  241. g_assert(opts == NULL);
  242. /* create the opts */
  243. opts = qemu_opts_create(list, NULL, 0, &error_abort);
  244. g_assert(opts != NULL);
  245. g_assert(!QTAILQ_EMPTY(&list->head));
  246. /* haven't set anything to size1 yet, so defval should be returned */
  247. opt = qemu_opt_get_size(opts, "size1", 5);
  248. g_assert(opt == 5);
  249. dict = qdict_new();
  250. g_assert(dict != NULL);
  251. qdict_put_str(dict, "size1", "10");
  252. qemu_opts_absorb_qdict(opts, dict, &error_abort);
  253. g_assert(error_abort == NULL);
  254. /* now we have set size1, should know about it */
  255. opt = qemu_opt_get_size(opts, "size1", 5);
  256. g_assert(opt == 10);
  257. /* reset value */
  258. qdict_put_str(dict, "size1", "15");
  259. qemu_opts_absorb_qdict(opts, dict, &error_abort);
  260. g_assert(error_abort == NULL);
  261. /* test the reset value */
  262. opt = qemu_opt_get_size(opts, "size1", 5);
  263. g_assert(opt == 15);
  264. qdict_del(dict, "size1");
  265. g_free(dict);
  266. qemu_opts_del(opts);
  267. /* should not find anything at this point */
  268. opts = qemu_opts_find(list, NULL);
  269. g_assert(opts == NULL);
  270. }
  271. static void test_qemu_opt_unset(void)
  272. {
  273. QemuOpts *opts;
  274. const char *value;
  275. int ret;
  276. /* dynamically initialized (parsed) opts */
  277. opts = qemu_opts_parse(&opts_list_03, "key=value", false, NULL);
  278. g_assert(opts != NULL);
  279. /* check default/parsed value */
  280. value = qemu_opt_get(opts, "key");
  281. g_assert_cmpstr(value, ==, "value");
  282. /* reset it to value2 */
  283. qemu_opt_set(opts, "key", "value2", &error_abort);
  284. value = qemu_opt_get(opts, "key");
  285. g_assert_cmpstr(value, ==, "value2");
  286. /* unset, valid only for "accept any" */
  287. ret = qemu_opt_unset(opts, "key");
  288. g_assert(ret == 0);
  289. /* after reset the value should be the parsed/default one */
  290. value = qemu_opt_get(opts, "key");
  291. g_assert_cmpstr(value, ==, "value");
  292. qemu_opts_del(opts);
  293. }
  294. static void test_qemu_opts_reset(void)
  295. {
  296. Error *err = NULL;
  297. QemuOptsList *list;
  298. QemuOpts *opts;
  299. uint64_t opt;
  300. list = qemu_find_opts("opts_list_01");
  301. g_assert(list != NULL);
  302. g_assert(QTAILQ_EMPTY(&list->head));
  303. g_assert_cmpstr(list->name, ==, "opts_list_01");
  304. /* should not find anything at this point */
  305. opts = qemu_opts_find(list, NULL);
  306. g_assert(opts == NULL);
  307. /* create the opts */
  308. opts = qemu_opts_create(list, NULL, 0, &error_abort);
  309. g_assert(opts != NULL);
  310. g_assert(!QTAILQ_EMPTY(&list->head));
  311. /* haven't set anything to number1 yet, so defval should be returned */
  312. opt = qemu_opt_get_number(opts, "number1", 5);
  313. g_assert(opt == 5);
  314. qemu_opt_set_number(opts, "number1", 10, &err);
  315. g_assert(!err);
  316. /* now we have set number1, should know about it */
  317. opt = qemu_opt_get_number(opts, "number1", 5);
  318. g_assert(opt == 10);
  319. qemu_opts_reset(list);
  320. /* should not find anything at this point */
  321. opts = qemu_opts_find(list, NULL);
  322. g_assert(opts == NULL);
  323. }
  324. static void test_qemu_opts_set(void)
  325. {
  326. Error *err = NULL;
  327. QemuOptsList *list;
  328. QemuOpts *opts;
  329. const char *opt;
  330. list = qemu_find_opts("opts_list_01");
  331. g_assert(list != NULL);
  332. g_assert(QTAILQ_EMPTY(&list->head));
  333. g_assert_cmpstr(list->name, ==, "opts_list_01");
  334. /* should not find anything at this point */
  335. opts = qemu_opts_find(list, NULL);
  336. g_assert(opts == NULL);
  337. /* implicitly create opts and set str3 value */
  338. qemu_opts_set(list, NULL, "str3", "value", &err);
  339. g_assert(!err);
  340. g_assert(!QTAILQ_EMPTY(&list->head));
  341. /* get the just created opts */
  342. opts = qemu_opts_find(list, NULL);
  343. g_assert(opts != NULL);
  344. /* check the str3 value */
  345. opt = qemu_opt_get(opts, "str3");
  346. g_assert_cmpstr(opt, ==, "value");
  347. qemu_opts_del(opts);
  348. /* should not find anything at this point */
  349. opts = qemu_opts_find(list, NULL);
  350. g_assert(opts == NULL);
  351. }
  352. static int opts_count_iter(void *opaque, const char *name, const char *value,
  353. Error **errp)
  354. {
  355. (*(size_t *)opaque)++;
  356. return 0;
  357. }
  358. static size_t opts_count(QemuOpts *opts)
  359. {
  360. size_t n = 0;
  361. qemu_opt_foreach(opts, opts_count_iter, &n, NULL);
  362. return n;
  363. }
  364. static void test_opts_parse(void)
  365. {
  366. Error *err = NULL;
  367. QemuOpts *opts;
  368. /* Nothing */
  369. opts = qemu_opts_parse(&opts_list_03, "", false, &error_abort);
  370. g_assert_cmpuint(opts_count(opts), ==, 0);
  371. /* Empty key */
  372. opts = qemu_opts_parse(&opts_list_03, "=val", false, &error_abort);
  373. g_assert_cmpuint(opts_count(opts), ==, 1);
  374. g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "val");
  375. /* Multiple keys, last one wins */
  376. opts = qemu_opts_parse(&opts_list_03, "a=1,b=2,,x,a=3",
  377. false, &error_abort);
  378. g_assert_cmpuint(opts_count(opts), ==, 3);
  379. g_assert_cmpstr(qemu_opt_get(opts, "a"), ==, "3");
  380. g_assert_cmpstr(qemu_opt_get(opts, "b"), ==, "2,x");
  381. /* Except when it doesn't */
  382. opts = qemu_opts_parse(&opts_list_03, "id=foo,id=bar",
  383. false, &error_abort);
  384. g_assert_cmpuint(opts_count(opts), ==, 0);
  385. g_assert_cmpstr(qemu_opts_id(opts), ==, "foo");
  386. /* TODO Cover low-level access to repeated keys */
  387. /* Trailing comma is ignored */
  388. opts = qemu_opts_parse(&opts_list_03, "x=y,", false, &error_abort);
  389. g_assert_cmpuint(opts_count(opts), ==, 1);
  390. g_assert_cmpstr(qemu_opt_get(opts, "x"), ==, "y");
  391. /* Except when it isn't */
  392. opts = qemu_opts_parse(&opts_list_03, ",", false, &error_abort);
  393. g_assert_cmpuint(opts_count(opts), ==, 1);
  394. g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "on");
  395. /* Duplicate ID */
  396. opts = qemu_opts_parse(&opts_list_03, "x=y,id=foo", false, &err);
  397. error_free_or_abort(&err);
  398. g_assert(!opts);
  399. /* TODO Cover .merge_lists = true */
  400. /* Buggy ID recognition */
  401. opts = qemu_opts_parse(&opts_list_03, "x=,,id=bar", false, &error_abort);
  402. g_assert_cmpuint(opts_count(opts), ==, 1);
  403. g_assert_cmpstr(qemu_opts_id(opts), ==, "bar"); /* BUG */
  404. g_assert_cmpstr(qemu_opt_get(opts, "x"), ==, ",id=bar");
  405. /* Anti-social ID */
  406. opts = qemu_opts_parse(&opts_list_01, "id=666", false, &err);
  407. error_free_or_abort(&err);
  408. g_assert(!opts);
  409. /* Implied value */
  410. opts = qemu_opts_parse(&opts_list_03, "an,noaus,noaus=",
  411. false, &error_abort);
  412. g_assert_cmpuint(opts_count(opts), ==, 3);
  413. g_assert_cmpstr(qemu_opt_get(opts, "an"), ==, "on");
  414. g_assert_cmpstr(qemu_opt_get(opts, "aus"), ==, "off");
  415. g_assert_cmpstr(qemu_opt_get(opts, "noaus"), ==, "");
  416. /* Implied value, negated empty key */
  417. opts = qemu_opts_parse(&opts_list_03, "no", false, &error_abort);
  418. g_assert_cmpuint(opts_count(opts), ==, 1);
  419. g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "off");
  420. /* Implied key */
  421. opts = qemu_opts_parse(&opts_list_03, "an,noaus,noaus=", true,
  422. &error_abort);
  423. g_assert_cmpuint(opts_count(opts), ==, 3);
  424. g_assert_cmpstr(qemu_opt_get(opts, "implied"), ==, "an");
  425. g_assert_cmpstr(qemu_opt_get(opts, "aus"), ==, "off");
  426. g_assert_cmpstr(qemu_opt_get(opts, "noaus"), ==, "");
  427. /* Implied key with empty value */
  428. opts = qemu_opts_parse(&opts_list_03, ",", true, &error_abort);
  429. g_assert_cmpuint(opts_count(opts), ==, 1);
  430. g_assert_cmpstr(qemu_opt_get(opts, "implied"), ==, "");
  431. /* Implied key with comma value */
  432. opts = qemu_opts_parse(&opts_list_03, ",,,a=1", true, &error_abort);
  433. g_assert_cmpuint(opts_count(opts), ==, 2);
  434. g_assert_cmpstr(qemu_opt_get(opts, "implied"), ==, ",");
  435. g_assert_cmpstr(qemu_opt_get(opts, "a"), ==, "1");
  436. /* Empty key is not an implied key */
  437. opts = qemu_opts_parse(&opts_list_03, "=val", true, &error_abort);
  438. g_assert_cmpuint(opts_count(opts), ==, 1);
  439. g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "val");
  440. /* Unknown key */
  441. opts = qemu_opts_parse(&opts_list_01, "nonexistent=", false, &err);
  442. error_free_or_abort(&err);
  443. g_assert(!opts);
  444. qemu_opts_reset(&opts_list_01);
  445. qemu_opts_reset(&opts_list_03);
  446. }
  447. static void test_opts_parse_bool(void)
  448. {
  449. Error *err = NULL;
  450. QemuOpts *opts;
  451. opts = qemu_opts_parse(&opts_list_02, "bool1=on,bool2=off",
  452. false, &error_abort);
  453. g_assert_cmpuint(opts_count(opts), ==, 2);
  454. g_assert(qemu_opt_get_bool(opts, "bool1", false));
  455. g_assert(!qemu_opt_get_bool(opts, "bool2", true));
  456. opts = qemu_opts_parse(&opts_list_02, "bool1=offer", false, &err);
  457. error_free_or_abort(&err);
  458. g_assert(!opts);
  459. qemu_opts_reset(&opts_list_02);
  460. }
  461. static void test_opts_parse_number(void)
  462. {
  463. Error *err = NULL;
  464. QemuOpts *opts;
  465. /* Lower limit zero */
  466. opts = qemu_opts_parse(&opts_list_01, "number1=0", false, &error_abort);
  467. g_assert_cmpuint(opts_count(opts), ==, 1);
  468. g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, 0);
  469. /* Upper limit 2^64-1 */
  470. opts = qemu_opts_parse(&opts_list_01,
  471. "number1=18446744073709551615,number2=-1",
  472. false, &error_abort);
  473. g_assert_cmpuint(opts_count(opts), ==, 2);
  474. g_assert_cmphex(qemu_opt_get_number(opts, "number1", 1), ==, UINT64_MAX);
  475. g_assert_cmphex(qemu_opt_get_number(opts, "number2", 0), ==, UINT64_MAX);
  476. /* Above upper limit */
  477. opts = qemu_opts_parse(&opts_list_01, "number1=18446744073709551616",
  478. false, &err);
  479. error_free_or_abort(&err);
  480. g_assert(!opts);
  481. /* Below lower limit */
  482. opts = qemu_opts_parse(&opts_list_01, "number1=-18446744073709551616",
  483. false, &err);
  484. error_free_or_abort(&err);
  485. g_assert(!opts);
  486. /* Hex and octal */
  487. opts = qemu_opts_parse(&opts_list_01, "number1=0x2a,number2=052",
  488. false, &error_abort);
  489. g_assert_cmpuint(opts_count(opts), ==, 2);
  490. g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, 42);
  491. g_assert_cmpuint(qemu_opt_get_number(opts, "number2", 0), ==, 42);
  492. /* Invalid */
  493. opts = qemu_opts_parse(&opts_list_01, "number1=", false, &err);
  494. error_free_or_abort(&err);
  495. g_assert(!opts);
  496. opts = qemu_opts_parse(&opts_list_01, "number1=eins", false, &err);
  497. error_free_or_abort(&err);
  498. g_assert(!opts);
  499. /* Leading whitespace */
  500. opts = qemu_opts_parse(&opts_list_01, "number1= \t42",
  501. false, &error_abort);
  502. g_assert_cmpuint(opts_count(opts), ==, 1);
  503. g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, 42);
  504. /* Trailing crap */
  505. opts = qemu_opts_parse(&opts_list_01, "number1=3.14", false, &err);
  506. error_free_or_abort(&err);
  507. g_assert(!opts);
  508. opts = qemu_opts_parse(&opts_list_01, "number1=08", false, &err);
  509. error_free_or_abort(&err);
  510. g_assert(!opts);
  511. opts = qemu_opts_parse(&opts_list_01, "number1=0 ", false, &err);
  512. error_free_or_abort(&err);
  513. g_assert(!opts);
  514. qemu_opts_reset(&opts_list_01);
  515. }
  516. static void test_opts_parse_size(void)
  517. {
  518. Error *err = NULL;
  519. QemuOpts *opts;
  520. /* Lower limit zero */
  521. opts = qemu_opts_parse(&opts_list_02, "size1=0", false, &error_abort);
  522. g_assert_cmpuint(opts_count(opts), ==, 1);
  523. g_assert_cmpuint(qemu_opt_get_size(opts, "size1", 1), ==, 0);
  524. /* Note: precision is 53 bits since we're parsing with strtod() */
  525. /* Around limit of precision: 2^53-1, 2^53, 2^54 */
  526. opts = qemu_opts_parse(&opts_list_02,
  527. "size1=9007199254740991,"
  528. "size2=9007199254740992,"
  529. "size3=9007199254740993",
  530. false, &error_abort);
  531. g_assert_cmpuint(opts_count(opts), ==, 3);
  532. g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1),
  533. ==, 0x1fffffffffffff);
  534. g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1),
  535. ==, 0x20000000000000);
  536. g_assert_cmphex(qemu_opt_get_size(opts, "size3", 1),
  537. ==, 0x20000000000000);
  538. /* Close to signed upper limit 0x7ffffffffffffc00 (53 msbs set) */
  539. opts = qemu_opts_parse(&opts_list_02,
  540. "size1=9223372036854774784," /* 7ffffffffffffc00 */
  541. "size2=9223372036854775295", /* 7ffffffffffffdff */
  542. false, &error_abort);
  543. g_assert_cmpuint(opts_count(opts), ==, 2);
  544. g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1),
  545. ==, 0x7ffffffffffffc00);
  546. g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1),
  547. ==, 0x7ffffffffffffc00);
  548. /* Close to actual upper limit 0xfffffffffffff800 (53 msbs set) */
  549. opts = qemu_opts_parse(&opts_list_02,
  550. "size1=18446744073709549568," /* fffffffffffff800 */
  551. "size2=18446744073709550591", /* fffffffffffffbff */
  552. false, &error_abort);
  553. g_assert_cmpuint(opts_count(opts), ==, 2);
  554. g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1),
  555. ==, 0xfffffffffffff800);
  556. g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1),
  557. ==, 0xfffffffffffff800);
  558. /* Beyond limits */
  559. opts = qemu_opts_parse(&opts_list_02, "size1=-1", false, &err);
  560. error_free_or_abort(&err);
  561. g_assert(!opts);
  562. opts = qemu_opts_parse(&opts_list_02,
  563. "size1=18446744073709550592", /* fffffffffffffc00 */
  564. false, &err);
  565. error_free_or_abort(&err);
  566. g_assert(!opts);
  567. /* Suffixes */
  568. opts = qemu_opts_parse(&opts_list_02, "size1=8b,size2=1.5k,size3=2M",
  569. false, &error_abort);
  570. g_assert_cmpuint(opts_count(opts), ==, 3);
  571. g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, 8);
  572. g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0), ==, 1536);
  573. g_assert_cmphex(qemu_opt_get_size(opts, "size3", 0), ==, 2 * MiB);
  574. opts = qemu_opts_parse(&opts_list_02, "size1=0.1G,size2=16777215T",
  575. false, &error_abort);
  576. g_assert_cmpuint(opts_count(opts), ==, 2);
  577. g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, GiB / 10);
  578. g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0), ==, 16777215ULL * TiB);
  579. /* Beyond limit with suffix */
  580. opts = qemu_opts_parse(&opts_list_02, "size1=16777216T",
  581. false, &err);
  582. error_free_or_abort(&err);
  583. g_assert(!opts);
  584. /* Trailing crap */
  585. opts = qemu_opts_parse(&opts_list_02, "size1=16E", false, &err);
  586. error_free_or_abort(&err);
  587. g_assert(!opts);
  588. opts = qemu_opts_parse(&opts_list_02, "size1=16Gi", false, &err);
  589. error_free_or_abort(&err);
  590. g_assert(!opts);
  591. qemu_opts_reset(&opts_list_02);
  592. }
  593. static void append_verify_list_01(QemuOptDesc *desc, bool with_overlapping)
  594. {
  595. int i = 0;
  596. if (with_overlapping) {
  597. g_assert_cmpstr(desc[i].name, ==, "str1");
  598. g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING);
  599. g_assert_cmpstr(desc[i].help, ==,
  600. "Help texts are preserved in qemu_opts_append");
  601. g_assert_cmpstr(desc[i].def_value_str, ==, "default");
  602. i++;
  603. g_assert_cmpstr(desc[i].name, ==, "str2");
  604. g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING);
  605. g_assert_cmpstr(desc[i].help, ==, NULL);
  606. g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
  607. i++;
  608. }
  609. g_assert_cmpstr(desc[i].name, ==, "str3");
  610. g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING);
  611. g_assert_cmpstr(desc[i].help, ==, NULL);
  612. g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
  613. i++;
  614. g_assert_cmpstr(desc[i].name, ==, "number1");
  615. g_assert_cmpint(desc[i].type, ==, QEMU_OPT_NUMBER);
  616. g_assert_cmpstr(desc[i].help, ==,
  617. "Having help texts only for some options is okay");
  618. g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
  619. i++;
  620. g_assert_cmpstr(desc[i].name, ==, "number2");
  621. g_assert_cmpint(desc[i].type, ==, QEMU_OPT_NUMBER);
  622. g_assert_cmpstr(desc[i].help, ==, NULL);
  623. g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
  624. i++;
  625. g_assert_cmpstr(desc[i].name, ==, NULL);
  626. }
  627. static void append_verify_list_02(QemuOptDesc *desc)
  628. {
  629. int i = 0;
  630. g_assert_cmpstr(desc[i].name, ==, "str1");
  631. g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING);
  632. g_assert_cmpstr(desc[i].help, ==, NULL);
  633. g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
  634. i++;
  635. g_assert_cmpstr(desc[i].name, ==, "str2");
  636. g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING);
  637. g_assert_cmpstr(desc[i].help, ==, NULL);
  638. g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
  639. i++;
  640. g_assert_cmpstr(desc[i].name, ==, "bool1");
  641. g_assert_cmpint(desc[i].type, ==, QEMU_OPT_BOOL);
  642. g_assert_cmpstr(desc[i].help, ==, NULL);
  643. g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
  644. i++;
  645. g_assert_cmpstr(desc[i].name, ==, "bool2");
  646. g_assert_cmpint(desc[i].type, ==, QEMU_OPT_BOOL);
  647. g_assert_cmpstr(desc[i].help, ==, NULL);
  648. g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
  649. i++;
  650. g_assert_cmpstr(desc[i].name, ==, "size1");
  651. g_assert_cmpint(desc[i].type, ==, QEMU_OPT_SIZE);
  652. g_assert_cmpstr(desc[i].help, ==, NULL);
  653. g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
  654. i++;
  655. g_assert_cmpstr(desc[i].name, ==, "size2");
  656. g_assert_cmpint(desc[i].type, ==, QEMU_OPT_SIZE);
  657. g_assert_cmpstr(desc[i].help, ==, NULL);
  658. g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
  659. i++;
  660. g_assert_cmpstr(desc[i].name, ==, "size3");
  661. g_assert_cmpint(desc[i].type, ==, QEMU_OPT_SIZE);
  662. g_assert_cmpstr(desc[i].help, ==, NULL);
  663. g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
  664. }
  665. static void test_opts_append_to_null(void)
  666. {
  667. QemuOptsList *merged;
  668. merged = qemu_opts_append(NULL, &opts_list_01);
  669. g_assert(merged != &opts_list_01);
  670. g_assert_cmpstr(merged->name, ==, NULL);
  671. g_assert_cmpstr(merged->implied_opt_name, ==, NULL);
  672. g_assert_false(merged->merge_lists);
  673. append_verify_list_01(merged->desc, true);
  674. qemu_opts_free(merged);
  675. }
  676. static void test_opts_append(void)
  677. {
  678. QemuOptsList *first, *merged;
  679. first = qemu_opts_append(NULL, &opts_list_02);
  680. merged = qemu_opts_append(first, &opts_list_01);
  681. g_assert(first != &opts_list_02);
  682. g_assert(merged != &opts_list_01);
  683. g_assert_cmpstr(merged->name, ==, NULL);
  684. g_assert_cmpstr(merged->implied_opt_name, ==, NULL);
  685. g_assert_false(merged->merge_lists);
  686. append_verify_list_02(&merged->desc[0]);
  687. append_verify_list_01(&merged->desc[7], false);
  688. qemu_opts_free(merged);
  689. }
  690. static void test_opts_to_qdict_basic(void)
  691. {
  692. QemuOpts *opts;
  693. QDict *dict;
  694. opts = qemu_opts_parse(&opts_list_01, "str1=foo,str2=,str3=bar,number1=42",
  695. false, &error_abort);
  696. g_assert(opts != NULL);
  697. dict = qemu_opts_to_qdict(opts, NULL);
  698. g_assert(dict != NULL);
  699. g_assert_cmpstr(qdict_get_str(dict, "str1"), ==, "foo");
  700. g_assert_cmpstr(qdict_get_str(dict, "str2"), ==, "");
  701. g_assert_cmpstr(qdict_get_str(dict, "str3"), ==, "bar");
  702. g_assert_cmpstr(qdict_get_str(dict, "number1"), ==, "42");
  703. g_assert_false(qdict_haskey(dict, "number2"));
  704. qobject_unref(dict);
  705. qemu_opts_del(opts);
  706. }
  707. static void test_opts_to_qdict_filtered(void)
  708. {
  709. QemuOptsList *first, *merged;
  710. QemuOpts *opts;
  711. QDict *dict;
  712. first = qemu_opts_append(NULL, &opts_list_02);
  713. merged = qemu_opts_append(first, &opts_list_01);
  714. opts = qemu_opts_parse(merged,
  715. "str1=foo,str2=,str3=bar,bool1=off,number1=42",
  716. false, &error_abort);
  717. g_assert(opts != NULL);
  718. /* Convert to QDict without deleting from opts */
  719. dict = qemu_opts_to_qdict_filtered(opts, NULL, &opts_list_01, false);
  720. g_assert(dict != NULL);
  721. g_assert_cmpstr(qdict_get_str(dict, "str1"), ==, "foo");
  722. g_assert_cmpstr(qdict_get_str(dict, "str2"), ==, "");
  723. g_assert_cmpstr(qdict_get_str(dict, "str3"), ==, "bar");
  724. g_assert_cmpstr(qdict_get_str(dict, "number1"), ==, "42");
  725. g_assert_false(qdict_haskey(dict, "number2"));
  726. g_assert_false(qdict_haskey(dict, "bool1"));
  727. qobject_unref(dict);
  728. dict = qemu_opts_to_qdict_filtered(opts, NULL, &opts_list_02, false);
  729. g_assert(dict != NULL);
  730. g_assert_cmpstr(qdict_get_str(dict, "str1"), ==, "foo");
  731. g_assert_cmpstr(qdict_get_str(dict, "str2"), ==, "");
  732. g_assert_cmpstr(qdict_get_str(dict, "bool1"), ==, "off");
  733. g_assert_false(qdict_haskey(dict, "str3"));
  734. g_assert_false(qdict_haskey(dict, "number1"));
  735. g_assert_false(qdict_haskey(dict, "number2"));
  736. qobject_unref(dict);
  737. /* Now delete converted options from opts */
  738. dict = qemu_opts_to_qdict_filtered(opts, NULL, &opts_list_01, true);
  739. g_assert(dict != NULL);
  740. g_assert_cmpstr(qdict_get_str(dict, "str1"), ==, "foo");
  741. g_assert_cmpstr(qdict_get_str(dict, "str2"), ==, "");
  742. g_assert_cmpstr(qdict_get_str(dict, "str3"), ==, "bar");
  743. g_assert_cmpstr(qdict_get_str(dict, "number1"), ==, "42");
  744. g_assert_false(qdict_haskey(dict, "number2"));
  745. g_assert_false(qdict_haskey(dict, "bool1"));
  746. qobject_unref(dict);
  747. dict = qemu_opts_to_qdict_filtered(opts, NULL, &opts_list_02, true);
  748. g_assert(dict != NULL);
  749. g_assert_cmpstr(qdict_get_str(dict, "bool1"), ==, "off");
  750. g_assert_false(qdict_haskey(dict, "str1"));
  751. g_assert_false(qdict_haskey(dict, "str2"));
  752. g_assert_false(qdict_haskey(dict, "str3"));
  753. g_assert_false(qdict_haskey(dict, "number1"));
  754. g_assert_false(qdict_haskey(dict, "number2"));
  755. qobject_unref(dict);
  756. g_assert_true(QTAILQ_EMPTY(&opts->head));
  757. qemu_opts_del(opts);
  758. qemu_opts_free(merged);
  759. }
  760. static void test_opts_to_qdict_duplicates(void)
  761. {
  762. QemuOpts *opts;
  763. QemuOpt *opt;
  764. QDict *dict;
  765. opts = qemu_opts_parse(&opts_list_03, "foo=a,foo=b", false, &error_abort);
  766. g_assert(opts != NULL);
  767. /* Verify that opts has two options with the same name */
  768. opt = QTAILQ_FIRST(&opts->head);
  769. g_assert_cmpstr(opt->name, ==, "foo");
  770. g_assert_cmpstr(opt->str , ==, "a");
  771. opt = QTAILQ_NEXT(opt, next);
  772. g_assert_cmpstr(opt->name, ==, "foo");
  773. g_assert_cmpstr(opt->str , ==, "b");
  774. opt = QTAILQ_NEXT(opt, next);
  775. g_assert(opt == NULL);
  776. /* In the conversion to QDict, the last one wins */
  777. dict = qemu_opts_to_qdict(opts, NULL);
  778. g_assert(dict != NULL);
  779. g_assert_cmpstr(qdict_get_str(dict, "foo"), ==, "b");
  780. qobject_unref(dict);
  781. /* The last one still wins if entries are deleted, and both are deleted */
  782. dict = qemu_opts_to_qdict_filtered(opts, NULL, NULL, true);
  783. g_assert(dict != NULL);
  784. g_assert_cmpstr(qdict_get_str(dict, "foo"), ==, "b");
  785. qobject_unref(dict);
  786. g_assert_true(QTAILQ_EMPTY(&opts->head));
  787. qemu_opts_del(opts);
  788. }
  789. int main(int argc, char *argv[])
  790. {
  791. register_opts();
  792. g_test_init(&argc, &argv, NULL);
  793. g_test_add_func("/qemu-opts/find_unknown_opts", test_find_unknown_opts);
  794. g_test_add_func("/qemu-opts/find_opts", test_qemu_find_opts);
  795. g_test_add_func("/qemu-opts/opts_create", test_qemu_opts_create);
  796. g_test_add_func("/qemu-opts/opt_get", test_qemu_opt_get);
  797. g_test_add_func("/qemu-opts/opt_get_bool", test_qemu_opt_get_bool);
  798. g_test_add_func("/qemu-opts/opt_get_number", test_qemu_opt_get_number);
  799. g_test_add_func("/qemu-opts/opt_get_size", test_qemu_opt_get_size);
  800. g_test_add_func("/qemu-opts/opt_unset", test_qemu_opt_unset);
  801. g_test_add_func("/qemu-opts/opts_reset", test_qemu_opts_reset);
  802. g_test_add_func("/qemu-opts/opts_set", test_qemu_opts_set);
  803. g_test_add_func("/qemu-opts/opts_parse/general", test_opts_parse);
  804. g_test_add_func("/qemu-opts/opts_parse/bool", test_opts_parse_bool);
  805. g_test_add_func("/qemu-opts/opts_parse/number", test_opts_parse_number);
  806. g_test_add_func("/qemu-opts/opts_parse/size", test_opts_parse_size);
  807. g_test_add_func("/qemu-opts/append_to_null", test_opts_append_to_null);
  808. g_test_add_func("/qemu-opts/append", test_opts_append);
  809. g_test_add_func("/qemu-opts/to_qdict/basic", test_opts_to_qdict_basic);
  810. g_test_add_func("/qemu-opts/to_qdict/filtered", test_opts_to_qdict_filtered);
  811. g_test_add_func("/qemu-opts/to_qdict/duplicates", test_opts_to_qdict_duplicates);
  812. g_test_run();
  813. return 0;
  814. }