Annotation of qemu/tests/test-qmp-output-visitor.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * QMP Output Visitor unit-tests.
                      3:  *
                      4:  * Copyright (C) 2011 Red Hat Inc.
                      5:  *
                      6:  * Authors:
                      7:  *  Luiz Capitulino <lcapitulino@redhat.com>
                      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: 
                     13: #include <glib.h>
                     14: 
                     15: #include "qapi/qmp-output-visitor.h"
                     16: #include "test-qapi-types.h"
                     17: #include "test-qapi-visit.h"
                     18: #include "qemu-objects.h"
                     19: 
                     20: typedef struct TestOutputVisitorData {
                     21:     QmpOutputVisitor *qov;
                     22:     Visitor *ov;
                     23: } TestOutputVisitorData;
                     24: 
                     25: static void visitor_output_setup(TestOutputVisitorData *data,
                     26:                                  const void *unused)
                     27: {
                     28:     data->qov = qmp_output_visitor_new();
                     29:     g_assert(data->qov != NULL);
                     30: 
                     31:     data->ov = qmp_output_get_visitor(data->qov);
                     32:     g_assert(data->ov != NULL);
                     33: }
                     34: 
                     35: static void visitor_output_teardown(TestOutputVisitorData *data,
                     36:                                     const void *unused)
                     37: {
                     38:     qmp_output_visitor_cleanup(data->qov);
                     39:     data->qov = NULL;
                     40:     data->ov = NULL;
                     41: }
                     42: 
                     43: static void test_visitor_out_int(TestOutputVisitorData *data,
                     44:                                  const void *unused)
                     45: {
                     46:     int64_t value = -42;
                     47:     Error *errp = NULL;
                     48:     QObject *obj;
                     49: 
                     50:     visit_type_int(data->ov, &value, NULL, &errp);
                     51:     g_assert(error_is_set(&errp) == 0);
                     52: 
                     53:     obj = qmp_output_get_qobject(data->qov);
                     54:     g_assert(obj != NULL);
                     55:     g_assert(qobject_type(obj) == QTYPE_QINT);
                     56:     g_assert_cmpint(qint_get_int(qobject_to_qint(obj)), ==, value);
                     57: 
                     58:     qobject_decref(obj);
                     59: }
                     60: 
                     61: static void test_visitor_out_bool(TestOutputVisitorData *data,
                     62:                                   const void *unused)
                     63: {
                     64:     Error *errp = NULL;
                     65:     bool value = true;
                     66:     QObject *obj;
                     67: 
                     68:     visit_type_bool(data->ov, &value, NULL, &errp);
                     69:     g_assert(error_is_set(&errp) == 0);
                     70: 
                     71:     obj = qmp_output_get_qobject(data->qov);
                     72:     g_assert(obj != NULL);
                     73:     g_assert(qobject_type(obj) == QTYPE_QBOOL);
                     74:     g_assert(qbool_get_int(qobject_to_qbool(obj)) == value);
                     75: 
                     76:     qobject_decref(obj);
                     77: }
                     78: 
                     79: static void test_visitor_out_number(TestOutputVisitorData *data,
                     80:                                     const void *unused)
                     81: {
                     82:     double value = 3.14;
                     83:     Error *errp = NULL;
                     84:     QObject *obj;
                     85: 
                     86:     visit_type_number(data->ov, &value, NULL, &errp);
                     87:     g_assert(error_is_set(&errp) == 0);
                     88: 
                     89:     obj = qmp_output_get_qobject(data->qov);
                     90:     g_assert(obj != NULL);
                     91:     g_assert(qobject_type(obj) == QTYPE_QFLOAT);
                     92:     g_assert(qfloat_get_double(qobject_to_qfloat(obj)) == value);
                     93: 
                     94:     qobject_decref(obj);
                     95: }
                     96: 
                     97: static void test_visitor_out_string(TestOutputVisitorData *data,
                     98:                                     const void *unused)
                     99: {
                    100:     char *string = (char *) "Q E M U";
                    101:     Error *errp = NULL;
                    102:     QObject *obj;
                    103: 
                    104:     visit_type_str(data->ov, &string, NULL, &errp);
                    105:     g_assert(error_is_set(&errp) == 0);
                    106: 
                    107:     obj = qmp_output_get_qobject(data->qov);
                    108:     g_assert(obj != NULL);
                    109:     g_assert(qobject_type(obj) == QTYPE_QSTRING);
                    110:     g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, string);
                    111: 
                    112:     qobject_decref(obj);
                    113: }
                    114: 
                    115: static void test_visitor_out_no_string(TestOutputVisitorData *data,
                    116:                                        const void *unused)
                    117: {
                    118:     char *string = NULL;
                    119:     Error *errp = NULL;
                    120:     QObject *obj;
                    121: 
                    122:     /* A null string should return "" */
                    123:     visit_type_str(data->ov, &string, NULL, &errp);
                    124:     g_assert(error_is_set(&errp) == 0);
                    125: 
                    126:     obj = qmp_output_get_qobject(data->qov);
                    127:     g_assert(obj != NULL);
                    128:     g_assert(qobject_type(obj) == QTYPE_QSTRING);
                    129:     g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, "");
                    130: 
                    131:     qobject_decref(obj);
                    132: }
                    133: 
                    134: static void test_visitor_out_enum(TestOutputVisitorData *data,
                    135:                                   const void *unused)
                    136: {
                    137:     Error *errp = NULL;
                    138:     QObject *obj;
                    139:     EnumOne i;
                    140: 
                    141:     for (i = 0; i < ENUM_ONE_MAX; i++) {
                    142:         visit_type_EnumOne(data->ov, &i, "unused", &errp);
                    143:         g_assert(!error_is_set(&errp));
                    144: 
                    145:         obj = qmp_output_get_qobject(data->qov);
                    146:         g_assert(obj != NULL);
                    147:         g_assert(qobject_type(obj) == QTYPE_QSTRING);
                    148:         g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==,
                    149:                         EnumOne_lookup[i]);
                    150:         qobject_decref(obj);
                    151:     }
                    152: }
                    153: 
                    154: static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
                    155:                                          const void *unused)
                    156: {
                    157:     EnumOne i, bad_values[] = { ENUM_ONE_MAX, -1 };
                    158:     Error *errp;
                    159: 
                    160:     for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
                    161:         errp = NULL;
                    162:         visit_type_EnumOne(data->ov, &bad_values[i], "unused", &errp);
                    163:         g_assert(error_is_set(&errp) == true);
                    164:         error_free(errp);
                    165:     }
                    166: }
                    167: 
                    168: typedef struct TestStruct
                    169: {
                    170:     int64_t integer;
                    171:     bool boolean;
                    172:     char *string;
                    173: } TestStruct;
                    174: 
                    175: static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
                    176:                                   const char *name, Error **errp)
                    177: {
                    178:     visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
                    179:                        errp);
                    180: 
                    181:     visit_type_int(v, &(*obj)->integer, "integer", errp);
                    182:     visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
                    183:     visit_type_str(v, &(*obj)->string, "string", errp);
                    184: 
                    185:     visit_end_struct(v, errp);
                    186: }
                    187: 
                    188: static void test_visitor_out_struct(TestOutputVisitorData *data,
                    189:                                     const void *unused)
                    190: {
                    191:     TestStruct test_struct = { .integer = 42,
                    192:                                .boolean = false,
                    193:                                .string = (char *) "foo"};
                    194:     TestStruct *p = &test_struct;
                    195:     Error *errp = NULL;
                    196:     QObject *obj;
                    197:     QDict *qdict;
                    198: 
                    199:     visit_type_TestStruct(data->ov, &p, NULL, &errp);
                    200:     g_assert(!error_is_set(&errp));
                    201: 
                    202:     obj = qmp_output_get_qobject(data->qov);
                    203:     g_assert(obj != NULL);
                    204:     g_assert(qobject_type(obj) == QTYPE_QDICT);
                    205: 
                    206:     qdict = qobject_to_qdict(obj);
                    207:     g_assert_cmpint(qdict_size(qdict), ==, 3);
                    208:     g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 42);
                    209:     g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, 0);
                    210:     g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "foo");
                    211: 
                    212:     QDECREF(qdict);
                    213: }
                    214: 
                    215: static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
                    216:                                            const void *unused)
                    217: {
                    218:     int64_t value = 42;
                    219:     Error *errp = NULL;
                    220:     UserDefNested *ud2;
                    221:     QObject *obj;
                    222:     QDict *qdict, *dict1, *dict2, *dict3, *userdef;
                    223:     const char *string = "user def string";
                    224:     const char *strings[] = { "forty two", "forty three", "forty four",
                    225:                               "forty five" };
                    226: 
                    227:     ud2 = g_malloc0(sizeof(*ud2));
                    228:     ud2->string0 = g_strdup(strings[0]);
                    229: 
                    230:     ud2->dict1.string1 = g_strdup(strings[1]);
                    231:     ud2->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
                    232:     ud2->dict1.dict2.userdef1->string = g_strdup(string);
                    233:     ud2->dict1.dict2.userdef1->integer = value;
                    234:     ud2->dict1.dict2.string2 = g_strdup(strings[2]);
                    235: 
                    236:     ud2->dict1.has_dict3 = true;
                    237:     ud2->dict1.dict3.userdef2 = g_malloc0(sizeof(UserDefOne));
                    238:     ud2->dict1.dict3.userdef2->string = g_strdup(string);
                    239:     ud2->dict1.dict3.userdef2->integer = value;
                    240:     ud2->dict1.dict3.string3 = g_strdup(strings[3]);
                    241: 
                    242:     visit_type_UserDefNested(data->ov, &ud2, "unused", &errp);
                    243:     g_assert(!error_is_set(&errp));
                    244: 
                    245:     obj = qmp_output_get_qobject(data->qov);
                    246:     g_assert(obj != NULL);
                    247:     g_assert(qobject_type(obj) == QTYPE_QDICT);
                    248: 
                    249:     qdict = qobject_to_qdict(obj);
                    250:     g_assert_cmpint(qdict_size(qdict), ==, 2);
                    251:     g_assert_cmpstr(qdict_get_str(qdict, "string0"), ==, strings[0]);
                    252: 
                    253:     dict1 = qdict_get_qdict(qdict, "dict1");
                    254:     g_assert_cmpint(qdict_size(dict1), ==, 3);
                    255:     g_assert_cmpstr(qdict_get_str(dict1, "string1"), ==, strings[1]);
                    256: 
                    257:     dict2 = qdict_get_qdict(dict1, "dict2");
                    258:     g_assert_cmpint(qdict_size(dict2), ==, 2);
                    259:     g_assert_cmpstr(qdict_get_str(dict2, "string2"), ==, strings[2]);
                    260:     userdef = qdict_get_qdict(dict2, "userdef1");
                    261:     g_assert_cmpint(qdict_size(userdef), ==, 2);
                    262:     g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
                    263:     g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
                    264: 
                    265:     dict3 = qdict_get_qdict(dict1, "dict3");
                    266:     g_assert_cmpint(qdict_size(dict3), ==, 2);
                    267:     g_assert_cmpstr(qdict_get_str(dict3, "string3"), ==, strings[3]);
                    268:     userdef = qdict_get_qdict(dict3, "userdef2");
                    269:     g_assert_cmpint(qdict_size(userdef), ==, 2);
                    270:     g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
                    271:     g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
                    272: 
                    273:     QDECREF(qdict);
                    274:     qapi_free_UserDefNested(ud2);
                    275: }
                    276: 
                    277: static void test_visitor_out_struct_errors(TestOutputVisitorData *data,
                    278:                                            const void *unused)
                    279: {
                    280:     EnumOne bad_values[] = { ENUM_ONE_MAX, -1 };
                    281:     UserDefOne u = { 0 }, *pu = &u;
                    282:     Error *errp;
                    283:     int i;
                    284: 
                    285:     for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
                    286:         errp = NULL;
                    287:         u.has_enum1 = true;
                    288:         u.enum1 = bad_values[i];
                    289:         visit_type_UserDefOne(data->ov, &pu, "unused", &errp);
                    290:         g_assert(error_is_set(&errp) == true);
                    291:         error_free(errp);
                    292:     }
                    293: }
                    294: 
                    295: typedef struct TestStructList
                    296: {
                    297:     TestStruct *value;
                    298:     struct TestStructList *next;
                    299: } TestStructList;
                    300: 
                    301: static void visit_type_TestStructList(Visitor *v, TestStructList **obj,
                    302:                                       const char *name, Error **errp)
                    303: {
                    304:     GenericList *i, **head = (GenericList **)obj;
                    305: 
                    306:     visit_start_list(v, name, errp);
                    307: 
                    308:     for (*head = i = visit_next_list(v, head, errp); i; i = visit_next_list(v, &i, errp)) {
                    309:         TestStructList *native_i = (TestStructList *)i;
                    310:         visit_type_TestStruct(v, &native_i->value, NULL, errp);
                    311:     }
                    312: 
                    313:     visit_end_list(v, errp);
                    314: }
                    315: 
                    316: static void test_visitor_out_list(TestOutputVisitorData *data,
                    317:                                   const void *unused)
                    318: {
                    319:     char *value_str = (char *) "list value";
                    320:     TestStructList *p, *head = NULL;
                    321:     const int max_items = 10;
                    322:     bool value_bool = true;
                    323:     int value_int = 10;
                    324:     Error *errp = NULL;
                    325:     QListEntry *entry;
                    326:     QObject *obj;
                    327:     QList *qlist;
                    328:     int i;
                    329: 
                    330:     for (i = 0; i < max_items; i++) {
                    331:         p = g_malloc0(sizeof(*p));
                    332:         p->value = g_malloc0(sizeof(*p->value));
                    333:         p->value->integer = value_int;
                    334:         p->value->boolean = value_bool;
                    335:         p->value->string = value_str;
                    336: 
                    337:         p->next = head;
                    338:         head = p;
                    339:     }
                    340: 
                    341:     visit_type_TestStructList(data->ov, &head, NULL, &errp);
                    342:     g_assert(!error_is_set(&errp));
                    343: 
                    344:     obj = qmp_output_get_qobject(data->qov);
                    345:     g_assert(obj != NULL);
                    346:     g_assert(qobject_type(obj) == QTYPE_QLIST);
                    347: 
                    348:     qlist = qobject_to_qlist(obj);
                    349:     g_assert(!qlist_empty(qlist));
                    350: 
                    351:     i = 0;
                    352:     QLIST_FOREACH_ENTRY(qlist, entry) {
                    353:         QDict *qdict;
                    354: 
                    355:         g_assert(qobject_type(entry->value) == QTYPE_QDICT);
                    356:         qdict = qobject_to_qdict(entry->value);
                    357:         g_assert_cmpint(qdict_size(qdict), ==, 3);
                    358:         g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, value_int);
                    359:         g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, value_bool);
                    360:         g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, value_str);
                    361:         i++;
                    362:     }
                    363:     g_assert_cmpint(i, ==, max_items);
                    364: 
                    365:     QDECREF(qlist);
                    366: 
                    367:     for (p = head; p;) {
                    368:         TestStructList *tmp = p->next;
                    369:         g_free(p->value);
                    370:         g_free(p);
                    371:         p = tmp;
                    372:     }
                    373: }
                    374: 
                    375: static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data,
                    376:                                             const void *unused)
                    377: {
                    378:     UserDefNestedList *p, *head = NULL;
                    379:     const char string[] = "foo bar";
                    380:     int i, max_count = 1024;
                    381: 
                    382:     for (i = 0; i < max_count; i++) {
                    383:         p = g_malloc0(sizeof(*p));
                    384:         p->value = g_malloc0(sizeof(*p->value));
                    385: 
                    386:         p->value->string0 = g_strdup(string);
                    387:         p->value->dict1.string1 = g_strdup(string);
                    388:         p->value->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
                    389:         p->value->dict1.dict2.userdef1->string = g_strdup(string);
                    390:         p->value->dict1.dict2.userdef1->integer = 42;
                    391:         p->value->dict1.dict2.string2 = g_strdup(string);
                    392:         p->value->dict1.has_dict3 = false;
                    393: 
                    394:         p->next = head;
                    395:         head = p;
                    396:     }
                    397: 
                    398:     qapi_free_UserDefNestedList(head);
                    399: }
                    400: 
                    401: static void test_visitor_out_union(TestOutputVisitorData *data,
                    402:                                    const void *unused)
                    403: {
                    404:     QObject *arg, *qvalue;
                    405:     QDict *qdict, *value;
                    406: 
                    407:     Error *err = NULL;
                    408: 
                    409:     UserDefUnion *tmp = g_malloc0(sizeof(UserDefUnion));
                    410:     tmp->kind = USER_DEF_UNION_KIND_A;
                    411:     tmp->a = g_malloc0(sizeof(UserDefA));
                    412:     tmp->a->boolean = true;
                    413: 
                    414:     visit_type_UserDefUnion(data->ov, &tmp, NULL, &err);
                    415:     g_assert(err == NULL);
                    416:     arg = qmp_output_get_qobject(data->qov);
                    417: 
                    418:     g_assert(qobject_type(arg) == QTYPE_QDICT);
                    419:     qdict = qobject_to_qdict(arg);
                    420: 
                    421:     g_assert_cmpstr(qdict_get_str(qdict, "type"), ==, "a");
                    422: 
                    423:     qvalue = qdict_get(qdict, "data");
                    424:     g_assert(data != NULL);
                    425:     g_assert(qobject_type(qvalue) == QTYPE_QDICT);
                    426:     value = qobject_to_qdict(qvalue);
                    427:     g_assert_cmpint(qdict_get_bool(value, "boolean"), ==, true);
                    428: 
                    429:     qapi_free_UserDefUnion(tmp);
                    430:     QDECREF(qdict);
                    431: }
                    432: 
                    433: static void output_visitor_test_add(const char *testpath,
                    434:                                     TestOutputVisitorData *data,
                    435:                                     void (*test_func)(TestOutputVisitorData *data, const void *user_data))
                    436: {
                    437:     g_test_add(testpath, TestOutputVisitorData, data, visitor_output_setup,
                    438:                test_func, visitor_output_teardown);
                    439: }
                    440: 
                    441: int main(int argc, char **argv)
                    442: {
                    443:     TestOutputVisitorData out_visitor_data;
                    444: 
                    445:     g_test_init(&argc, &argv, NULL);
                    446: 
                    447:     output_visitor_test_add("/visitor/output/int",
                    448:                             &out_visitor_data, test_visitor_out_int);
                    449:     output_visitor_test_add("/visitor/output/bool",
                    450:                             &out_visitor_data, test_visitor_out_bool);
                    451:     output_visitor_test_add("/visitor/output/number",
                    452:                             &out_visitor_data, test_visitor_out_number);
                    453:     output_visitor_test_add("/visitor/output/string",
                    454:                             &out_visitor_data, test_visitor_out_string);
                    455:     output_visitor_test_add("/visitor/output/no-string",
                    456:                             &out_visitor_data, test_visitor_out_no_string);
                    457:     output_visitor_test_add("/visitor/output/enum",
                    458:                             &out_visitor_data, test_visitor_out_enum);
                    459:     output_visitor_test_add("/visitor/output/enum-errors",
                    460:                             &out_visitor_data, test_visitor_out_enum_errors);
                    461:     output_visitor_test_add("/visitor/output/struct",
                    462:                             &out_visitor_data, test_visitor_out_struct);
                    463:     output_visitor_test_add("/visitor/output/struct-nested",
                    464:                             &out_visitor_data, test_visitor_out_struct_nested);
                    465:     output_visitor_test_add("/visitor/output/struct-errors",
                    466:                             &out_visitor_data, test_visitor_out_struct_errors);
                    467:     output_visitor_test_add("/visitor/output/list",
                    468:                             &out_visitor_data, test_visitor_out_list);
                    469:     output_visitor_test_add("/visitor/output/list-qapi-free",
                    470:                             &out_visitor_data, test_visitor_out_list_qapi_free);
                    471:     output_visitor_test_add("/visitor/output/union",
                    472:                             &out_visitor_data, test_visitor_out_union);
                    473: 
                    474:     g_test_run();
                    475: 
                    476:     return 0;
                    477: }

unix.superglobalmegacorp.com