|
|
1.1 ! root 1: /* ! 2: * QMP Output Visitor unit-tests. ! 3: * ! 4: * Copyright (C) 2011 Red Hat Inc. ! 5: * ! 6: * Authors: ! 7: * Luiz Capitulino <[email protected]> ! 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.