qapi: test cases for QEMUFile input/output visitors
[qemu/mdroth.git] / test-visitor.c
blob15a9ce96d78be3244c42baf34195ef2a65468307
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 #include "qapi/qemu-file-output-visitor.h"
8 #include "qapi/qemu-file-input-visitor.h"
9 #include "hw/hw.h"
10 #include "qemu-common.h"
12 typedef struct TestStruct
14 int64_t x;
15 int64_t y;
16 } TestStruct;
18 typedef struct TestStructList
20 TestStruct *value;
21 struct TestStructList *next;
22 } TestStructList;
24 static void visit_type_TestStruct(Visitor *v, TestStruct **obj, const char *name, Error **errp)
26 visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct), errp);
27 visit_type_int(v, &(*obj)->x, "x", errp);
28 visit_type_int(v, &(*obj)->y, "y", errp);
29 visit_end_struct(v, errp);
32 static void visit_type_TestStructList(Visitor *m, TestStructList ** obj, const char *name, Error **errp)
34 GenericList *i, **head = (GenericList **)obj;
36 visit_start_list(m, name, errp);
38 for (*head = i = visit_next_list(m, head, errp); i; i = visit_next_list(m, &i, errp)) {
39 TestStructList *native_i = (TestStructList *)i;
40 visit_type_TestStruct(m, &native_i->value, NULL, errp);
43 visit_end_list(m, errp);
46 /* test core visitor methods */
47 static void test_visitor_core(void)
49 QmpOutputVisitor *mo;
50 QmpInputVisitor *mi;
51 Visitor *v;
52 TestStruct ts = { 42, 82 };
53 TestStruct *pts = &ts;
54 TestStructList *lts = NULL;
55 Error *err = NULL;
56 QObject *obj;
57 QList *qlist;
58 QDict *qdict;
59 QString *str;
60 int64_t value = 0;
62 mo = qmp_output_visitor_new();
63 v = qmp_output_get_visitor(mo);
65 visit_type_TestStruct(v, &pts, NULL, &err);
67 obj = qmp_output_get_qobject(mo);
69 str = qobject_to_json(obj);
71 printf("%s\n", qstring_get_str(str));
73 QDECREF(str);
75 obj = QOBJECT(qint_from_int(0x42));
77 mi = qmp_input_visitor_new(obj);
78 v = qmp_input_get_visitor(mi);
80 visit_type_int(v, &value, NULL, &err);
81 if (err) {
82 g_error("%s", error_get_pretty(err));
85 g_assert(value == 0x42);
87 qobject_decref(obj);
89 obj = qobject_from_json("{'x': 42, 'y': 84}");
90 mi = qmp_input_visitor_new(obj);
91 v = qmp_input_get_visitor(mi);
93 pts = NULL;
95 visit_type_TestStruct(v, &pts, NULL, &err);
96 if (err) {
97 g_error("%s", error_get_pretty(err));
100 g_assert(pts != NULL);
101 g_assert(pts->x == 42);
102 g_assert(pts->y == 84);
104 qobject_decref(obj);
105 g_free(pts);
107 /* test list input visitor */
108 obj = qobject_from_json("[{'x': 42, 'y': 84}, {'x': 12, 'y': 24}]");
109 mi = qmp_input_visitor_new(obj);
110 v = qmp_input_get_visitor(mi);
112 visit_type_TestStructList(v, &lts, NULL, &err);
113 if (err) {
114 g_error("%s", error_get_pretty(err));
117 g_assert(lts != NULL);
118 g_assert(lts->value->x == 42);
119 g_assert(lts->value->y == 84);
121 g_assert(lts->next != NULL);
122 g_assert(lts->next->value->x == 12);
123 g_assert(lts->next->value->y == 24);
124 g_assert(lts->next->next == NULL);
126 qobject_decref(obj);
128 /* test list output visitor */
129 mo = qmp_output_visitor_new();
130 v = qmp_output_get_visitor(mo);
131 visit_type_TestStructList(v, &lts, NULL, &err);
132 if (err) {
133 g_error("%s", error_get_pretty(err));
135 obj = qmp_output_get_qobject(mo);
136 g_print("obj: %s\n", qstring_get_str(qobject_to_json(obj)));
138 qlist = qobject_to_qlist(obj);
139 assert(qlist);
140 obj = qlist_pop(qlist);
141 qdict = qobject_to_qdict(obj);
142 assert(qdict);
143 assert(qdict_get_int(qdict, "x") == 42);
144 assert(qdict_get_int(qdict, "y") == 84);
145 qobject_decref(obj);
147 obj = qlist_pop(qlist);
148 qdict = qobject_to_qdict(obj);
149 assert(qdict);
150 assert(qdict_get_int(qdict, "x") == 12);
151 assert(qdict_get_int(qdict, "y") == 24);
152 qobject_decref(obj);
154 qmp_output_visitor_cleanup(mo);
155 QDECREF(qlist);
158 /* test deep nesting with refs to other user-defined types */
159 static void test_nested_structs(void)
161 QmpOutputVisitor *mo;
162 QmpInputVisitor *mi;
163 Visitor *v;
164 UserDefOne ud1;
165 UserDefOne *ud1_p = &ud1, *ud1c_p = NULL;
166 UserDefTwo ud2;
167 UserDefTwo *ud2_p = &ud2, *ud2c_p = NULL;
168 Error *err = NULL;
169 QObject *obj;
170 QString *str;
172 ud1.integer = 42;
173 ud1.string = strdup("fourty two");
175 /* sanity check */
176 mo = qmp_output_visitor_new();
177 v = qmp_output_get_visitor(mo);
178 visit_type_UserDefOne(v, &ud1_p, "o_O", &err);
179 if (err) {
180 g_error("%s", error_get_pretty(err));
182 obj = qmp_output_get_qobject(mo);
183 g_assert(obj);
184 qobject_decref(obj);
186 ud2.string = strdup("fourty three");
187 ud2.dict.string = strdup("fourty four");
188 ud2.dict.dict.userdef = ud1_p;
189 ud2.dict.dict.string = strdup("fourty five");
190 ud2.dict.has_dict2 = true;
191 ud2.dict.dict2.userdef = ud1_p;
192 ud2.dict.dict2.string = strdup("fourty six");
194 /* c type -> qobject */
195 mo = qmp_output_visitor_new();
196 v = qmp_output_get_visitor(mo);
197 visit_type_UserDefTwo(v, &ud2_p, "unused", &err);
198 if (err) {
199 g_error("%s", error_get_pretty(err));
201 obj = qmp_output_get_qobject(mo);
202 g_assert(obj);
203 str = qobject_to_json_pretty(obj);
204 g_print("%s\n", qstring_get_str(str));
205 QDECREF(str);
207 /* qobject -> c type, should match original struct */
208 mi = qmp_input_visitor_new(obj);
209 v = qmp_input_get_visitor(mi);
210 visit_type_UserDefTwo(v, &ud2c_p, NULL, &err);
211 if (err) {
212 g_error("%s", error_get_pretty(err));
215 g_assert(!g_strcmp0(ud2c_p->string, ud2.string));
216 g_assert(!g_strcmp0(ud2c_p->dict.string, ud2.dict.string));
218 ud1c_p = ud2c_p->dict.dict.userdef;
219 g_assert(ud1c_p->integer == ud1_p->integer);
220 g_assert(!g_strcmp0(ud1c_p->string, ud1_p->string));
222 g_assert(!g_strcmp0(ud2c_p->dict.dict.string, ud2.dict.dict.string));
224 ud1c_p = ud2c_p->dict.dict2.userdef;
225 g_assert(ud1c_p->integer == ud1_p->integer);
226 g_assert(!g_strcmp0(ud1c_p->string, ud1_p->string));
228 g_assert(!g_strcmp0(ud2c_p->dict.dict2.string, ud2.dict.dict2.string));
229 g_free(ud1.string);
230 g_free(ud2.string);
231 g_free(ud2.dict.string);
232 g_free(ud2.dict.dict.string);
233 g_free(ud2.dict.dict2.string);
235 qapi_free_UserDefTwo(ud2c_p);
237 qobject_decref(obj);
240 /* test enum values */
241 static void test_enums(void)
243 QmpOutputVisitor *mo;
244 QmpInputVisitor *mi;
245 Visitor *v;
246 EnumOne enum1 = ENUM_ONE_VALUE2, enum1_cpy = ENUM_ONE_VALUE1;
247 Error *err = NULL;
248 QObject *obj;
249 QString *str;
251 /* C type -> QObject */
252 mo = qmp_output_visitor_new();
253 v = qmp_output_get_visitor(mo);
254 visit_type_EnumOne(v, &enum1, "unused", &err);
255 if (err) {
256 g_error("%s", error_get_pretty(err));
258 obj = qmp_output_get_qobject(mo);
259 g_assert(obj);
260 str = qobject_to_json_pretty(obj);
261 g_print("%s\n", qstring_get_str(str));
262 QDECREF(str);
263 g_assert(g_strcmp0(qstring_get_str(qobject_to_qstring(obj)), "value2") == 0);
265 /* QObject -> C type */
266 mi = qmp_input_visitor_new(obj);
267 v = qmp_input_get_visitor(mi);
268 visit_type_EnumOne(v, &enum1_cpy, "unused", &err);
269 if (err) {
270 g_error("%s", error_get_pretty(err));
272 g_debug("enum1_cpy, enum1: %d, %d", enum1_cpy, enum1);
273 g_assert(enum1_cpy == enum1);
275 qobject_decref(obj);
278 /* test enum values nested in schema-defined structs */
279 static void test_nested_enums(void)
281 QmpOutputVisitor *mo;
282 QmpInputVisitor *mi;
283 Visitor *v;
284 NestedEnumsOne *nested_enums, *nested_enums_cpy = NULL;
285 Error *err = NULL;
286 QObject *obj;
287 QString *str;
289 nested_enums = g_malloc0(sizeof(NestedEnumsOne));
290 nested_enums->enum1 = ENUM_ONE_VALUE1;
291 nested_enums->enum2 = ENUM_ONE_VALUE2;
292 nested_enums->enum3 = ENUM_ONE_VALUE3;
293 nested_enums->enum4 = ENUM_ONE_VALUE3;
294 nested_enums->has_enum2 = false;
295 nested_enums->has_enum4 = true;
297 /* C type -> QObject */
298 mo = qmp_output_visitor_new();
299 v = qmp_output_get_visitor(mo);
300 visit_type_NestedEnumsOne(v, &nested_enums, NULL, &err);
301 if (err) {
302 g_error("%s", error_get_pretty(err));
304 obj = qmp_output_get_qobject(mo);
305 g_assert(obj);
306 str = qobject_to_json_pretty(obj);
307 g_print("%s\n", qstring_get_str(str));
308 QDECREF(str);
310 /* QObject -> C type */
311 mi = qmp_input_visitor_new(obj);
312 v = qmp_input_get_visitor(mi);
313 visit_type_NestedEnumsOne(v, &nested_enums_cpy, NULL, &err);
314 if (err) {
315 g_error("%s", error_get_pretty(err));
317 g_assert(nested_enums_cpy);
318 g_assert(nested_enums_cpy->enum1 == nested_enums->enum1);
319 g_assert(nested_enums_cpy->enum3 == nested_enums->enum3);
320 g_assert(nested_enums_cpy->enum4 == nested_enums->enum4);
321 g_assert(nested_enums_cpy->has_enum2 == false);
322 g_assert(nested_enums_cpy->has_enum4 == true);
324 qmp_output_visitor_cleanup(mo);
325 qmp_input_visitor_cleanup(mi);
326 qapi_free_NestedEnumsOne(nested_enums);
327 qapi_free_NestedEnumsOne(nested_enums_cpy);
330 #define TEST_QEMU_FILE_PATH "/tmp/test_qemu_file_visitors"
332 typedef struct QEMUFileValue {
333 union {
334 bool boolean;
335 double number;
336 uint8_t u8;
337 uint16_t u16;
338 uint32_t u32;
339 uint64_t u64;
340 int8_t s8;
341 int16_t s16;
342 int32_t s32;
343 int64_t s64;
344 uintmax_t umax;
345 } value;
346 union {
347 uint8_t u8[32];
348 uint16_t u16[32];
349 uint32_t u32[32];
350 uint64_t u64[32];
351 int8_t s8[32];
352 int16_t s16[32];
353 int32_t s32[32];
354 int64_t s64[32];
355 uintmax_t umax[32];
356 } array;
357 size_t array_len;
358 enum {
359 QFV_BOOL = 0,
360 QFV_NUMBER,
361 QFV_U8,
362 QFV_U16,
363 QFV_U32,
364 QFV_U64,
365 QFV_S8,
366 QFV_S16,
367 QFV_S32,
368 QFV_S64,
369 QFV_U8_ARRAY,
370 QFV_EOL,
371 } type;
372 } QEMUFileValue;
374 QEMUFileValue qfvalues[] = {
375 { .value.boolean = true, .type = QFV_BOOL },
376 { .value.boolean = false, .type = QFV_BOOL },
377 { .value.number = 3.14159265, .type = QFV_NUMBER },
378 { .value.u8 = 0, .type = QFV_U8 },
379 { .value.u8 = 1, .type = QFV_U8 },
380 { .value.u8 = 128, .type = QFV_U8 },
381 { .value.u8 = 255u, .type = QFV_U8 },
382 { .value.u16 = 0, .type = QFV_U16 },
383 { .value.u16 = 1, .type = QFV_U16 },
384 { .value.u16 = 32768, .type = QFV_U16 },
385 { .value.u16 = 65535u, .type = QFV_U16 },
386 { .value.u32 = 0, .type = QFV_U32 },
387 { .value.u32 = 1, .type = QFV_U32 },
388 { .value.u32 = 2147483648, .type = QFV_U32 },
389 { .value.u32 = 4294967295u, .type = QFV_U32 },
390 { .value.u64 = 0, .type = QFV_U64 },
391 { .value.u64 = 1, .type = QFV_U64 },
392 { .value.u64 = 9223372036854775808u, .type = QFV_U64 },
393 { .value.u64 = 18446744073709551615u, .type = QFV_U64 },
394 { .value.s8 = 0, .type = QFV_S8 },
395 { .value.s8 = 1, .type = QFV_S8 },
396 { .value.s8 = 128, .type = QFV_S8 },
397 { .value.s8 = -1, .type = QFV_S8 },
398 { .value.s16 = 0, .type = QFV_S16 },
399 { .value.s16 = 1, .type = QFV_S16 },
400 { .value.s16 = 32768, .type = QFV_S16 },
401 { .value.s16 = -1, .type = QFV_S16 },
402 { .value.s32 = 0, .type = QFV_S32 },
403 { .value.s32 = 1, .type = QFV_S32 },
404 { .value.s32 = 2147483648, .type = QFV_S32 },
405 { .value.s32 = -1, .type = QFV_S32 },
406 { .value.s64 = 0, .type = QFV_S64 },
407 { .value.s64 = 1, .type = QFV_S64 },
408 { .value.s64 = 9223372036854775808u, .type = QFV_S64 },
409 { .value.s64 = -1, .type = QFV_S64 },
410 { .array.u8 = { }, .array_len = 0, .type = QFV_U8_ARRAY },
411 { .array.u8 = { 1, 2, 3, 4 }, .array_len = 4, .type = QFV_U8_ARRAY },
412 { .type = QFV_EOL }
415 static void qfv_process(QEMUFileValue *qfv, bool visitor, bool write,
416 void *opaque)
418 int i;
419 void *ptr;
421 switch (qfv->type) {
422 case QFV_BOOL:
423 if (visitor) {
424 visit_type_bool(opaque, &qfv->value.boolean, NULL, NULL);
425 } else {
426 if (write) {
427 qemu_put_byte(opaque, qfv->value.boolean);
428 } else {
429 qfv->value.boolean = qemu_get_byte(opaque);
432 break;
433 case QFV_NUMBER:
434 if (visitor) {
435 visit_type_number(opaque, &qfv->value.number, NULL, NULL);
436 } else {
437 if (write) {
438 qemu_put_be64s(opaque, (uint64_t *)&qfv->value.number);
439 } else {
440 qemu_get_be64s(opaque, (uint64_t *)&qfv->value.number);
443 break;
444 case QFV_U8:
445 if (visitor) {
446 visit_type_uint8(opaque, &qfv->value.u8, NULL, NULL);
447 } else {
448 if (write) {
449 qemu_put_byte(opaque, qfv->value.u8);
450 } else {
451 qfv->value.u8 = qemu_get_byte(opaque);
454 break;
455 case QFV_U16:
456 if (visitor) {
457 visit_type_uint16(opaque, &qfv->value.u16, NULL, NULL);
458 } else {
459 if (write) {
460 qemu_put_be16(opaque, qfv->value.u16);
461 } else {
462 qfv->value.u16 = qemu_get_be16(opaque);
465 break;
466 case QFV_U32:
467 if (visitor) {
468 visit_type_uint32(opaque, &qfv->value.u32, NULL, NULL);
469 } else {
470 if (write) {
471 qemu_put_be32(opaque, qfv->value.u32);
472 } else {
473 qfv->value.u32 = qemu_get_be32(opaque);
476 break;
477 case QFV_U64:
478 if (visitor) {
479 visit_type_uint64(opaque, &qfv->value.u64, NULL, NULL);
480 } else {
481 if (write) {
482 qemu_put_be64(opaque, qfv->value.u64);
483 } else {
484 qfv->value.u64 = qemu_get_be64(opaque);
487 break;
488 case QFV_S8:
489 if (visitor) {
490 visit_type_int8(opaque, &qfv->value.s8, NULL, NULL);
491 } else {
492 if (write) {
493 qemu_put_byte(opaque, qfv->value.s8);
494 } else {
495 qfv->value.s8 = qemu_get_byte(opaque);
498 break;
499 case QFV_S16:
500 if (visitor) {
501 visit_type_int16(opaque, &qfv->value.s16, NULL, NULL);
502 } else {
503 if (write) {
504 qemu_put_be16(opaque, qfv->value.s16);
505 } else {
506 qfv->value.s16 = qemu_get_be16(opaque);
509 break;
510 case QFV_S32:
511 if (visitor) {
512 visit_type_int32(opaque, &qfv->value.s32, NULL, NULL);
513 } else {
514 if (write) {
515 qemu_put_be32(opaque, qfv->value.s32);
516 } else {
517 qfv->value.s32 = qemu_get_be32(opaque);
520 break;
521 case QFV_S64:
522 if (visitor) {
523 visit_type_int64(opaque, &qfv->value.s64, NULL, NULL);
524 } else {
525 if (write) {
526 qemu_put_be64(opaque, qfv->value.s64);
527 } else {
528 qfv->value.s64 = qemu_get_be64(opaque);
531 break;
532 case QFV_U8_ARRAY:
533 if (visitor) {
534 ptr = qfv->array.u8;
535 visit_start_array(opaque, (void **)&ptr, NULL,
536 qfv->array_len, sizeof(uint8_t), NULL);
537 for (i = 0; i < qfv->array_len; i++, visit_next_array(opaque, NULL)) {
538 visit_type_uint8(opaque, &((uint8_t *)ptr)[i], NULL, NULL);
540 visit_end_array(opaque, NULL);
541 } else {
542 for (i = 0; i < qfv->array_len; i++) {
543 if (write) {
544 qemu_put_byte(opaque, qfv->array.u8[i]);
545 } else {
546 qfv->array.u8[i] = qemu_get_byte(opaque);
550 break;
551 default:
552 return;
556 static void qfv_visitor_write(QEMUFileValue *qfv, Visitor *v)
558 qfv_process(qfv, true, true, v);
561 static void qfv_visitor_read(QEMUFileValue *qfv, Visitor *v)
563 qfv_process(qfv, true, false, v);
566 static void qfv_write(QEMUFileValue *qfv, QEMUFile *f)
568 qfv_process(qfv, false, true, f);
571 static void qfv_read(QEMUFileValue *qfv, QEMUFile *f)
573 qfv_process(qfv, false, false, f);
576 static void test_qemu_file_in_visitor(void)
578 QEMUFile *f1, *f2;
579 QemuFileInputVisitor *qfi;
580 QemuFileOutputVisitor *qfo;
581 Visitor *v;
582 QEMUFileValue qfval1, qfval2;
583 int i, j;
584 TestStruct ts, *pts;
585 TestStructList *lts;
587 /* write our test scalars/arrays */
588 f1 = qemu_fopen(TEST_QEMU_FILE_PATH, "wb");
589 g_assert(f1);
590 qfo = qemu_file_output_visitor_new(f1);
591 v = qemu_file_output_get_visitor(qfo);
592 for (i = 0; qfvalues[i].type != QFV_EOL; i++) {
593 qfv_write(&qfvalues[i], f1);
595 /* write our test struct/list. qemu_put_* interfaces have
596 * no analogue for this and instead rely on byte arrays,
597 * so we'll write this using a visitor and simply test
598 * visitor input/output compatibility
600 /* write a simple struct */
601 ts.x = 42;
602 ts.y = 43;
603 pts = &ts;
604 visit_type_TestStruct(v, &pts, NULL, NULL);
605 /* throw in a linked list as well */
606 lts = g_malloc0(sizeof(*lts));
607 lts->value = g_malloc0(sizeof(TestStruct));
608 lts->value->x = 44;
609 lts->value->y = 45;
610 lts->next = g_malloc0(sizeof(*lts));
611 lts->next->value = g_malloc0(sizeof(TestStruct));
612 lts->next->value->x = 46;
613 lts->next->value->y = 47;
614 visit_type_TestStructList(v, &lts, NULL, NULL);
615 g_free(lts->next->value);
616 g_free(lts->next);
617 g_free(lts->value);
618 g_free(lts);
620 qemu_file_output_visitor_cleanup(qfo);
621 qemu_fclose(f1);
623 /* make sure qemu_get_be* and input visitor read same/correct input */
624 f1 = qemu_fopen(TEST_QEMU_FILE_PATH, "rb");
625 f2 = qemu_fopen(TEST_QEMU_FILE_PATH, "rb");
626 qfi = qemu_file_input_visitor_new(f2);
627 g_assert(qfi);
628 v = qemu_file_input_get_visitor(qfi);
629 g_assert(v);
630 for (i = 0; qfvalues[i].type != QFV_EOL; i++) {
631 qfval1.value.umax = qfval2.value.umax = 0;
632 memset(qfval1.array.umax, 0, sizeof(qfval1.array.umax));
633 memset(qfval2.array.umax, 0, sizeof(qfval2.array.umax));
634 qfval1.type = qfval2.type = qfvalues[i].type;
635 qfval1.array_len = qfval2.array_len = qfvalues[i].array_len;
636 qfv_read(&qfval1, f1);
637 qfv_visitor_read(&qfval2, v);
638 if (qfvalues[i].type >= QFV_U8_ARRAY) {
639 for (j = 0; j < qfvalues[i].array_len; j++) {
640 g_assert(qfval1.array.u8[j] == qfval2.array.u8[j]);
641 g_assert(qfval2.array.u8[j] == qfvalues[i].array.u8[j]);
643 } else {
644 g_assert(qfval1.value.umax == qfval2.value.umax);
645 g_assert(qfval2.value.umax == qfvalues[i].value.umax);
648 qemu_file_input_visitor_cleanup(qfi);
649 qemu_fclose(f1);
650 qemu_fclose(f2);
651 unlink(TEST_QEMU_FILE_PATH);
654 static void test_qemu_file_out_visitor(void)
656 QEMUFile *f;
657 QemuFileOutputVisitor *qfo;
658 Visitor *v;
659 QEMUFileValue qfval1;
660 int i, j;
661 TestStruct ts, *pts;
662 TestStructList *lts;
664 /* write test scalars/arrays using an output visitor */
665 f = qemu_fopen(TEST_QEMU_FILE_PATH, "wb");
666 g_assert(f);
667 qfo = qemu_file_output_visitor_new(f);
668 g_assert(qfo);
669 v = qemu_file_output_get_visitor(qfo);
670 g_assert(v);
671 for (i = 0; qfvalues[i].type != QFV_EOL; i++) {
672 qfv_visitor_write(&qfvalues[i], v);
674 /* write a simple struct */
675 ts.x = 42;
676 ts.y = 43;
677 pts = &ts;
678 visit_type_TestStruct(v, &pts, NULL, NULL);
679 /* throw in a linked list as well */
680 lts = g_malloc0(sizeof(*lts));
681 lts->value = g_malloc0(sizeof(TestStruct));
682 lts->value->x = 44;
683 lts->value->y = 45;
684 lts->next = g_malloc0(sizeof(*lts));
685 lts->next->value = g_malloc0(sizeof(TestStruct));
686 lts->next->value->x = 46;
687 lts->next->value->y = 47;
688 visit_type_TestStructList(v, &lts, NULL, NULL);
689 g_free(lts->next->value);
690 g_free(lts->next);
691 g_free(lts->value);
692 g_free(lts);
694 qemu_file_output_visitor_cleanup(qfo);
695 qemu_fclose(f);
697 /* make sure output visitor wrote the expected values */
698 f = qemu_fopen(TEST_QEMU_FILE_PATH, "rb");
699 g_assert(f);
700 for (i = 0; qfvalues[i].type != QFV_EOL; i++) {
701 qfval1.type = qfvalues[i].type;
702 qfval1.value.umax = 0;
703 memset(qfval1.array.umax, 0, sizeof(qfval1.array.umax));
704 qfval1.array_len = qfvalues[i].array_len;
706 qfv_read(&qfval1, f);
707 if (qfvalues[i].type >= QFV_U8_ARRAY) {
708 for (j = 0; j < qfvalues[i].array_len; j++) {
709 g_assert(qfval1.array.u8[j] == qfvalues[i].array.u8[j]);
711 } else {
712 g_assert(qfval1.value.umax == qfvalues[i].value.umax);
715 /* test the struct */
716 g_assert(qemu_get_be64(f) == ts.x);
717 g_assert(qemu_get_be64(f) == ts.y);
718 /* test the linked list */
719 g_assert(qemu_get_be64(f) == 44);
720 g_assert(qemu_get_be64(f) == 45);
721 g_assert(qemu_get_be64(f) == 46);
722 g_assert(qemu_get_be64(f) == 47);
724 qemu_fclose(f);
725 unlink(TEST_QEMU_FILE_PATH);
728 int main(int argc, char **argv)
730 g_test_init(&argc, &argv, NULL);
732 g_test_add_func("/0.15/visitor_core", test_visitor_core);
733 g_test_add_func("/0.15/nested_structs", test_nested_structs);
734 g_test_add_func("/0.15/enums", test_enums);
735 g_test_add_func("/0.15/nested_enums", test_nested_enums);
736 g_test_add_func("/1.0/qemu_file_input_visitor", test_qemu_file_in_visitor);
737 g_test_add_func("/1.0/qemu_file_output_visitor", test_qemu_file_out_visitor);
739 g_test_run();
741 return 0;