qemu/test-visitor.c
<<
>>
Prefs
   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
   8typedef struct TestStruct
   9{
  10    int64_t x;
  11    int64_t y;
  12} TestStruct;
  13
  14typedef struct TestStructList
  15{
  16    TestStruct *value;
  17    struct TestStructList *next;
  18} TestStructList;
  19
  20static 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
  28static void visit_type_TestStructList(Visitor *m, TestStructList ** obj, const char *name, Error **errp)
  29{
  30    GenericList *i, **head = (GenericList **)obj;
  31
  32    visit_start_list(m, name, errp);
  33
  34    for (*head = i = visit_next_list(m, head, errp); i; i = visit_next_list(m, &i, errp)) {
  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 */
  43static 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;
  53    QList *qlist;
  54    QDict *qdict;
  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);
 101    g_free(pts);
 102
 103    /* test list input visitor */
 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
 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)));
 133
 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);
 142
 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);
 148    qobject_decref(obj);
 149
 150    qmp_output_visitor_cleanup(mo);
 151    QDECREF(qlist);
 152}
 153
 154/* test deep nesting with refs to other user-defined types */
 155static 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));
 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);
 230
 231    qapi_free_UserDefTwo(ud2c_p);
 232
 233    qobject_decref(obj);
 234}
 235
 236/* test enum values */
 237static 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 */
 275static 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
 285    nested_enums = g_malloc0(sizeof(NestedEnumsOne));
 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
 320    qmp_output_visitor_cleanup(mo);
 321    qmp_input_visitor_cleanup(mi);
 322    qapi_free_NestedEnumsOne(nested_enums);
 323    qapi_free_NestedEnumsOne(nested_enums_cpy);
 324}
 325
 326int 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}
 339