test-string-input-visitor.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  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-types.h"
  17. #include "test-qapi-visit.h"
  18. #include "qapi/qmp/types.h"
  19. typedef struct TestInputVisitorData {
  20. Visitor *v;
  21. } TestInputVisitorData;
  22. static void visitor_input_teardown(TestInputVisitorData *data,
  23. const void *unused)
  24. {
  25. if (data->v) {
  26. visit_free(data->v);
  27. data->v = NULL;
  28. }
  29. }
  30. /* This is provided instead of a test setup function so that the JSON
  31. string used by the tests are kept in the test functions (and not
  32. int main()) */
  33. static
  34. Visitor *visitor_input_test_init(TestInputVisitorData *data,
  35. const char *string)
  36. {
  37. visitor_input_teardown(data, NULL);
  38. data->v = string_input_visitor_new(string);
  39. g_assert(data->v);
  40. return data->v;
  41. }
  42. static void test_visitor_in_int(TestInputVisitorData *data,
  43. const void *unused)
  44. {
  45. int64_t res = 0, value = -42;
  46. Error *err = NULL;
  47. Visitor *v;
  48. v = visitor_input_test_init(data, "-42");
  49. visit_type_int(v, NULL, &res, &err);
  50. g_assert(!err);
  51. g_assert_cmpint(res, ==, value);
  52. v = visitor_input_test_init(data, "not an int");
  53. visit_type_int(v, NULL, &res, &err);
  54. error_free_or_abort(&err);
  55. v = visitor_input_test_init(data, "");
  56. visit_type_int(v, NULL, &res, &err);
  57. error_free_or_abort(&err);
  58. }
  59. static void check_ilist(Visitor *v, int64_t *expected, size_t n)
  60. {
  61. int64List *res = NULL;
  62. int64List *tail;
  63. int i;
  64. visit_type_int64List(v, NULL, &res, &error_abort);
  65. tail = res;
  66. for (i = 0; i < n; i++) {
  67. g_assert(tail);
  68. g_assert_cmpint(tail->value, ==, expected[i]);
  69. tail = tail->next;
  70. }
  71. g_assert(!tail);
  72. qapi_free_int64List(res);
  73. }
  74. static void check_ulist(Visitor *v, uint64_t *expected, size_t n)
  75. {
  76. uint64List *res = NULL;
  77. uint64List *tail;
  78. int i;
  79. /* BUG: unsigned numbers above INT64_MAX don't work */
  80. for (i = 0; i < n; i++) {
  81. if (expected[i] > INT64_MAX) {
  82. Error *err = NULL;
  83. visit_type_uint64List(v, NULL, &res, &err);
  84. error_free_or_abort(&err);
  85. return;
  86. }
  87. }
  88. visit_type_uint64List(v, NULL, &res, &error_abort);
  89. tail = res;
  90. for (i = 0; i < n; i++) {
  91. g_assert(tail);
  92. g_assert_cmpuint(tail->value, ==, expected[i]);
  93. tail = tail->next;
  94. }
  95. g_assert(!tail);
  96. qapi_free_uint64List(res);
  97. }
  98. static void test_visitor_in_intList(TestInputVisitorData *data,
  99. const void *unused)
  100. {
  101. /* Note: the visitor *sorts* ranges *unsigned* */
  102. int64_t expect1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 20 };
  103. int64_t expect2[] = { 32767, -32768, -32767 };
  104. int64_t expect3[] = { INT64_MAX, INT64_MIN };
  105. uint64_t expect4[] = { UINT64_MAX };
  106. Error *err = NULL;
  107. int64List *res = NULL;
  108. int64List *tail;
  109. Visitor *v;
  110. int64_t val;
  111. /* Valid lists */
  112. v = visitor_input_test_init(data, "1,2,0,2-4,20,5-9,1-8");
  113. check_ilist(v, expect1, ARRAY_SIZE(expect1));
  114. v = visitor_input_test_init(data, "32767,-32768--32767");
  115. check_ilist(v, expect2, ARRAY_SIZE(expect2));
  116. v = visitor_input_test_init(data,
  117. "-9223372036854775808,9223372036854775807");
  118. check_ilist(v, expect3, ARRAY_SIZE(expect3));
  119. v = visitor_input_test_init(data, "18446744073709551615");
  120. check_ulist(v, expect4, ARRAY_SIZE(expect4));
  121. /* Empty list */
  122. v = visitor_input_test_init(data, "");
  123. visit_type_int64List(v, NULL, &res, &error_abort);
  124. g_assert(!res);
  125. /* Not a list */
  126. v = visitor_input_test_init(data, "not an int list");
  127. visit_type_int64List(v, NULL, &res, &err);
  128. error_free_or_abort(&err);
  129. g_assert(!res);
  130. /* Unvisited list tail */
  131. v = visitor_input_test_init(data, "0,2-3");
  132. /* Would be simpler if the visitor genuinely supported virtual walks */
  133. visit_start_list(v, NULL, (GenericList **)&res, sizeof(*res),
  134. &error_abort);
  135. tail = res;
  136. visit_type_int64(v, NULL, &tail->value, &error_abort);
  137. g_assert_cmpint(tail->value, ==, 0);
  138. tail = (int64List *)visit_next_list(v, (GenericList *)tail, sizeof(*res));
  139. g_assert(tail);
  140. visit_type_int64(v, NULL, &tail->value, &error_abort);
  141. g_assert_cmpint(tail->value, ==, 2);
  142. tail = (int64List *)visit_next_list(v, (GenericList *)tail, sizeof(*res));
  143. g_assert(tail);
  144. visit_check_list(v, &err);
  145. error_free_or_abort(&err);
  146. visit_end_list(v, (void **)&res);
  147. qapi_free_int64List(res);
  148. /* Visit beyond end of list */
  149. v = visitor_input_test_init(data, "0");
  150. visit_start_list(v, NULL, (GenericList **)&res, sizeof(*res),
  151. &error_abort);
  152. tail = res;
  153. visit_type_int64(v, NULL, &tail->value, &err);
  154. g_assert_cmpint(tail->value, ==, 0);
  155. visit_type_int64(v, NULL, &val, &err);
  156. g_assert_cmpint(val, ==, 1); /* BUG */
  157. visit_check_list(v, &error_abort);
  158. visit_end_list(v, (void **)&res);
  159. qapi_free_int64List(res);
  160. }
  161. static void test_visitor_in_bool(TestInputVisitorData *data,
  162. const void *unused)
  163. {
  164. Error *err = NULL;
  165. bool res = false;
  166. Visitor *v;
  167. v = visitor_input_test_init(data, "true");
  168. visit_type_bool(v, NULL, &res, &err);
  169. g_assert(!err);
  170. g_assert_cmpint(res, ==, true);
  171. v = visitor_input_test_init(data, "yes");
  172. visit_type_bool(v, NULL, &res, &err);
  173. g_assert(!err);
  174. g_assert_cmpint(res, ==, true);
  175. v = visitor_input_test_init(data, "on");
  176. visit_type_bool(v, NULL, &res, &err);
  177. g_assert(!err);
  178. g_assert_cmpint(res, ==, true);
  179. v = visitor_input_test_init(data, "false");
  180. visit_type_bool(v, NULL, &res, &err);
  181. g_assert(!err);
  182. g_assert_cmpint(res, ==, false);
  183. v = visitor_input_test_init(data, "no");
  184. visit_type_bool(v, NULL, &res, &err);
  185. g_assert(!err);
  186. g_assert_cmpint(res, ==, false);
  187. v = visitor_input_test_init(data, "off");
  188. visit_type_bool(v, NULL, &res, &err);
  189. g_assert(!err);
  190. g_assert_cmpint(res, ==, false);
  191. }
  192. static void test_visitor_in_number(TestInputVisitorData *data,
  193. const void *unused)
  194. {
  195. double res = 0, value = 3.14;
  196. Error *err = NULL;
  197. Visitor *v;
  198. v = visitor_input_test_init(data, "3.14");
  199. visit_type_number(v, NULL, &res, &err);
  200. g_assert(!err);
  201. g_assert_cmpfloat(res, ==, value);
  202. }
  203. static void test_visitor_in_string(TestInputVisitorData *data,
  204. const void *unused)
  205. {
  206. char *res = NULL, *value = (char *) "Q E M U";
  207. Error *err = NULL;
  208. Visitor *v;
  209. v = visitor_input_test_init(data, value);
  210. visit_type_str(v, NULL, &res, &err);
  211. g_assert(!err);
  212. g_assert_cmpstr(res, ==, value);
  213. g_free(res);
  214. }
  215. static void test_visitor_in_enum(TestInputVisitorData *data,
  216. const void *unused)
  217. {
  218. Error *err = NULL;
  219. Visitor *v;
  220. EnumOne i;
  221. for (i = 0; EnumOne_lookup[i]; i++) {
  222. EnumOne res = -1;
  223. v = visitor_input_test_init(data, EnumOne_lookup[i]);
  224. visit_type_EnumOne(v, NULL, &res, &err);
  225. g_assert(!err);
  226. g_assert_cmpint(i, ==, res);
  227. }
  228. }
  229. /* Try to crash the visitors */
  230. static void test_visitor_in_fuzz(TestInputVisitorData *data,
  231. const void *unused)
  232. {
  233. int64_t ires;
  234. intList *ilres;
  235. bool bres;
  236. double nres;
  237. char *sres;
  238. EnumOne eres;
  239. Visitor *v;
  240. unsigned int i;
  241. char buf[10000];
  242. for (i = 0; i < 100; i++) {
  243. unsigned int j;
  244. j = g_test_rand_int_range(0, sizeof(buf) - 1);
  245. buf[j] = '\0';
  246. if (j != 0) {
  247. for (j--; j != 0; j--) {
  248. buf[j - 1] = (char)g_test_rand_int_range(0, 256);
  249. }
  250. }
  251. v = visitor_input_test_init(data, buf);
  252. visit_type_int(v, NULL, &ires, NULL);
  253. v = visitor_input_test_init(data, buf);
  254. visit_type_intList(v, NULL, &ilres, NULL);
  255. qapi_free_intList(ilres);
  256. v = visitor_input_test_init(data, buf);
  257. visit_type_bool(v, NULL, &bres, NULL);
  258. v = visitor_input_test_init(data, buf);
  259. visit_type_number(v, NULL, &nres, NULL);
  260. v = visitor_input_test_init(data, buf);
  261. sres = NULL;
  262. visit_type_str(v, NULL, &sres, NULL);
  263. g_free(sres);
  264. v = visitor_input_test_init(data, buf);
  265. visit_type_EnumOne(v, NULL, &eres, NULL);
  266. }
  267. }
  268. static void input_visitor_test_add(const char *testpath,
  269. TestInputVisitorData *data,
  270. void (*test_func)(TestInputVisitorData *data, const void *user_data))
  271. {
  272. g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
  273. visitor_input_teardown);
  274. }
  275. int main(int argc, char **argv)
  276. {
  277. TestInputVisitorData in_visitor_data;
  278. g_test_init(&argc, &argv, NULL);
  279. input_visitor_test_add("/string-visitor/input/int",
  280. &in_visitor_data, test_visitor_in_int);
  281. input_visitor_test_add("/string-visitor/input/intList",
  282. &in_visitor_data, test_visitor_in_intList);
  283. input_visitor_test_add("/string-visitor/input/bool",
  284. &in_visitor_data, test_visitor_in_bool);
  285. input_visitor_test_add("/string-visitor/input/number",
  286. &in_visitor_data, test_visitor_in_number);
  287. input_visitor_test_add("/string-visitor/input/string",
  288. &in_visitor_data, test_visitor_in_string);
  289. input_visitor_test_add("/string-visitor/input/enum",
  290. &in_visitor_data, test_visitor_in_enum);
  291. input_visitor_test_add("/string-visitor/input/fuzz",
  292. &in_visitor_data, test_visitor_in_fuzz);
  293. g_test_run();
  294. return 0;
  295. }