Annotation of qemu/test-visitor.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com