test-visitor.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. #include <glib.h>
  2. #include "qapi/qmp-output-visitor.h"
  3. #include "qapi/qmp-input-visitor.h"
  4. #include "test-qapi-types.h"
  5. #include "test-qapi-visit.h"
  6. #include "qemu-objects.h"
  7. typedef struct TestStruct
  8. {
  9. int64_t x;
  10. int64_t y;
  11. } TestStruct;
  12. typedef struct TestStructList
  13. {
  14. TestStruct *value;
  15. struct TestStructList *next;
  16. } TestStructList;
  17. static void visit_type_TestStruct(Visitor *v, TestStruct **obj, const char *name, Error **errp)
  18. {
  19. visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct), errp);
  20. visit_type_int(v, &(*obj)->x, "x", errp);
  21. visit_type_int(v, &(*obj)->y, "y", errp);
  22. visit_end_struct(v, errp);
  23. }
  24. static void visit_type_TestStructList(Visitor *m, TestStructList ** obj, const char *name, Error **errp)
  25. {
  26. GenericList *i, **head = (GenericList **)obj;
  27. visit_start_list(m, name, errp);
  28. for (*head = i = visit_next_list(m, head, errp); i; i = visit_next_list(m, &i, errp)) {
  29. TestStructList *native_i = (TestStructList *)i;
  30. visit_type_TestStruct(m, &native_i->value, NULL, errp);
  31. }
  32. visit_end_list(m, errp);
  33. }
  34. /* test core visitor methods */
  35. static void test_visitor_core(void)
  36. {
  37. QmpOutputVisitor *mo;
  38. QmpInputVisitor *mi;
  39. Visitor *v;
  40. TestStruct ts = { 42, 82 };
  41. TestStruct *pts = &ts;
  42. TestStructList *lts = NULL;
  43. Error *err = NULL;
  44. QObject *obj;
  45. QList *qlist;
  46. QDict *qdict;
  47. QString *str;
  48. int64_t value = 0;
  49. mo = qmp_output_visitor_new();
  50. v = qmp_output_get_visitor(mo);
  51. visit_type_TestStruct(v, &pts, NULL, &err);
  52. obj = qmp_output_get_qobject(mo);
  53. str = qobject_to_json(obj);
  54. printf("%s\n", qstring_get_str(str));
  55. QDECREF(str);
  56. obj = QOBJECT(qint_from_int(0x42));
  57. mi = qmp_input_visitor_new(obj);
  58. v = qmp_input_get_visitor(mi);
  59. visit_type_int(v, &value, NULL, &err);
  60. if (err) {
  61. g_error("%s", error_get_pretty(err));
  62. }
  63. g_assert(value == 0x42);
  64. qobject_decref(obj);
  65. obj = qobject_from_json("{'x': 42, 'y': 84}");
  66. mi = qmp_input_visitor_new(obj);
  67. v = qmp_input_get_visitor(mi);
  68. pts = NULL;
  69. visit_type_TestStruct(v, &pts, NULL, &err);
  70. if (err) {
  71. g_error("%s", error_get_pretty(err));
  72. }
  73. g_assert(pts != NULL);
  74. g_assert(pts->x == 42);
  75. g_assert(pts->y == 84);
  76. qobject_decref(obj);
  77. g_free(pts);
  78. /* test list input visitor */
  79. obj = qobject_from_json("[{'x': 42, 'y': 84}, {'x': 12, 'y': 24}]");
  80. mi = qmp_input_visitor_new(obj);
  81. v = qmp_input_get_visitor(mi);
  82. visit_type_TestStructList(v, &lts, NULL, &err);
  83. if (err) {
  84. g_error("%s", error_get_pretty(err));
  85. }
  86. g_assert(lts != NULL);
  87. g_assert(lts->value->x == 42);
  88. g_assert(lts->value->y == 84);
  89. g_assert(lts->next != NULL);
  90. g_assert(lts->next->value->x == 12);
  91. g_assert(lts->next->value->y == 24);
  92. g_assert(lts->next->next == NULL);
  93. qobject_decref(obj);
  94. /* test list output visitor */
  95. mo = qmp_output_visitor_new();
  96. v = qmp_output_get_visitor(mo);
  97. visit_type_TestStructList(v, &lts, NULL, &err);
  98. if (err) {
  99. g_error("%s", error_get_pretty(err));
  100. }
  101. obj = qmp_output_get_qobject(mo);
  102. g_print("obj: %s\n", qstring_get_str(qobject_to_json(obj)));
  103. qlist = qobject_to_qlist(obj);
  104. assert(qlist);
  105. obj = qlist_pop(qlist);
  106. qdict = qobject_to_qdict(obj);
  107. assert(qdict);
  108. assert(qdict_get_int(qdict, "x") == 42);
  109. assert(qdict_get_int(qdict, "y") == 84);
  110. qobject_decref(obj);
  111. obj = qlist_pop(qlist);
  112. qdict = qobject_to_qdict(obj);
  113. assert(qdict);
  114. assert(qdict_get_int(qdict, "x") == 12);
  115. assert(qdict_get_int(qdict, "y") == 24);
  116. qobject_decref(obj);
  117. qmp_output_visitor_cleanup(mo);
  118. QDECREF(qlist);
  119. }
  120. /* test deep nesting with refs to other user-defined types */
  121. static void test_nested_structs(void)
  122. {
  123. QmpOutputVisitor *mo;
  124. QmpInputVisitor *mi;
  125. Visitor *v;
  126. UserDefOne ud1;
  127. UserDefOne *ud1_p = &ud1, *ud1c_p = NULL;
  128. UserDefTwo ud2;
  129. UserDefTwo *ud2_p = &ud2, *ud2c_p = NULL;
  130. Error *err = NULL;
  131. QObject *obj;
  132. QString *str;
  133. ud1.integer = 42;
  134. ud1.string = strdup("fourty two");
  135. /* sanity check */
  136. mo = qmp_output_visitor_new();
  137. v = qmp_output_get_visitor(mo);
  138. visit_type_UserDefOne(v, &ud1_p, "o_O", &err);
  139. if (err) {
  140. g_error("%s", error_get_pretty(err));
  141. }
  142. obj = qmp_output_get_qobject(mo);
  143. g_assert(obj);
  144. qobject_decref(obj);
  145. ud2.string = strdup("fourty three");
  146. ud2.dict.string = strdup("fourty four");
  147. ud2.dict.dict.userdef = ud1_p;
  148. ud2.dict.dict.string = strdup("fourty five");
  149. ud2.dict.has_dict2 = true;
  150. ud2.dict.dict2.userdef = ud1_p;
  151. ud2.dict.dict2.string = strdup("fourty six");
  152. /* c type -> qobject */
  153. mo = qmp_output_visitor_new();
  154. v = qmp_output_get_visitor(mo);
  155. visit_type_UserDefTwo(v, &ud2_p, "unused", &err);
  156. if (err) {
  157. g_error("%s", error_get_pretty(err));
  158. }
  159. obj = qmp_output_get_qobject(mo);
  160. g_assert(obj);
  161. str = qobject_to_json_pretty(obj);
  162. g_print("%s\n", qstring_get_str(str));
  163. QDECREF(str);
  164. /* qobject -> c type, should match original struct */
  165. mi = qmp_input_visitor_new(obj);
  166. v = qmp_input_get_visitor(mi);
  167. visit_type_UserDefTwo(v, &ud2c_p, NULL, &err);
  168. if (err) {
  169. g_error("%s", error_get_pretty(err));
  170. }
  171. g_assert(!g_strcmp0(ud2c_p->string, ud2.string));
  172. g_assert(!g_strcmp0(ud2c_p->dict.string, ud2.dict.string));
  173. ud1c_p = ud2c_p->dict.dict.userdef;
  174. g_assert(ud1c_p->integer == ud1_p->integer);
  175. g_assert(!g_strcmp0(ud1c_p->string, ud1_p->string));
  176. g_assert(!g_strcmp0(ud2c_p->dict.dict.string, ud2.dict.dict.string));
  177. ud1c_p = ud2c_p->dict.dict2.userdef;
  178. g_assert(ud1c_p->integer == ud1_p->integer);
  179. g_assert(!g_strcmp0(ud1c_p->string, ud1_p->string));
  180. g_assert(!g_strcmp0(ud2c_p->dict.dict2.string, ud2.dict.dict2.string));
  181. g_free(ud1.string);
  182. g_free(ud2.string);
  183. g_free(ud2.dict.string);
  184. g_free(ud2.dict.dict.string);
  185. g_free(ud2.dict.dict2.string);
  186. qapi_free_UserDefTwo(ud2c_p);
  187. qobject_decref(obj);
  188. }
  189. /* test enum values */
  190. static void test_enums(void)
  191. {
  192. QmpOutputVisitor *mo;
  193. QmpInputVisitor *mi;
  194. Visitor *v;
  195. EnumOne enum1 = ENUM_ONE_VALUE2, enum1_cpy = ENUM_ONE_VALUE1;
  196. Error *err = NULL;
  197. QObject *obj;
  198. QString *str;
  199. /* C type -> QObject */
  200. mo = qmp_output_visitor_new();
  201. v = qmp_output_get_visitor(mo);
  202. visit_type_EnumOne(v, &enum1, "unused", &err);
  203. if (err) {
  204. g_error("%s", error_get_pretty(err));
  205. }
  206. obj = qmp_output_get_qobject(mo);
  207. g_assert(obj);
  208. str = qobject_to_json_pretty(obj);
  209. g_print("%s\n", qstring_get_str(str));
  210. QDECREF(str);
  211. g_assert(g_strcmp0(qstring_get_str(qobject_to_qstring(obj)), "value2") == 0);
  212. /* QObject -> C type */
  213. mi = qmp_input_visitor_new(obj);
  214. v = qmp_input_get_visitor(mi);
  215. visit_type_EnumOne(v, &enum1_cpy, "unused", &err);
  216. if (err) {
  217. g_error("%s", error_get_pretty(err));
  218. }
  219. g_debug("enum1_cpy, enum1: %d, %d", enum1_cpy, enum1);
  220. g_assert(enum1_cpy == enum1);
  221. qobject_decref(obj);
  222. }
  223. /* test enum values nested in schema-defined structs */
  224. static void test_nested_enums(void)
  225. {
  226. QmpOutputVisitor *mo;
  227. QmpInputVisitor *mi;
  228. Visitor *v;
  229. NestedEnumsOne *nested_enums, *nested_enums_cpy = NULL;
  230. Error *err = NULL;
  231. QObject *obj;
  232. QString *str;
  233. nested_enums = g_malloc0(sizeof(NestedEnumsOne));
  234. nested_enums->enum1 = ENUM_ONE_VALUE1;
  235. nested_enums->enum2 = ENUM_ONE_VALUE2;
  236. nested_enums->enum3 = ENUM_ONE_VALUE3;
  237. nested_enums->enum4 = ENUM_ONE_VALUE3;
  238. nested_enums->has_enum2 = false;
  239. nested_enums->has_enum4 = true;
  240. /* C type -> QObject */
  241. mo = qmp_output_visitor_new();
  242. v = qmp_output_get_visitor(mo);
  243. visit_type_NestedEnumsOne(v, &nested_enums, NULL, &err);
  244. if (err) {
  245. g_error("%s", error_get_pretty(err));
  246. }
  247. obj = qmp_output_get_qobject(mo);
  248. g_assert(obj);
  249. str = qobject_to_json_pretty(obj);
  250. g_print("%s\n", qstring_get_str(str));
  251. QDECREF(str);
  252. /* QObject -> C type */
  253. mi = qmp_input_visitor_new(obj);
  254. v = qmp_input_get_visitor(mi);
  255. visit_type_NestedEnumsOne(v, &nested_enums_cpy, NULL, &err);
  256. if (err) {
  257. g_error("%s", error_get_pretty(err));
  258. }
  259. g_assert(nested_enums_cpy);
  260. g_assert(nested_enums_cpy->enum1 == nested_enums->enum1);
  261. g_assert(nested_enums_cpy->enum3 == nested_enums->enum3);
  262. g_assert(nested_enums_cpy->enum4 == nested_enums->enum4);
  263. g_assert(nested_enums_cpy->has_enum2 == false);
  264. g_assert(nested_enums_cpy->has_enum4 == true);
  265. qmp_output_visitor_cleanup(mo);
  266. qmp_input_visitor_cleanup(mi);
  267. qapi_free_NestedEnumsOne(nested_enums);
  268. qapi_free_NestedEnumsOne(nested_enums_cpy);
  269. }
  270. int main(int argc, char **argv)
  271. {
  272. g_test_init(&argc, &argv, NULL);
  273. g_test_add_func("/0.15/visitor_core", test_visitor_core);
  274. g_test_add_func("/0.15/nested_structs", test_nested_structs);
  275. g_test_add_func("/0.15/enums", test_enums);
  276. g_test_add_func("/0.15/nested_enums", test_nested_enums);
  277. g_test_run();
  278. return 0;
  279. }