2
0

test-string-input-visitor.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. /*
  2. * String Input Visitor unit-tests.
  3. *
  4. * Copyright (C) 2012 Red Hat Inc.
  5. *
  6. * Authors:
  7. * Paolo Bonzini <pbonzini@redhat.com> (based on test-qobject-input-visitor)
  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-common.h"
  14. #include "qapi/error.h"
  15. #include "qapi/string-input-visitor.h"
  16. #include "test-qapi-visit.h"
  17. typedef struct TestInputVisitorData {
  18. Visitor *v;
  19. } TestInputVisitorData;
  20. static void visitor_input_teardown(TestInputVisitorData *data,
  21. const void *unused)
  22. {
  23. if (data->v) {
  24. visit_free(data->v);
  25. data->v = NULL;
  26. }
  27. }
  28. /* This is provided instead of a test setup function so that the JSON
  29. string used by the tests are kept in the test functions (and not
  30. int main()) */
  31. static
  32. Visitor *visitor_input_test_init(TestInputVisitorData *data,
  33. const char *string)
  34. {
  35. visitor_input_teardown(data, NULL);
  36. data->v = string_input_visitor_new(string);
  37. g_assert(data->v);
  38. return data->v;
  39. }
  40. static void test_visitor_in_int(TestInputVisitorData *data,
  41. const void *unused)
  42. {
  43. int64_t res = 0, value = -42;
  44. Error *err = NULL;
  45. Visitor *v;
  46. v = visitor_input_test_init(data, "-42");
  47. visit_type_int(v, NULL, &res, &err);
  48. g_assert(!err);
  49. g_assert_cmpint(res, ==, value);
  50. v = visitor_input_test_init(data, "not an int");
  51. visit_type_int(v, NULL, &res, &err);
  52. error_free_or_abort(&err);
  53. v = visitor_input_test_init(data, "");
  54. visit_type_int(v, NULL, &res, &err);
  55. error_free_or_abort(&err);
  56. }
  57. static void check_ilist(Visitor *v, int64_t *expected, size_t n)
  58. {
  59. int64List *res = NULL;
  60. int64List *tail;
  61. int i;
  62. visit_type_int64List(v, NULL, &res, &error_abort);
  63. tail = res;
  64. for (i = 0; i < n; i++) {
  65. g_assert(tail);
  66. g_assert_cmpint(tail->value, ==, expected[i]);
  67. tail = tail->next;
  68. }
  69. g_assert(!tail);
  70. qapi_free_int64List(res);
  71. }
  72. static void check_ulist(Visitor *v, uint64_t *expected, size_t n)
  73. {
  74. uint64List *res = NULL;
  75. uint64List *tail;
  76. int i;
  77. visit_type_uint64List(v, NULL, &res, &error_abort);
  78. tail = res;
  79. for (i = 0; i < n; i++) {
  80. g_assert(tail);
  81. g_assert_cmpuint(tail->value, ==, expected[i]);
  82. tail = tail->next;
  83. }
  84. g_assert(!tail);
  85. qapi_free_uint64List(res);
  86. }
  87. static void test_visitor_in_intList(TestInputVisitorData *data,
  88. const void *unused)
  89. {
  90. int64_t expect1[] = { 1, 2, 0, 2, 3, 4, 20, 5, 6, 7,
  91. 8, 9, 1, 2, 3, 4, 5, 6, 7, 8 };
  92. int64_t expect2[] = { 32767, -32768, -32767 };
  93. int64_t expect3[] = { INT64_MIN, INT64_MAX };
  94. int64_t expect4[] = { 1 };
  95. int64_t expect5[] = { INT64_MAX - 2, INT64_MAX - 1, INT64_MAX };
  96. Error *err = NULL;
  97. int64List *res = NULL;
  98. Visitor *v;
  99. int64_t val;
  100. /* Valid lists */
  101. v = visitor_input_test_init(data, "1,2,0,2-4,20,5-9,1-8");
  102. check_ilist(v, expect1, ARRAY_SIZE(expect1));
  103. v = visitor_input_test_init(data, "32767,-32768--32767");
  104. check_ilist(v, expect2, ARRAY_SIZE(expect2));
  105. v = visitor_input_test_init(data,
  106. "-9223372036854775808,9223372036854775807");
  107. check_ilist(v, expect3, ARRAY_SIZE(expect3));
  108. v = visitor_input_test_init(data, "1-1");
  109. check_ilist(v, expect4, ARRAY_SIZE(expect4));
  110. v = visitor_input_test_init(data,
  111. "9223372036854775805-9223372036854775807");
  112. check_ilist(v, expect5, ARRAY_SIZE(expect5));
  113. /* Value too large */
  114. v = visitor_input_test_init(data, "9223372036854775808");
  115. visit_type_int64List(v, NULL, &res, &err);
  116. error_free_or_abort(&err);
  117. g_assert(!res);
  118. /* Value too small */
  119. v = visitor_input_test_init(data, "-9223372036854775809");
  120. visit_type_int64List(v, NULL, &res, &err);
  121. error_free_or_abort(&err);
  122. g_assert(!res);
  123. /* Range not ascending */
  124. v = visitor_input_test_init(data, "3-1");
  125. visit_type_int64List(v, NULL, &res, &err);
  126. error_free_or_abort(&err);
  127. g_assert(!res);
  128. v = visitor_input_test_init(data, "9223372036854775807-0");
  129. visit_type_int64List(v, NULL, &res, &err);
  130. error_free_or_abort(&err);
  131. g_assert(!res);
  132. /* Range too big (65536 is the limit against DOS attacks) */
  133. v = visitor_input_test_init(data, "0-65536");
  134. visit_type_int64List(v, NULL, &res, &err);
  135. error_free_or_abort(&err);
  136. g_assert(!res);
  137. /* Empty list */
  138. v = visitor_input_test_init(data, "");
  139. visit_type_int64List(v, NULL, &res, &error_abort);
  140. g_assert(!res);
  141. /* Not a list */
  142. v = visitor_input_test_init(data, "not an int list");
  143. visit_type_int64List(v, NULL, &res, &err);
  144. error_free_or_abort(&err);
  145. g_assert(!res);
  146. /* Unvisited list tail */
  147. v = visitor_input_test_init(data, "0,2-3");
  148. visit_start_list(v, NULL, NULL, 0, &error_abort);
  149. visit_type_int64(v, NULL, &val, &error_abort);
  150. g_assert_cmpint(val, ==, 0);
  151. visit_type_int64(v, NULL, &val, &error_abort);
  152. g_assert_cmpint(val, ==, 2);
  153. visit_check_list(v, &err);
  154. error_free_or_abort(&err);
  155. visit_end_list(v, NULL);
  156. /* Visit beyond end of list */
  157. v = visitor_input_test_init(data, "0");
  158. visit_start_list(v, NULL, NULL, 0, &error_abort);
  159. visit_type_int64(v, NULL, &val, &err);
  160. g_assert_cmpint(val, ==, 0);
  161. visit_type_int64(v, NULL, &val, &err);
  162. error_free_or_abort(&err);
  163. visit_check_list(v, &error_abort);
  164. visit_end_list(v, NULL);
  165. }
  166. static void test_visitor_in_uintList(TestInputVisitorData *data,
  167. const void *unused)
  168. {
  169. uint64_t expect1[] = { 1, 2, 0, 2, 3, 4, 20, 5, 6, 7,
  170. 8, 9, 1, 2, 3, 4, 5, 6, 7, 8 };
  171. uint64_t expect2[] = { 32767, -32768, -32767 };
  172. uint64_t expect3[] = { INT64_MIN, INT64_MAX };
  173. uint64_t expect4[] = { 1 };
  174. uint64_t expect5[] = { UINT64_MAX };
  175. uint64_t expect6[] = { UINT64_MAX - 2, UINT64_MAX - 1, UINT64_MAX };
  176. Error *err = NULL;
  177. uint64List *res = NULL;
  178. Visitor *v;
  179. uint64_t val;
  180. /* Valid lists */
  181. v = visitor_input_test_init(data, "1,2,0,2-4,20,5-9,1-8");
  182. check_ulist(v, expect1, ARRAY_SIZE(expect1));
  183. v = visitor_input_test_init(data, "32767,-32768--32767");
  184. check_ulist(v, expect2, ARRAY_SIZE(expect2));
  185. v = visitor_input_test_init(data,
  186. "-9223372036854775808,9223372036854775807");
  187. check_ulist(v, expect3, ARRAY_SIZE(expect3));
  188. v = visitor_input_test_init(data, "1-1");
  189. check_ulist(v, expect4, ARRAY_SIZE(expect4));
  190. v = visitor_input_test_init(data, "18446744073709551615");
  191. check_ulist(v, expect5, ARRAY_SIZE(expect5));
  192. v = visitor_input_test_init(data,
  193. "18446744073709551613-18446744073709551615");
  194. check_ulist(v, expect6, ARRAY_SIZE(expect6));
  195. /* Value too large */
  196. v = visitor_input_test_init(data, "18446744073709551616");
  197. visit_type_uint64List(v, NULL, &res, &err);
  198. error_free_or_abort(&err);
  199. g_assert(!res);
  200. /* Value too small */
  201. v = visitor_input_test_init(data, "-18446744073709551616");
  202. visit_type_uint64List(v, NULL, &res, &err);
  203. error_free_or_abort(&err);
  204. g_assert(!res);
  205. /* Range not ascending */
  206. v = visitor_input_test_init(data, "3-1");
  207. visit_type_uint64List(v, NULL, &res, &err);
  208. error_free_or_abort(&err);
  209. g_assert(!res);
  210. v = visitor_input_test_init(data, "18446744073709551615-0");
  211. visit_type_uint64List(v, NULL, &res, &err);
  212. error_free_or_abort(&err);
  213. g_assert(!res);
  214. /* Range too big (65536 is the limit against DOS attacks) */
  215. v = visitor_input_test_init(data, "0-65536");
  216. visit_type_uint64List(v, NULL, &res, &err);
  217. error_free_or_abort(&err);
  218. g_assert(!res);
  219. /* Empty list */
  220. v = visitor_input_test_init(data, "");
  221. visit_type_uint64List(v, NULL, &res, &error_abort);
  222. g_assert(!res);
  223. /* Not a list */
  224. v = visitor_input_test_init(data, "not an uint list");
  225. visit_type_uint64List(v, NULL, &res, &err);
  226. error_free_or_abort(&err);
  227. g_assert(!res);
  228. /* Unvisited list tail */
  229. v = visitor_input_test_init(data, "0,2-3");
  230. visit_start_list(v, NULL, NULL, 0, &error_abort);
  231. visit_type_uint64(v, NULL, &val, &error_abort);
  232. g_assert_cmpuint(val, ==, 0);
  233. visit_type_uint64(v, NULL, &val, &error_abort);
  234. g_assert_cmpuint(val, ==, 2);
  235. visit_check_list(v, &err);
  236. error_free_or_abort(&err);
  237. visit_end_list(v, NULL);
  238. /* Visit beyond end of list */
  239. v = visitor_input_test_init(data, "0");
  240. visit_start_list(v, NULL, NULL, 0, &error_abort);
  241. visit_type_uint64(v, NULL, &val, &err);
  242. g_assert_cmpuint(val, ==, 0);
  243. visit_type_uint64(v, NULL, &val, &err);
  244. error_free_or_abort(&err);
  245. visit_check_list(v, &error_abort);
  246. visit_end_list(v, NULL);
  247. }
  248. static void test_visitor_in_bool(TestInputVisitorData *data,
  249. const void *unused)
  250. {
  251. Error *err = NULL;
  252. bool res = false;
  253. Visitor *v;
  254. v = visitor_input_test_init(data, "true");
  255. visit_type_bool(v, NULL, &res, &err);
  256. g_assert(!err);
  257. g_assert_cmpint(res, ==, true);
  258. v = visitor_input_test_init(data, "yes");
  259. visit_type_bool(v, NULL, &res, &err);
  260. g_assert(!err);
  261. g_assert_cmpint(res, ==, true);
  262. v = visitor_input_test_init(data, "on");
  263. visit_type_bool(v, NULL, &res, &err);
  264. g_assert(!err);
  265. g_assert_cmpint(res, ==, true);
  266. v = visitor_input_test_init(data, "false");
  267. visit_type_bool(v, NULL, &res, &err);
  268. g_assert(!err);
  269. g_assert_cmpint(res, ==, false);
  270. v = visitor_input_test_init(data, "no");
  271. visit_type_bool(v, NULL, &res, &err);
  272. g_assert(!err);
  273. g_assert_cmpint(res, ==, false);
  274. v = visitor_input_test_init(data, "off");
  275. visit_type_bool(v, NULL, &res, &err);
  276. g_assert(!err);
  277. g_assert_cmpint(res, ==, false);
  278. }
  279. static void test_visitor_in_number(TestInputVisitorData *data,
  280. const void *unused)
  281. {
  282. double res = 0, value = 3.14;
  283. Error *err = NULL;
  284. Visitor *v;
  285. v = visitor_input_test_init(data, "3.14");
  286. visit_type_number(v, NULL, &res, &err);
  287. g_assert(!err);
  288. g_assert_cmpfloat(res, ==, value);
  289. /* NaN and infinity has to be rejected */
  290. v = visitor_input_test_init(data, "NaN");
  291. visit_type_number(v, NULL, &res, &err);
  292. error_free_or_abort(&err);
  293. v = visitor_input_test_init(data, "inf");
  294. visit_type_number(v, NULL, &res, &err);
  295. error_free_or_abort(&err);
  296. }
  297. static void test_visitor_in_string(TestInputVisitorData *data,
  298. const void *unused)
  299. {
  300. char *res = NULL, *value = (char *) "Q E M U";
  301. Error *err = NULL;
  302. Visitor *v;
  303. v = visitor_input_test_init(data, value);
  304. visit_type_str(v, NULL, &res, &err);
  305. g_assert(!err);
  306. g_assert_cmpstr(res, ==, value);
  307. g_free(res);
  308. }
  309. static void test_visitor_in_enum(TestInputVisitorData *data,
  310. const void *unused)
  311. {
  312. Error *err = NULL;
  313. Visitor *v;
  314. EnumOne i;
  315. for (i = 0; i < ENUM_ONE__MAX; i++) {
  316. EnumOne res = -1;
  317. v = visitor_input_test_init(data, EnumOne_str(i));
  318. visit_type_EnumOne(v, NULL, &res, &err);
  319. g_assert(!err);
  320. g_assert_cmpint(i, ==, res);
  321. }
  322. }
  323. /* Try to crash the visitors */
  324. static void test_visitor_in_fuzz(TestInputVisitorData *data,
  325. const void *unused)
  326. {
  327. int64_t ires;
  328. intList *ilres;
  329. bool bres;
  330. double nres;
  331. char *sres;
  332. EnumOne eres;
  333. Visitor *v;
  334. unsigned int i;
  335. char buf[10000];
  336. for (i = 0; i < 100; i++) {
  337. unsigned int j, k;
  338. j = g_test_rand_int_range(0, sizeof(buf) - 1);
  339. buf[j] = '\0';
  340. for (k = 0; k != j; k++) {
  341. buf[k] = (char)g_test_rand_int_range(0, 256);
  342. }
  343. v = visitor_input_test_init(data, buf);
  344. visit_type_int(v, NULL, &ires, NULL);
  345. v = visitor_input_test_init(data, buf);
  346. visit_type_intList(v, NULL, &ilres, NULL);
  347. qapi_free_intList(ilres);
  348. v = visitor_input_test_init(data, buf);
  349. visit_type_bool(v, NULL, &bres, NULL);
  350. v = visitor_input_test_init(data, buf);
  351. visit_type_number(v, NULL, &nres, NULL);
  352. v = visitor_input_test_init(data, buf);
  353. sres = NULL;
  354. visit_type_str(v, NULL, &sres, NULL);
  355. g_free(sres);
  356. v = visitor_input_test_init(data, buf);
  357. visit_type_EnumOne(v, NULL, &eres, NULL);
  358. }
  359. }
  360. static void input_visitor_test_add(const char *testpath,
  361. TestInputVisitorData *data,
  362. void (*test_func)(TestInputVisitorData *data, const void *user_data))
  363. {
  364. g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
  365. visitor_input_teardown);
  366. }
  367. int main(int argc, char **argv)
  368. {
  369. TestInputVisitorData in_visitor_data;
  370. g_test_init(&argc, &argv, NULL);
  371. input_visitor_test_add("/string-visitor/input/int",
  372. &in_visitor_data, test_visitor_in_int);
  373. input_visitor_test_add("/string-visitor/input/intList",
  374. &in_visitor_data, test_visitor_in_intList);
  375. input_visitor_test_add("/string-visitor/input/uintList",
  376. &in_visitor_data, test_visitor_in_uintList);
  377. input_visitor_test_add("/string-visitor/input/bool",
  378. &in_visitor_data, test_visitor_in_bool);
  379. input_visitor_test_add("/string-visitor/input/number",
  380. &in_visitor_data, test_visitor_in_number);
  381. input_visitor_test_add("/string-visitor/input/string",
  382. &in_visitor_data, test_visitor_in_string);
  383. input_visitor_test_add("/string-visitor/input/enum",
  384. &in_visitor_data, test_visitor_in_enum);
  385. input_visitor_test_add("/string-visitor/input/fuzz",
  386. &in_visitor_data, test_visitor_in_fuzz);
  387. g_test_run();
  388. return 0;
  389. }