test-string-input-visitor.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  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. uint64_t expect5[] = { UINT64_MAX };
  96. Error *err = NULL;
  97. int64List *res = NULL;
  98. int64List *tail;
  99. Visitor *v;
  100. int64_t val;
  101. /* Valid lists */
  102. v = visitor_input_test_init(data, "1,2,0,2-4,20,5-9,1-8");
  103. check_ilist(v, expect1, ARRAY_SIZE(expect1));
  104. v = visitor_input_test_init(data, "32767,-32768--32767");
  105. check_ilist(v, expect2, ARRAY_SIZE(expect2));
  106. v = visitor_input_test_init(data,
  107. "-9223372036854775808,9223372036854775807");
  108. check_ilist(v, expect3, ARRAY_SIZE(expect3));
  109. v = visitor_input_test_init(data, "1-1");
  110. check_ilist(v, expect4, ARRAY_SIZE(expect4));
  111. v = visitor_input_test_init(data, "18446744073709551615");
  112. check_ulist(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. /* Would be simpler if the visitor genuinely supported virtual walks */
  149. visit_start_list(v, NULL, (GenericList **)&res, sizeof(*res),
  150. &error_abort);
  151. tail = res;
  152. visit_type_int64(v, NULL, &tail->value, &error_abort);
  153. g_assert_cmpint(tail->value, ==, 0);
  154. tail = (int64List *)visit_next_list(v, (GenericList *)tail, sizeof(*res));
  155. g_assert(tail);
  156. visit_type_int64(v, NULL, &tail->value, &error_abort);
  157. g_assert_cmpint(tail->value, ==, 2);
  158. tail = (int64List *)visit_next_list(v, (GenericList *)tail, sizeof(*res));
  159. g_assert(tail);
  160. visit_check_list(v, &err);
  161. error_free_or_abort(&err);
  162. visit_end_list(v, (void **)&res);
  163. qapi_free_int64List(res);
  164. /* Visit beyond end of list */
  165. v = visitor_input_test_init(data, "0");
  166. visit_start_list(v, NULL, (GenericList **)&res, sizeof(*res),
  167. &error_abort);
  168. tail = res;
  169. visit_type_int64(v, NULL, &tail->value, &err);
  170. g_assert_cmpint(tail->value, ==, 0);
  171. visit_type_int64(v, NULL, &val, &err);
  172. error_free_or_abort(&err);
  173. visit_check_list(v, &error_abort);
  174. visit_end_list(v, (void **)&res);
  175. qapi_free_int64List(res);
  176. }
  177. static void test_visitor_in_bool(TestInputVisitorData *data,
  178. const void *unused)
  179. {
  180. Error *err = NULL;
  181. bool res = false;
  182. Visitor *v;
  183. v = visitor_input_test_init(data, "true");
  184. visit_type_bool(v, NULL, &res, &err);
  185. g_assert(!err);
  186. g_assert_cmpint(res, ==, true);
  187. v = visitor_input_test_init(data, "yes");
  188. visit_type_bool(v, NULL, &res, &err);
  189. g_assert(!err);
  190. g_assert_cmpint(res, ==, true);
  191. v = visitor_input_test_init(data, "on");
  192. visit_type_bool(v, NULL, &res, &err);
  193. g_assert(!err);
  194. g_assert_cmpint(res, ==, true);
  195. v = visitor_input_test_init(data, "false");
  196. visit_type_bool(v, NULL, &res, &err);
  197. g_assert(!err);
  198. g_assert_cmpint(res, ==, false);
  199. v = visitor_input_test_init(data, "no");
  200. visit_type_bool(v, NULL, &res, &err);
  201. g_assert(!err);
  202. g_assert_cmpint(res, ==, false);
  203. v = visitor_input_test_init(data, "off");
  204. visit_type_bool(v, NULL, &res, &err);
  205. g_assert(!err);
  206. g_assert_cmpint(res, ==, false);
  207. }
  208. static void test_visitor_in_number(TestInputVisitorData *data,
  209. const void *unused)
  210. {
  211. double res = 0, value = 3.14;
  212. Error *err = NULL;
  213. Visitor *v;
  214. v = visitor_input_test_init(data, "3.14");
  215. visit_type_number(v, NULL, &res, &err);
  216. g_assert(!err);
  217. g_assert_cmpfloat(res, ==, value);
  218. /* NaN and infinity has to be rejected */
  219. v = visitor_input_test_init(data, "NaN");
  220. visit_type_number(v, NULL, &res, &err);
  221. error_free_or_abort(&err);
  222. v = visitor_input_test_init(data, "inf");
  223. visit_type_number(v, NULL, &res, &err);
  224. error_free_or_abort(&err);
  225. }
  226. static void test_visitor_in_string(TestInputVisitorData *data,
  227. const void *unused)
  228. {
  229. char *res = NULL, *value = (char *) "Q E M U";
  230. Error *err = NULL;
  231. Visitor *v;
  232. v = visitor_input_test_init(data, value);
  233. visit_type_str(v, NULL, &res, &err);
  234. g_assert(!err);
  235. g_assert_cmpstr(res, ==, value);
  236. g_free(res);
  237. }
  238. static void test_visitor_in_enum(TestInputVisitorData *data,
  239. const void *unused)
  240. {
  241. Error *err = NULL;
  242. Visitor *v;
  243. EnumOne i;
  244. for (i = 0; i < ENUM_ONE__MAX; i++) {
  245. EnumOne res = -1;
  246. v = visitor_input_test_init(data, EnumOne_str(i));
  247. visit_type_EnumOne(v, NULL, &res, &err);
  248. g_assert(!err);
  249. g_assert_cmpint(i, ==, res);
  250. }
  251. }
  252. /* Try to crash the visitors */
  253. static void test_visitor_in_fuzz(TestInputVisitorData *data,
  254. const void *unused)
  255. {
  256. int64_t ires;
  257. intList *ilres;
  258. bool bres;
  259. double nres;
  260. char *sres;
  261. EnumOne eres;
  262. Visitor *v;
  263. unsigned int i;
  264. char buf[10000];
  265. for (i = 0; i < 100; i++) {
  266. unsigned int j;
  267. j = g_test_rand_int_range(0, sizeof(buf) - 1);
  268. buf[j] = '\0';
  269. if (j != 0) {
  270. for (j--; j != 0; j--) {
  271. buf[j - 1] = (char)g_test_rand_int_range(0, 256);
  272. }
  273. }
  274. v = visitor_input_test_init(data, buf);
  275. visit_type_int(v, NULL, &ires, NULL);
  276. v = visitor_input_test_init(data, buf);
  277. visit_type_intList(v, NULL, &ilres, NULL);
  278. qapi_free_intList(ilres);
  279. v = visitor_input_test_init(data, buf);
  280. visit_type_bool(v, NULL, &bres, NULL);
  281. v = visitor_input_test_init(data, buf);
  282. visit_type_number(v, NULL, &nres, NULL);
  283. v = visitor_input_test_init(data, buf);
  284. sres = NULL;
  285. visit_type_str(v, NULL, &sres, NULL);
  286. g_free(sres);
  287. v = visitor_input_test_init(data, buf);
  288. visit_type_EnumOne(v, NULL, &eres, NULL);
  289. }
  290. }
  291. static void input_visitor_test_add(const char *testpath,
  292. TestInputVisitorData *data,
  293. void (*test_func)(TestInputVisitorData *data, const void *user_data))
  294. {
  295. g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
  296. visitor_input_teardown);
  297. }
  298. int main(int argc, char **argv)
  299. {
  300. TestInputVisitorData in_visitor_data;
  301. g_test_init(&argc, &argv, NULL);
  302. input_visitor_test_add("/string-visitor/input/int",
  303. &in_visitor_data, test_visitor_in_int);
  304. input_visitor_test_add("/string-visitor/input/intList",
  305. &in_visitor_data, test_visitor_in_intList);
  306. input_visitor_test_add("/string-visitor/input/bool",
  307. &in_visitor_data, test_visitor_in_bool);
  308. input_visitor_test_add("/string-visitor/input/number",
  309. &in_visitor_data, test_visitor_in_number);
  310. input_visitor_test_add("/string-visitor/input/string",
  311. &in_visitor_data, test_visitor_in_string);
  312. input_visitor_test_add("/string-visitor/input/enum",
  313. &in_visitor_data, test_visitor_in_enum);
  314. input_visitor_test_add("/string-visitor/input/fuzz",
  315. &in_visitor_data, test_visitor_in_fuzz);
  316. g_test_run();
  317. return 0;
  318. }