2
0

test-visitor-serialization.c 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187
  1. /*
  2. * Unit-tests for visitor-based serialization
  3. *
  4. * Copyright (C) 2014-2015 Red Hat, Inc.
  5. * Copyright IBM, Corp. 2012
  6. *
  7. * Authors:
  8. * Michael Roth <mdroth@linux.vnet.ibm.com>
  9. *
  10. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  11. * See the COPYING file in the top-level directory.
  12. */
  13. #include "qemu/osdep.h"
  14. #include <float.h>
  15. #include "qemu-common.h"
  16. #include "test-qapi-visit.h"
  17. #include "qapi/error.h"
  18. #include "qapi/qmp/qjson.h"
  19. #include "qapi/qmp/qstring.h"
  20. #include "qapi/qobject-input-visitor.h"
  21. #include "qapi/qobject-output-visitor.h"
  22. #include "qapi/string-input-visitor.h"
  23. #include "qapi/string-output-visitor.h"
  24. #include "qapi/dealloc-visitor.h"
  25. enum PrimitiveTypeKind {
  26. PTYPE_STRING = 0,
  27. PTYPE_BOOLEAN,
  28. PTYPE_NUMBER,
  29. PTYPE_INTEGER,
  30. PTYPE_U8,
  31. PTYPE_U16,
  32. PTYPE_U32,
  33. PTYPE_U64,
  34. PTYPE_S8,
  35. PTYPE_S16,
  36. PTYPE_S32,
  37. PTYPE_S64,
  38. PTYPE_EOL,
  39. };
  40. typedef struct PrimitiveType {
  41. union {
  42. const char *string;
  43. bool boolean;
  44. double number;
  45. int64_t integer;
  46. uint8_t u8;
  47. uint16_t u16;
  48. uint32_t u32;
  49. uint64_t u64;
  50. int8_t s8;
  51. int16_t s16;
  52. int32_t s32;
  53. int64_t s64;
  54. intmax_t max;
  55. } value;
  56. enum PrimitiveTypeKind type;
  57. const char *description;
  58. } PrimitiveType;
  59. typedef struct PrimitiveList {
  60. union {
  61. strList *strings;
  62. boolList *booleans;
  63. numberList *numbers;
  64. intList *integers;
  65. int8List *s8_integers;
  66. int16List *s16_integers;
  67. int32List *s32_integers;
  68. int64List *s64_integers;
  69. uint8List *u8_integers;
  70. uint16List *u16_integers;
  71. uint32List *u32_integers;
  72. uint64List *u64_integers;
  73. } value;
  74. enum PrimitiveTypeKind type;
  75. const char *description;
  76. } PrimitiveList;
  77. /* test helpers */
  78. typedef void (*VisitorFunc)(Visitor *v, void **native, Error **errp);
  79. static void dealloc_helper(void *native_in, VisitorFunc visit, Error **errp)
  80. {
  81. Visitor *v = qapi_dealloc_visitor_new();
  82. visit(v, &native_in, errp);
  83. visit_free(v);
  84. }
  85. static void visit_primitive_type(Visitor *v, void **native, Error **errp)
  86. {
  87. PrimitiveType *pt = *native;
  88. switch(pt->type) {
  89. case PTYPE_STRING:
  90. visit_type_str(v, NULL, (char **)&pt->value.string, errp);
  91. break;
  92. case PTYPE_BOOLEAN:
  93. visit_type_bool(v, NULL, &pt->value.boolean, errp);
  94. break;
  95. case PTYPE_NUMBER:
  96. visit_type_number(v, NULL, &pt->value.number, errp);
  97. break;
  98. case PTYPE_INTEGER:
  99. visit_type_int(v, NULL, &pt->value.integer, errp);
  100. break;
  101. case PTYPE_U8:
  102. visit_type_uint8(v, NULL, &pt->value.u8, errp);
  103. break;
  104. case PTYPE_U16:
  105. visit_type_uint16(v, NULL, &pt->value.u16, errp);
  106. break;
  107. case PTYPE_U32:
  108. visit_type_uint32(v, NULL, &pt->value.u32, errp);
  109. break;
  110. case PTYPE_U64:
  111. visit_type_uint64(v, NULL, &pt->value.u64, errp);
  112. break;
  113. case PTYPE_S8:
  114. visit_type_int8(v, NULL, &pt->value.s8, errp);
  115. break;
  116. case PTYPE_S16:
  117. visit_type_int16(v, NULL, &pt->value.s16, errp);
  118. break;
  119. case PTYPE_S32:
  120. visit_type_int32(v, NULL, &pt->value.s32, errp);
  121. break;
  122. case PTYPE_S64:
  123. visit_type_int64(v, NULL, &pt->value.s64, errp);
  124. break;
  125. case PTYPE_EOL:
  126. g_assert_not_reached();
  127. }
  128. }
  129. static void visit_primitive_list(Visitor *v, void **native, Error **errp)
  130. {
  131. PrimitiveList *pl = *native;
  132. switch (pl->type) {
  133. case PTYPE_STRING:
  134. visit_type_strList(v, NULL, &pl->value.strings, errp);
  135. break;
  136. case PTYPE_BOOLEAN:
  137. visit_type_boolList(v, NULL, &pl->value.booleans, errp);
  138. break;
  139. case PTYPE_NUMBER:
  140. visit_type_numberList(v, NULL, &pl->value.numbers, errp);
  141. break;
  142. case PTYPE_INTEGER:
  143. visit_type_intList(v, NULL, &pl->value.integers, errp);
  144. break;
  145. case PTYPE_S8:
  146. visit_type_int8List(v, NULL, &pl->value.s8_integers, errp);
  147. break;
  148. case PTYPE_S16:
  149. visit_type_int16List(v, NULL, &pl->value.s16_integers, errp);
  150. break;
  151. case PTYPE_S32:
  152. visit_type_int32List(v, NULL, &pl->value.s32_integers, errp);
  153. break;
  154. case PTYPE_S64:
  155. visit_type_int64List(v, NULL, &pl->value.s64_integers, errp);
  156. break;
  157. case PTYPE_U8:
  158. visit_type_uint8List(v, NULL, &pl->value.u8_integers, errp);
  159. break;
  160. case PTYPE_U16:
  161. visit_type_uint16List(v, NULL, &pl->value.u16_integers, errp);
  162. break;
  163. case PTYPE_U32:
  164. visit_type_uint32List(v, NULL, &pl->value.u32_integers, errp);
  165. break;
  166. case PTYPE_U64:
  167. visit_type_uint64List(v, NULL, &pl->value.u64_integers, errp);
  168. break;
  169. default:
  170. g_assert_not_reached();
  171. }
  172. }
  173. static TestStruct *struct_create(void)
  174. {
  175. TestStruct *ts = g_malloc0(sizeof(*ts));
  176. ts->integer = -42;
  177. ts->boolean = true;
  178. ts->string = strdup("test string");
  179. return ts;
  180. }
  181. static void struct_compare(TestStruct *ts1, TestStruct *ts2)
  182. {
  183. g_assert(ts1);
  184. g_assert(ts2);
  185. g_assert_cmpint(ts1->integer, ==, ts2->integer);
  186. g_assert(ts1->boolean == ts2->boolean);
  187. g_assert_cmpstr(ts1->string, ==, ts2->string);
  188. }
  189. static void struct_cleanup(TestStruct *ts)
  190. {
  191. g_free(ts->string);
  192. g_free(ts);
  193. }
  194. static void visit_struct(Visitor *v, void **native, Error **errp)
  195. {
  196. visit_type_TestStruct(v, NULL, (TestStruct **)native, errp);
  197. }
  198. static UserDefTwo *nested_struct_create(void)
  199. {
  200. UserDefTwo *udnp = g_malloc0(sizeof(*udnp));
  201. udnp->string0 = strdup("test_string0");
  202. udnp->dict1 = g_malloc0(sizeof(*udnp->dict1));
  203. udnp->dict1->string1 = strdup("test_string1");
  204. udnp->dict1->dict2 = g_malloc0(sizeof(*udnp->dict1->dict2));
  205. udnp->dict1->dict2->userdef = g_new0(UserDefOne, 1);
  206. udnp->dict1->dict2->userdef->integer = 42;
  207. udnp->dict1->dict2->userdef->string = strdup("test_string");
  208. udnp->dict1->dict2->string = strdup("test_string2");
  209. udnp->dict1->dict3 = g_malloc0(sizeof(*udnp->dict1->dict3));
  210. udnp->dict1->has_dict3 = true;
  211. udnp->dict1->dict3->userdef = g_new0(UserDefOne, 1);
  212. udnp->dict1->dict3->userdef->integer = 43;
  213. udnp->dict1->dict3->userdef->string = strdup("test_string");
  214. udnp->dict1->dict3->string = strdup("test_string3");
  215. return udnp;
  216. }
  217. static void nested_struct_compare(UserDefTwo *udnp1, UserDefTwo *udnp2)
  218. {
  219. g_assert(udnp1);
  220. g_assert(udnp2);
  221. g_assert_cmpstr(udnp1->string0, ==, udnp2->string0);
  222. g_assert_cmpstr(udnp1->dict1->string1, ==, udnp2->dict1->string1);
  223. g_assert_cmpint(udnp1->dict1->dict2->userdef->integer, ==,
  224. udnp2->dict1->dict2->userdef->integer);
  225. g_assert_cmpstr(udnp1->dict1->dict2->userdef->string, ==,
  226. udnp2->dict1->dict2->userdef->string);
  227. g_assert_cmpstr(udnp1->dict1->dict2->string, ==,
  228. udnp2->dict1->dict2->string);
  229. g_assert(udnp1->dict1->has_dict3 == udnp2->dict1->has_dict3);
  230. g_assert_cmpint(udnp1->dict1->dict3->userdef->integer, ==,
  231. udnp2->dict1->dict3->userdef->integer);
  232. g_assert_cmpstr(udnp1->dict1->dict3->userdef->string, ==,
  233. udnp2->dict1->dict3->userdef->string);
  234. g_assert_cmpstr(udnp1->dict1->dict3->string, ==,
  235. udnp2->dict1->dict3->string);
  236. }
  237. static void nested_struct_cleanup(UserDefTwo *udnp)
  238. {
  239. qapi_free_UserDefTwo(udnp);
  240. }
  241. static void visit_nested_struct(Visitor *v, void **native, Error **errp)
  242. {
  243. visit_type_UserDefTwo(v, NULL, (UserDefTwo **)native, errp);
  244. }
  245. static void visit_nested_struct_list(Visitor *v, void **native, Error **errp)
  246. {
  247. visit_type_UserDefTwoList(v, NULL, (UserDefTwoList **)native, errp);
  248. }
  249. /* test cases */
  250. typedef enum VisitorCapabilities {
  251. VCAP_PRIMITIVES = 1,
  252. VCAP_STRUCTURES = 2,
  253. VCAP_LISTS = 4,
  254. VCAP_PRIMITIVE_LISTS = 8,
  255. } VisitorCapabilities;
  256. typedef struct SerializeOps {
  257. void (*serialize)(void *native_in, void **datap,
  258. VisitorFunc visit, Error **errp);
  259. void (*deserialize)(void **native_out, void *datap,
  260. VisitorFunc visit, Error **errp);
  261. void (*cleanup)(void *datap);
  262. const char *type;
  263. VisitorCapabilities caps;
  264. } SerializeOps;
  265. typedef struct TestArgs {
  266. const SerializeOps *ops;
  267. void *test_data;
  268. } TestArgs;
  269. static void test_primitives(gconstpointer opaque)
  270. {
  271. TestArgs *args = (TestArgs *) opaque;
  272. const SerializeOps *ops = args->ops;
  273. PrimitiveType *pt = args->test_data;
  274. PrimitiveType *pt_copy = g_malloc0(sizeof(*pt_copy));
  275. void *serialize_data;
  276. pt_copy->type = pt->type;
  277. ops->serialize(pt, &serialize_data, visit_primitive_type, &error_abort);
  278. ops->deserialize((void **)&pt_copy, serialize_data, visit_primitive_type,
  279. &error_abort);
  280. g_assert(pt_copy != NULL);
  281. if (pt->type == PTYPE_STRING) {
  282. g_assert_cmpstr(pt->value.string, ==, pt_copy->value.string);
  283. g_free((char *)pt_copy->value.string);
  284. } else if (pt->type == PTYPE_NUMBER) {
  285. GString *double_expected = g_string_new("");
  286. GString *double_actual = g_string_new("");
  287. /* we serialize with %f for our reference visitors, so rather than fuzzy
  288. * floating math to test "equality", just compare the formatted values
  289. */
  290. g_string_printf(double_expected, "%.6f", pt->value.number);
  291. g_string_printf(double_actual, "%.6f", pt_copy->value.number);
  292. g_assert_cmpstr(double_actual->str, ==, double_expected->str);
  293. g_string_free(double_expected, true);
  294. g_string_free(double_actual, true);
  295. } else if (pt->type == PTYPE_BOOLEAN) {
  296. g_assert_cmpint(!!pt->value.max, ==, !!pt->value.max);
  297. } else {
  298. g_assert_cmpint(pt->value.max, ==, pt_copy->value.max);
  299. }
  300. ops->cleanup(serialize_data);
  301. g_free(args);
  302. g_free(pt_copy);
  303. }
  304. static void test_primitive_lists(gconstpointer opaque)
  305. {
  306. TestArgs *args = (TestArgs *) opaque;
  307. const SerializeOps *ops = args->ops;
  308. PrimitiveType *pt = args->test_data;
  309. PrimitiveList pl = { .value = { NULL } };
  310. PrimitiveList pl_copy = { .value = { NULL } };
  311. PrimitiveList *pl_copy_ptr = &pl_copy;
  312. void *serialize_data;
  313. void *cur_head = NULL;
  314. int i;
  315. pl.type = pl_copy.type = pt->type;
  316. /* build up our list of primitive types */
  317. for (i = 0; i < 32; i++) {
  318. switch (pl.type) {
  319. case PTYPE_STRING: {
  320. strList *tmp = g_new0(strList, 1);
  321. tmp->value = g_strdup(pt->value.string);
  322. if (pl.value.strings == NULL) {
  323. pl.value.strings = tmp;
  324. } else {
  325. tmp->next = pl.value.strings;
  326. pl.value.strings = tmp;
  327. }
  328. break;
  329. }
  330. case PTYPE_INTEGER: {
  331. intList *tmp = g_new0(intList, 1);
  332. tmp->value = pt->value.integer;
  333. if (pl.value.integers == NULL) {
  334. pl.value.integers = tmp;
  335. } else {
  336. tmp->next = pl.value.integers;
  337. pl.value.integers = tmp;
  338. }
  339. break;
  340. }
  341. case PTYPE_S8: {
  342. int8List *tmp = g_new0(int8List, 1);
  343. tmp->value = pt->value.s8;
  344. if (pl.value.s8_integers == NULL) {
  345. pl.value.s8_integers = tmp;
  346. } else {
  347. tmp->next = pl.value.s8_integers;
  348. pl.value.s8_integers = tmp;
  349. }
  350. break;
  351. }
  352. case PTYPE_S16: {
  353. int16List *tmp = g_new0(int16List, 1);
  354. tmp->value = pt->value.s16;
  355. if (pl.value.s16_integers == NULL) {
  356. pl.value.s16_integers = tmp;
  357. } else {
  358. tmp->next = pl.value.s16_integers;
  359. pl.value.s16_integers = tmp;
  360. }
  361. break;
  362. }
  363. case PTYPE_S32: {
  364. int32List *tmp = g_new0(int32List, 1);
  365. tmp->value = pt->value.s32;
  366. if (pl.value.s32_integers == NULL) {
  367. pl.value.s32_integers = tmp;
  368. } else {
  369. tmp->next = pl.value.s32_integers;
  370. pl.value.s32_integers = tmp;
  371. }
  372. break;
  373. }
  374. case PTYPE_S64: {
  375. int64List *tmp = g_new0(int64List, 1);
  376. tmp->value = pt->value.s64;
  377. if (pl.value.s64_integers == NULL) {
  378. pl.value.s64_integers = tmp;
  379. } else {
  380. tmp->next = pl.value.s64_integers;
  381. pl.value.s64_integers = tmp;
  382. }
  383. break;
  384. }
  385. case PTYPE_U8: {
  386. uint8List *tmp = g_new0(uint8List, 1);
  387. tmp->value = pt->value.u8;
  388. if (pl.value.u8_integers == NULL) {
  389. pl.value.u8_integers = tmp;
  390. } else {
  391. tmp->next = pl.value.u8_integers;
  392. pl.value.u8_integers = tmp;
  393. }
  394. break;
  395. }
  396. case PTYPE_U16: {
  397. uint16List *tmp = g_new0(uint16List, 1);
  398. tmp->value = pt->value.u16;
  399. if (pl.value.u16_integers == NULL) {
  400. pl.value.u16_integers = tmp;
  401. } else {
  402. tmp->next = pl.value.u16_integers;
  403. pl.value.u16_integers = tmp;
  404. }
  405. break;
  406. }
  407. case PTYPE_U32: {
  408. uint32List *tmp = g_new0(uint32List, 1);
  409. tmp->value = pt->value.u32;
  410. if (pl.value.u32_integers == NULL) {
  411. pl.value.u32_integers = tmp;
  412. } else {
  413. tmp->next = pl.value.u32_integers;
  414. pl.value.u32_integers = tmp;
  415. }
  416. break;
  417. }
  418. case PTYPE_U64: {
  419. uint64List *tmp = g_new0(uint64List, 1);
  420. tmp->value = pt->value.u64;
  421. if (pl.value.u64_integers == NULL) {
  422. pl.value.u64_integers = tmp;
  423. } else {
  424. tmp->next = pl.value.u64_integers;
  425. pl.value.u64_integers = tmp;
  426. }
  427. break;
  428. }
  429. case PTYPE_NUMBER: {
  430. numberList *tmp = g_new0(numberList, 1);
  431. tmp->value = pt->value.number;
  432. if (pl.value.numbers == NULL) {
  433. pl.value.numbers = tmp;
  434. } else {
  435. tmp->next = pl.value.numbers;
  436. pl.value.numbers = tmp;
  437. }
  438. break;
  439. }
  440. case PTYPE_BOOLEAN: {
  441. boolList *tmp = g_new0(boolList, 1);
  442. tmp->value = pt->value.boolean;
  443. if (pl.value.booleans == NULL) {
  444. pl.value.booleans = tmp;
  445. } else {
  446. tmp->next = pl.value.booleans;
  447. pl.value.booleans = tmp;
  448. }
  449. break;
  450. }
  451. default:
  452. g_assert_not_reached();
  453. }
  454. }
  455. ops->serialize((void **)&pl, &serialize_data, visit_primitive_list,
  456. &error_abort);
  457. ops->deserialize((void **)&pl_copy_ptr, serialize_data,
  458. visit_primitive_list, &error_abort);
  459. i = 0;
  460. /* compare our deserialized list of primitives to the original */
  461. do {
  462. switch (pl_copy.type) {
  463. case PTYPE_STRING: {
  464. strList *ptr;
  465. if (cur_head) {
  466. ptr = cur_head;
  467. cur_head = ptr->next;
  468. } else {
  469. cur_head = ptr = pl_copy.value.strings;
  470. }
  471. g_assert_cmpstr(pt->value.string, ==, ptr->value);
  472. break;
  473. }
  474. case PTYPE_INTEGER: {
  475. intList *ptr;
  476. if (cur_head) {
  477. ptr = cur_head;
  478. cur_head = ptr->next;
  479. } else {
  480. cur_head = ptr = pl_copy.value.integers;
  481. }
  482. g_assert_cmpint(pt->value.integer, ==, ptr->value);
  483. break;
  484. }
  485. case PTYPE_S8: {
  486. int8List *ptr;
  487. if (cur_head) {
  488. ptr = cur_head;
  489. cur_head = ptr->next;
  490. } else {
  491. cur_head = ptr = pl_copy.value.s8_integers;
  492. }
  493. g_assert_cmpint(pt->value.s8, ==, ptr->value);
  494. break;
  495. }
  496. case PTYPE_S16: {
  497. int16List *ptr;
  498. if (cur_head) {
  499. ptr = cur_head;
  500. cur_head = ptr->next;
  501. } else {
  502. cur_head = ptr = pl_copy.value.s16_integers;
  503. }
  504. g_assert_cmpint(pt->value.s16, ==, ptr->value);
  505. break;
  506. }
  507. case PTYPE_S32: {
  508. int32List *ptr;
  509. if (cur_head) {
  510. ptr = cur_head;
  511. cur_head = ptr->next;
  512. } else {
  513. cur_head = ptr = pl_copy.value.s32_integers;
  514. }
  515. g_assert_cmpint(pt->value.s32, ==, ptr->value);
  516. break;
  517. }
  518. case PTYPE_S64: {
  519. int64List *ptr;
  520. if (cur_head) {
  521. ptr = cur_head;
  522. cur_head = ptr->next;
  523. } else {
  524. cur_head = ptr = pl_copy.value.s64_integers;
  525. }
  526. g_assert_cmpint(pt->value.s64, ==, ptr->value);
  527. break;
  528. }
  529. case PTYPE_U8: {
  530. uint8List *ptr;
  531. if (cur_head) {
  532. ptr = cur_head;
  533. cur_head = ptr->next;
  534. } else {
  535. cur_head = ptr = pl_copy.value.u8_integers;
  536. }
  537. g_assert_cmpint(pt->value.u8, ==, ptr->value);
  538. break;
  539. }
  540. case PTYPE_U16: {
  541. uint16List *ptr;
  542. if (cur_head) {
  543. ptr = cur_head;
  544. cur_head = ptr->next;
  545. } else {
  546. cur_head = ptr = pl_copy.value.u16_integers;
  547. }
  548. g_assert_cmpint(pt->value.u16, ==, ptr->value);
  549. break;
  550. }
  551. case PTYPE_U32: {
  552. uint32List *ptr;
  553. if (cur_head) {
  554. ptr = cur_head;
  555. cur_head = ptr->next;
  556. } else {
  557. cur_head = ptr = pl_copy.value.u32_integers;
  558. }
  559. g_assert_cmpint(pt->value.u32, ==, ptr->value);
  560. break;
  561. }
  562. case PTYPE_U64: {
  563. uint64List *ptr;
  564. if (cur_head) {
  565. ptr = cur_head;
  566. cur_head = ptr->next;
  567. } else {
  568. cur_head = ptr = pl_copy.value.u64_integers;
  569. }
  570. g_assert_cmpint(pt->value.u64, ==, ptr->value);
  571. break;
  572. }
  573. case PTYPE_NUMBER: {
  574. numberList *ptr;
  575. GString *double_expected = g_string_new("");
  576. GString *double_actual = g_string_new("");
  577. if (cur_head) {
  578. ptr = cur_head;
  579. cur_head = ptr->next;
  580. } else {
  581. cur_head = ptr = pl_copy.value.numbers;
  582. }
  583. /* we serialize with %f for our reference visitors, so rather than
  584. * fuzzy floating math to test "equality", just compare the
  585. * formatted values
  586. */
  587. g_string_printf(double_expected, "%.6f", pt->value.number);
  588. g_string_printf(double_actual, "%.6f", ptr->value);
  589. g_assert_cmpstr(double_actual->str, ==, double_expected->str);
  590. g_string_free(double_expected, true);
  591. g_string_free(double_actual, true);
  592. break;
  593. }
  594. case PTYPE_BOOLEAN: {
  595. boolList *ptr;
  596. if (cur_head) {
  597. ptr = cur_head;
  598. cur_head = ptr->next;
  599. } else {
  600. cur_head = ptr = pl_copy.value.booleans;
  601. }
  602. g_assert_cmpint(!!pt->value.boolean, ==, !!ptr->value);
  603. break;
  604. }
  605. default:
  606. g_assert_not_reached();
  607. }
  608. i++;
  609. } while (cur_head);
  610. g_assert_cmpint(i, ==, 33);
  611. ops->cleanup(serialize_data);
  612. dealloc_helper(&pl, visit_primitive_list, &error_abort);
  613. dealloc_helper(&pl_copy, visit_primitive_list, &error_abort);
  614. g_free(args);
  615. }
  616. static void test_struct(gconstpointer opaque)
  617. {
  618. TestArgs *args = (TestArgs *) opaque;
  619. const SerializeOps *ops = args->ops;
  620. TestStruct *ts = struct_create();
  621. TestStruct *ts_copy = NULL;
  622. void *serialize_data;
  623. ops->serialize(ts, &serialize_data, visit_struct, &error_abort);
  624. ops->deserialize((void **)&ts_copy, serialize_data, visit_struct,
  625. &error_abort);
  626. struct_compare(ts, ts_copy);
  627. struct_cleanup(ts);
  628. struct_cleanup(ts_copy);
  629. ops->cleanup(serialize_data);
  630. g_free(args);
  631. }
  632. static void test_nested_struct(gconstpointer opaque)
  633. {
  634. TestArgs *args = (TestArgs *) opaque;
  635. const SerializeOps *ops = args->ops;
  636. UserDefTwo *udnp = nested_struct_create();
  637. UserDefTwo *udnp_copy = NULL;
  638. void *serialize_data;
  639. ops->serialize(udnp, &serialize_data, visit_nested_struct, &error_abort);
  640. ops->deserialize((void **)&udnp_copy, serialize_data, visit_nested_struct,
  641. &error_abort);
  642. nested_struct_compare(udnp, udnp_copy);
  643. nested_struct_cleanup(udnp);
  644. nested_struct_cleanup(udnp_copy);
  645. ops->cleanup(serialize_data);
  646. g_free(args);
  647. }
  648. static void test_nested_struct_list(gconstpointer opaque)
  649. {
  650. TestArgs *args = (TestArgs *) opaque;
  651. const SerializeOps *ops = args->ops;
  652. UserDefTwoList *listp = NULL, *tmp, *tmp_copy, *listp_copy = NULL;
  653. void *serialize_data;
  654. int i = 0;
  655. for (i = 0; i < 8; i++) {
  656. tmp = g_new0(UserDefTwoList, 1);
  657. tmp->value = nested_struct_create();
  658. tmp->next = listp;
  659. listp = tmp;
  660. }
  661. ops->serialize(listp, &serialize_data, visit_nested_struct_list,
  662. &error_abort);
  663. ops->deserialize((void **)&listp_copy, serialize_data,
  664. visit_nested_struct_list, &error_abort);
  665. tmp = listp;
  666. tmp_copy = listp_copy;
  667. while (listp_copy) {
  668. g_assert(listp);
  669. nested_struct_compare(listp->value, listp_copy->value);
  670. listp = listp->next;
  671. listp_copy = listp_copy->next;
  672. }
  673. qapi_free_UserDefTwoList(tmp);
  674. qapi_free_UserDefTwoList(tmp_copy);
  675. ops->cleanup(serialize_data);
  676. g_free(args);
  677. }
  678. static PrimitiveType pt_values[] = {
  679. /* string tests */
  680. {
  681. .description = "string_empty",
  682. .type = PTYPE_STRING,
  683. .value.string = "",
  684. },
  685. {
  686. .description = "string_whitespace",
  687. .type = PTYPE_STRING,
  688. .value.string = "a b c\td",
  689. },
  690. {
  691. .description = "string_newlines",
  692. .type = PTYPE_STRING,
  693. .value.string = "a\nb\n",
  694. },
  695. {
  696. .description = "string_commas",
  697. .type = PTYPE_STRING,
  698. .value.string = "a,b, c,d",
  699. },
  700. {
  701. .description = "string_single_quoted",
  702. .type = PTYPE_STRING,
  703. .value.string = "'a b',cd",
  704. },
  705. {
  706. .description = "string_double_quoted",
  707. .type = PTYPE_STRING,
  708. .value.string = "\"a b\",cd",
  709. },
  710. /* boolean tests */
  711. {
  712. .description = "boolean_true1",
  713. .type = PTYPE_BOOLEAN,
  714. .value.boolean = true,
  715. },
  716. {
  717. .description = "boolean_true2",
  718. .type = PTYPE_BOOLEAN,
  719. .value.boolean = 8,
  720. },
  721. {
  722. .description = "boolean_true3",
  723. .type = PTYPE_BOOLEAN,
  724. .value.boolean = -1,
  725. },
  726. {
  727. .description = "boolean_false1",
  728. .type = PTYPE_BOOLEAN,
  729. .value.boolean = false,
  730. },
  731. {
  732. .description = "boolean_false2",
  733. .type = PTYPE_BOOLEAN,
  734. .value.boolean = 0,
  735. },
  736. /* number tests (double) */
  737. /* note: we format these to %.6f before comparing, since that's how
  738. * we serialize them and it doesn't make sense to check precision
  739. * beyond that.
  740. */
  741. {
  742. .description = "number_sanity1",
  743. .type = PTYPE_NUMBER,
  744. .value.number = -1,
  745. },
  746. {
  747. .description = "number_sanity2",
  748. .type = PTYPE_NUMBER,
  749. .value.number = 3.14159265,
  750. },
  751. {
  752. .description = "number_min",
  753. .type = PTYPE_NUMBER,
  754. .value.number = DBL_MIN,
  755. },
  756. {
  757. .description = "number_max",
  758. .type = PTYPE_NUMBER,
  759. .value.number = DBL_MAX,
  760. },
  761. /* integer tests (int64) */
  762. {
  763. .description = "integer_sanity1",
  764. .type = PTYPE_INTEGER,
  765. .value.integer = -1,
  766. },
  767. {
  768. .description = "integer_sanity2",
  769. .type = PTYPE_INTEGER,
  770. .value.integer = INT64_MAX / 2 + 1,
  771. },
  772. {
  773. .description = "integer_min",
  774. .type = PTYPE_INTEGER,
  775. .value.integer = INT64_MIN,
  776. },
  777. {
  778. .description = "integer_max",
  779. .type = PTYPE_INTEGER,
  780. .value.integer = INT64_MAX,
  781. },
  782. /* uint8 tests */
  783. {
  784. .description = "uint8_sanity1",
  785. .type = PTYPE_U8,
  786. .value.u8 = 1,
  787. },
  788. {
  789. .description = "uint8_sanity2",
  790. .type = PTYPE_U8,
  791. .value.u8 = UINT8_MAX / 2 + 1,
  792. },
  793. {
  794. .description = "uint8_min",
  795. .type = PTYPE_U8,
  796. .value.u8 = 0,
  797. },
  798. {
  799. .description = "uint8_max",
  800. .type = PTYPE_U8,
  801. .value.u8 = UINT8_MAX,
  802. },
  803. /* uint16 tests */
  804. {
  805. .description = "uint16_sanity1",
  806. .type = PTYPE_U16,
  807. .value.u16 = 1,
  808. },
  809. {
  810. .description = "uint16_sanity2",
  811. .type = PTYPE_U16,
  812. .value.u16 = UINT16_MAX / 2 + 1,
  813. },
  814. {
  815. .description = "uint16_min",
  816. .type = PTYPE_U16,
  817. .value.u16 = 0,
  818. },
  819. {
  820. .description = "uint16_max",
  821. .type = PTYPE_U16,
  822. .value.u16 = UINT16_MAX,
  823. },
  824. /* uint32 tests */
  825. {
  826. .description = "uint32_sanity1",
  827. .type = PTYPE_U32,
  828. .value.u32 = 1,
  829. },
  830. {
  831. .description = "uint32_sanity2",
  832. .type = PTYPE_U32,
  833. .value.u32 = UINT32_MAX / 2 + 1,
  834. },
  835. {
  836. .description = "uint32_min",
  837. .type = PTYPE_U32,
  838. .value.u32 = 0,
  839. },
  840. {
  841. .description = "uint32_max",
  842. .type = PTYPE_U32,
  843. .value.u32 = UINT32_MAX,
  844. },
  845. /* uint64 tests */
  846. {
  847. .description = "uint64_sanity1",
  848. .type = PTYPE_U64,
  849. .value.u64 = 1,
  850. },
  851. {
  852. .description = "uint64_sanity2",
  853. .type = PTYPE_U64,
  854. .value.u64 = UINT64_MAX / 2 + 1,
  855. },
  856. {
  857. .description = "uint64_min",
  858. .type = PTYPE_U64,
  859. .value.u64 = 0,
  860. },
  861. {
  862. .description = "uint64_max",
  863. .type = PTYPE_U64,
  864. .value.u64 = UINT64_MAX,
  865. },
  866. /* int8 tests */
  867. {
  868. .description = "int8_sanity1",
  869. .type = PTYPE_S8,
  870. .value.s8 = -1,
  871. },
  872. {
  873. .description = "int8_sanity2",
  874. .type = PTYPE_S8,
  875. .value.s8 = INT8_MAX / 2 + 1,
  876. },
  877. {
  878. .description = "int8_min",
  879. .type = PTYPE_S8,
  880. .value.s8 = INT8_MIN,
  881. },
  882. {
  883. .description = "int8_max",
  884. .type = PTYPE_S8,
  885. .value.s8 = INT8_MAX,
  886. },
  887. /* int16 tests */
  888. {
  889. .description = "int16_sanity1",
  890. .type = PTYPE_S16,
  891. .value.s16 = -1,
  892. },
  893. {
  894. .description = "int16_sanity2",
  895. .type = PTYPE_S16,
  896. .value.s16 = INT16_MAX / 2 + 1,
  897. },
  898. {
  899. .description = "int16_min",
  900. .type = PTYPE_S16,
  901. .value.s16 = INT16_MIN,
  902. },
  903. {
  904. .description = "int16_max",
  905. .type = PTYPE_S16,
  906. .value.s16 = INT16_MAX,
  907. },
  908. /* int32 tests */
  909. {
  910. .description = "int32_sanity1",
  911. .type = PTYPE_S32,
  912. .value.s32 = -1,
  913. },
  914. {
  915. .description = "int32_sanity2",
  916. .type = PTYPE_S32,
  917. .value.s32 = INT32_MAX / 2 + 1,
  918. },
  919. {
  920. .description = "int32_min",
  921. .type = PTYPE_S32,
  922. .value.s32 = INT32_MIN,
  923. },
  924. {
  925. .description = "int32_max",
  926. .type = PTYPE_S32,
  927. .value.s32 = INT32_MAX,
  928. },
  929. /* int64 tests */
  930. {
  931. .description = "int64_sanity1",
  932. .type = PTYPE_S64,
  933. .value.s64 = -1,
  934. },
  935. {
  936. .description = "int64_sanity2",
  937. .type = PTYPE_S64,
  938. .value.s64 = INT64_MAX / 2 + 1,
  939. },
  940. {
  941. .description = "int64_min",
  942. .type = PTYPE_S64,
  943. .value.s64 = INT64_MIN,
  944. },
  945. {
  946. .description = "int64_max",
  947. .type = PTYPE_S64,
  948. .value.s64 = INT64_MAX,
  949. },
  950. { .type = PTYPE_EOL }
  951. };
  952. /* visitor-specific op implementations */
  953. typedef struct QmpSerializeData {
  954. Visitor *qov;
  955. QObject *obj;
  956. Visitor *qiv;
  957. } QmpSerializeData;
  958. static void qmp_serialize(void *native_in, void **datap,
  959. VisitorFunc visit, Error **errp)
  960. {
  961. QmpSerializeData *d = g_malloc0(sizeof(*d));
  962. d->qov = qobject_output_visitor_new(&d->obj);
  963. visit(d->qov, &native_in, errp);
  964. *datap = d;
  965. }
  966. static void qmp_deserialize(void **native_out, void *datap,
  967. VisitorFunc visit, Error **errp)
  968. {
  969. QmpSerializeData *d = datap;
  970. QString *output_json;
  971. QObject *obj_orig, *obj;
  972. visit_complete(d->qov, &d->obj);
  973. obj_orig = d->obj;
  974. output_json = qobject_to_json(obj_orig);
  975. obj = qobject_from_json(qstring_get_str(output_json), &error_abort);
  976. qobject_unref(output_json);
  977. d->qiv = qobject_input_visitor_new(obj);
  978. qobject_unref(obj_orig);
  979. qobject_unref(obj);
  980. visit(d->qiv, native_out, errp);
  981. }
  982. static void qmp_cleanup(void *datap)
  983. {
  984. QmpSerializeData *d = datap;
  985. visit_free(d->qov);
  986. visit_free(d->qiv);
  987. g_free(d);
  988. }
  989. typedef struct StringSerializeData {
  990. char *string;
  991. Visitor *sov;
  992. Visitor *siv;
  993. } StringSerializeData;
  994. static void string_serialize(void *native_in, void **datap,
  995. VisitorFunc visit, Error **errp)
  996. {
  997. StringSerializeData *d = g_malloc0(sizeof(*d));
  998. d->sov = string_output_visitor_new(false, &d->string);
  999. visit(d->sov, &native_in, errp);
  1000. *datap = d;
  1001. }
  1002. static void string_deserialize(void **native_out, void *datap,
  1003. VisitorFunc visit, Error **errp)
  1004. {
  1005. StringSerializeData *d = datap;
  1006. visit_complete(d->sov, &d->string);
  1007. d->siv = string_input_visitor_new(d->string);
  1008. visit(d->siv, native_out, errp);
  1009. }
  1010. static void string_cleanup(void *datap)
  1011. {
  1012. StringSerializeData *d = datap;
  1013. visit_free(d->sov);
  1014. visit_free(d->siv);
  1015. g_free(d->string);
  1016. g_free(d);
  1017. }
  1018. /* visitor registration, test harness */
  1019. /* note: to function interchangeably as a serialization mechanism your
  1020. * visitor test implementation should pass the test cases for all visitor
  1021. * capabilities: primitives, structures, and lists
  1022. */
  1023. static const SerializeOps visitors[] = {
  1024. {
  1025. .type = "QMP",
  1026. .serialize = qmp_serialize,
  1027. .deserialize = qmp_deserialize,
  1028. .cleanup = qmp_cleanup,
  1029. .caps = VCAP_PRIMITIVES | VCAP_STRUCTURES | VCAP_LISTS |
  1030. VCAP_PRIMITIVE_LISTS
  1031. },
  1032. {
  1033. .type = "String",
  1034. .serialize = string_serialize,
  1035. .deserialize = string_deserialize,
  1036. .cleanup = string_cleanup,
  1037. .caps = VCAP_PRIMITIVES
  1038. },
  1039. { NULL }
  1040. };
  1041. static void add_visitor_type(const SerializeOps *ops)
  1042. {
  1043. char testname_prefix[32];
  1044. char testname[128];
  1045. TestArgs *args;
  1046. int i = 0;
  1047. sprintf(testname_prefix, "/visitor/serialization/%s", ops->type);
  1048. if (ops->caps & VCAP_PRIMITIVES) {
  1049. while (pt_values[i].type != PTYPE_EOL) {
  1050. sprintf(testname, "%s/primitives/%s", testname_prefix,
  1051. pt_values[i].description);
  1052. args = g_malloc0(sizeof(*args));
  1053. args->ops = ops;
  1054. args->test_data = &pt_values[i];
  1055. g_test_add_data_func(testname, args, test_primitives);
  1056. i++;
  1057. }
  1058. }
  1059. if (ops->caps & VCAP_STRUCTURES) {
  1060. sprintf(testname, "%s/struct", testname_prefix);
  1061. args = g_malloc0(sizeof(*args));
  1062. args->ops = ops;
  1063. args->test_data = NULL;
  1064. g_test_add_data_func(testname, args, test_struct);
  1065. sprintf(testname, "%s/nested_struct", testname_prefix);
  1066. args = g_malloc0(sizeof(*args));
  1067. args->ops = ops;
  1068. args->test_data = NULL;
  1069. g_test_add_data_func(testname, args, test_nested_struct);
  1070. }
  1071. if (ops->caps & VCAP_LISTS) {
  1072. sprintf(testname, "%s/nested_struct_list", testname_prefix);
  1073. args = g_malloc0(sizeof(*args));
  1074. args->ops = ops;
  1075. args->test_data = NULL;
  1076. g_test_add_data_func(testname, args, test_nested_struct_list);
  1077. }
  1078. if (ops->caps & VCAP_PRIMITIVE_LISTS) {
  1079. i = 0;
  1080. while (pt_values[i].type != PTYPE_EOL) {
  1081. sprintf(testname, "%s/primitive_list/%s", testname_prefix,
  1082. pt_values[i].description);
  1083. args = g_malloc0(sizeof(*args));
  1084. args->ops = ops;
  1085. args->test_data = &pt_values[i];
  1086. g_test_add_data_func(testname, args, test_primitive_lists);
  1087. i++;
  1088. }
  1089. }
  1090. }
  1091. int main(int argc, char **argv)
  1092. {
  1093. int i = 0;
  1094. g_test_init(&argc, &argv, NULL);
  1095. while (visitors[i].type != NULL) {
  1096. add_visitor_type(&visitors[i]);
  1097. i++;
  1098. }
  1099. g_test_run();
  1100. return 0;
  1101. }