qemu/tests/unit/test-qobject-output-visitor.c
<<
>>
Prefs
   1/*
   2 * QObject Output Visitor unit-tests.
   3 *
   4 * Copyright (C) 2011-2016 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 "qemu/osdep.h"
  14
  15#include "qapi/error.h"
  16#include "qapi/qobject-output-visitor.h"
  17#include "test-qapi-visit.h"
  18#include "qapi/qmp/qbool.h"
  19#include "qapi/qmp/qdict.h"
  20#include "qapi/qmp/qlist.h"
  21#include "qapi/qmp/qnull.h"
  22#include "qapi/qmp/qnum.h"
  23#include "qapi/qmp/qstring.h"
  24
  25typedef struct TestOutputVisitorData {
  26    Visitor *ov;
  27    QObject *obj;
  28} TestOutputVisitorData;
  29
  30static void visitor_output_setup(TestOutputVisitorData *data,
  31                                 const void *unused)
  32{
  33    data->ov = qobject_output_visitor_new(&data->obj);
  34    g_assert(data->ov);
  35}
  36
  37static void visitor_output_teardown(TestOutputVisitorData *data,
  38                                    const void *unused)
  39{
  40    visit_free(data->ov);
  41    data->ov = NULL;
  42    qobject_unref(data->obj);
  43    data->obj = NULL;
  44}
  45
  46static QObject *visitor_get(TestOutputVisitorData *data)
  47{
  48    visit_complete(data->ov, &data->obj);
  49    g_assert(data->obj);
  50    return data->obj;
  51}
  52
  53static void visitor_reset(TestOutputVisitorData *data)
  54{
  55    visitor_output_teardown(data, NULL);
  56    visitor_output_setup(data, NULL);
  57}
  58
  59static void test_visitor_out_int(TestOutputVisitorData *data,
  60                                 const void *unused)
  61{
  62    int64_t value = -42;
  63    int64_t val;
  64    QNum *qnum;
  65
  66    visit_type_int(data->ov, NULL, &value, &error_abort);
  67
  68    qnum = qobject_to(QNum, visitor_get(data));
  69    g_assert(qnum);
  70    g_assert(qnum_get_try_int(qnum, &val));
  71    g_assert_cmpint(val, ==, value);
  72}
  73
  74static void test_visitor_out_bool(TestOutputVisitorData *data,
  75                                  const void *unused)
  76{
  77    bool value = true;
  78    QBool *qbool;
  79
  80    visit_type_bool(data->ov, NULL, &value, &error_abort);
  81
  82    qbool = qobject_to(QBool, visitor_get(data));
  83    g_assert(qbool);
  84    g_assert(qbool_get_bool(qbool) == value);
  85}
  86
  87static void test_visitor_out_number(TestOutputVisitorData *data,
  88                                    const void *unused)
  89{
  90    double value = 3.14;
  91    QNum *qnum;
  92
  93    visit_type_number(data->ov, NULL, &value, &error_abort);
  94
  95    qnum = qobject_to(QNum, visitor_get(data));
  96    g_assert(qnum);
  97    g_assert(qnum_get_double(qnum) == value);
  98}
  99
 100static void test_visitor_out_string(TestOutputVisitorData *data,
 101                                    const void *unused)
 102{
 103    char *string = (char *) "Q E M U";
 104    QString *qstr;
 105
 106    visit_type_str(data->ov, NULL, &string, &error_abort);
 107
 108    qstr = qobject_to(QString, visitor_get(data));
 109    g_assert(qstr);
 110    g_assert_cmpstr(qstring_get_str(qstr), ==, string);
 111}
 112
 113static void test_visitor_out_no_string(TestOutputVisitorData *data,
 114                                       const void *unused)
 115{
 116    char *string = NULL;
 117    QString *qstr;
 118
 119    /* A null string should return "" */
 120    visit_type_str(data->ov, NULL, &string, &error_abort);
 121
 122    qstr = qobject_to(QString, visitor_get(data));
 123    g_assert(qstr);
 124    g_assert_cmpstr(qstring_get_str(qstr), ==, "");
 125}
 126
 127static void test_visitor_out_enum(TestOutputVisitorData *data,
 128                                  const void *unused)
 129{
 130    EnumOne i;
 131    QString *qstr;
 132
 133    for (i = 0; i < ENUM_ONE__MAX; i++) {
 134        visit_type_EnumOne(data->ov, "unused", &i, &error_abort);
 135
 136        qstr = qobject_to(QString, visitor_get(data));
 137        g_assert(qstr);
 138        g_assert_cmpstr(qstring_get_str(qstr), ==, EnumOne_str(i));
 139        visitor_reset(data);
 140    }
 141}
 142
 143static void test_visitor_out_struct(TestOutputVisitorData *data,
 144                                    const void *unused)
 145{
 146    TestStruct test_struct = { .integer = 42,
 147                               .boolean = false,
 148                               .string = (char *) "foo"};
 149    TestStruct *p = &test_struct;
 150    QDict *qdict;
 151
 152    visit_type_TestStruct(data->ov, NULL, &p, &error_abort);
 153
 154    qdict = qobject_to(QDict, visitor_get(data));
 155    g_assert(qdict);
 156    g_assert_cmpint(qdict_size(qdict), ==, 3);
 157    g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 42);
 158    g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, false);
 159    g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "foo");
 160}
 161
 162static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
 163                                           const void *unused)
 164{
 165    int64_t value = 42;
 166    UserDefTwo *ud2;
 167    QDict *qdict, *dict1, *dict2, *dict3, *userdef;
 168    const char *string = "user def string";
 169    const char *strings[] = { "forty two", "forty three", "forty four",
 170                              "forty five" };
 171
 172    ud2 = g_malloc0(sizeof(*ud2));
 173    ud2->string0 = g_strdup(strings[0]);
 174
 175    ud2->dict1 = g_malloc0(sizeof(*ud2->dict1));
 176    ud2->dict1->string1 = g_strdup(strings[1]);
 177
 178    ud2->dict1->dict2 = g_malloc0(sizeof(*ud2->dict1->dict2));
 179    ud2->dict1->dict2->userdef = g_new0(UserDefOne, 1);
 180    ud2->dict1->dict2->userdef->string = g_strdup(string);
 181    ud2->dict1->dict2->userdef->integer = value;
 182    ud2->dict1->dict2->string = g_strdup(strings[2]);
 183
 184    ud2->dict1->dict3 = g_malloc0(sizeof(*ud2->dict1->dict3));
 185    ud2->dict1->has_dict3 = true;
 186    ud2->dict1->dict3->userdef = g_new0(UserDefOne, 1);
 187    ud2->dict1->dict3->userdef->string = g_strdup(string);
 188    ud2->dict1->dict3->userdef->integer = value;
 189    ud2->dict1->dict3->string = g_strdup(strings[3]);
 190
 191    visit_type_UserDefTwo(data->ov, "unused", &ud2, &error_abort);
 192
 193    qdict = qobject_to(QDict, visitor_get(data));
 194    g_assert(qdict);
 195    g_assert_cmpint(qdict_size(qdict), ==, 2);
 196    g_assert_cmpstr(qdict_get_str(qdict, "string0"), ==, strings[0]);
 197
 198    dict1 = qdict_get_qdict(qdict, "dict1");
 199    g_assert_cmpint(qdict_size(dict1), ==, 3);
 200    g_assert_cmpstr(qdict_get_str(dict1, "string1"), ==, strings[1]);
 201
 202    dict2 = qdict_get_qdict(dict1, "dict2");
 203    g_assert_cmpint(qdict_size(dict2), ==, 2);
 204    g_assert_cmpstr(qdict_get_str(dict2, "string"), ==, strings[2]);
 205    userdef = qdict_get_qdict(dict2, "userdef");
 206    g_assert_cmpint(qdict_size(userdef), ==, 2);
 207    g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
 208    g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
 209
 210    dict3 = qdict_get_qdict(dict1, "dict3");
 211    g_assert_cmpint(qdict_size(dict3), ==, 2);
 212    g_assert_cmpstr(qdict_get_str(dict3, "string"), ==, strings[3]);
 213    userdef = qdict_get_qdict(dict3, "userdef");
 214    g_assert_cmpint(qdict_size(userdef), ==, 2);
 215    g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
 216    g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
 217
 218    qapi_free_UserDefTwo(ud2);
 219}
 220
 221static void test_visitor_out_list(TestOutputVisitorData *data,
 222                                  const void *unused)
 223{
 224    const char *value_str = "list value";
 225    TestStruct *value;
 226    TestStructList *head = NULL;
 227    const int max_items = 10;
 228    bool value_bool = true;
 229    int value_int = 10;
 230    QListEntry *entry;
 231    QList *qlist;
 232    int i;
 233
 234    /* Build the list in reverse order... */
 235    for (i = 0; i < max_items; i++) {
 236        value = g_malloc0(sizeof(*value));
 237        value->integer = value_int + (max_items - i - 1);
 238        value->boolean = value_bool;
 239        value->string = g_strdup(value_str);
 240
 241        QAPI_LIST_PREPEND(head, value);
 242    }
 243
 244    visit_type_TestStructList(data->ov, NULL, &head, &error_abort);
 245
 246    qlist = qobject_to(QList, visitor_get(data));
 247    g_assert(qlist);
 248    g_assert(!qlist_empty(qlist));
 249
 250    /* ...and ensure that the visitor sees it in order */
 251    i = 0;
 252    QLIST_FOREACH_ENTRY(qlist, entry) {
 253        QDict *qdict;
 254
 255        qdict = qobject_to(QDict, entry->value);
 256        g_assert(qdict);
 257        g_assert_cmpint(qdict_size(qdict), ==, 3);
 258        g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, value_int + i);
 259        g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, value_bool);
 260        g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, value_str);
 261        i++;
 262    }
 263    g_assert_cmpint(i, ==, max_items);
 264
 265    qapi_free_TestStructList(head);
 266}
 267
 268static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data,
 269                                            const void *unused)
 270{
 271    UserDefTwo *value;
 272    UserDefTwoList *head = NULL;
 273    const char string[] = "foo bar";
 274    int i, max_count = 1024;
 275
 276    for (i = 0; i < max_count; i++) {
 277        value = g_malloc0(sizeof(*value));
 278
 279        value->string0 = g_strdup(string);
 280        value->dict1 = g_new0(UserDefTwoDict, 1);
 281        value->dict1->string1 = g_strdup(string);
 282        value->dict1->dict2 = g_new0(UserDefTwoDictDict, 1);
 283        value->dict1->dict2->userdef = g_new0(UserDefOne, 1);
 284        value->dict1->dict2->userdef->string = g_strdup(string);
 285        value->dict1->dict2->userdef->integer = 42;
 286        value->dict1->dict2->string = g_strdup(string);
 287        value->dict1->has_dict3 = false;
 288
 289        QAPI_LIST_PREPEND(head, value);
 290    }
 291
 292    qapi_free_UserDefTwoList(head);
 293}
 294
 295static void test_visitor_out_any(TestOutputVisitorData *data,
 296                                 const void *unused)
 297{
 298    QObject *qobj;
 299    QNum *qnum;
 300    QBool *qbool;
 301    QString *qstring;
 302    QDict *qdict;
 303    int64_t val;
 304
 305    qobj = QOBJECT(qnum_from_int(-42));
 306    visit_type_any(data->ov, NULL, &qobj, &error_abort);
 307    qnum = qobject_to(QNum, visitor_get(data));
 308    g_assert(qnum);
 309    g_assert(qnum_get_try_int(qnum, &val));
 310    g_assert_cmpint(val, ==, -42);
 311    qobject_unref(qobj);
 312
 313    visitor_reset(data);
 314    qdict = qdict_new();
 315    qdict_put_int(qdict, "integer", -42);
 316    qdict_put_bool(qdict, "boolean", true);
 317    qdict_put_str(qdict, "string", "foo");
 318    qobj = QOBJECT(qdict);
 319    visit_type_any(data->ov, NULL, &qobj, &error_abort);
 320    qobject_unref(qobj);
 321    qdict = qobject_to(QDict, visitor_get(data));
 322    g_assert(qdict);
 323    qnum = qobject_to(QNum, qdict_get(qdict, "integer"));
 324    g_assert(qnum);
 325    g_assert(qnum_get_try_int(qnum, &val));
 326    g_assert_cmpint(val, ==, -42);
 327    qbool = qobject_to(QBool, qdict_get(qdict, "boolean"));
 328    g_assert(qbool);
 329    g_assert(qbool_get_bool(qbool) == true);
 330    qstring = qobject_to(QString, qdict_get(qdict, "string"));
 331    g_assert(qstring);
 332    g_assert_cmpstr(qstring_get_str(qstring), ==, "foo");
 333}
 334
 335static void test_visitor_out_union_flat(TestOutputVisitorData *data,
 336                                        const void *unused)
 337{
 338    QDict *qdict;
 339
 340    UserDefFlatUnion *tmp = g_new0(UserDefFlatUnion, 1);
 341    tmp->enum1 = ENUM_ONE_VALUE1;
 342    tmp->string = g_strdup("str");
 343    tmp->integer = 41;
 344    tmp->u.value1.boolean = true;
 345
 346    visit_type_UserDefFlatUnion(data->ov, NULL, &tmp, &error_abort);
 347    qdict = qobject_to(QDict, visitor_get(data));
 348    g_assert(qdict);
 349    g_assert_cmpstr(qdict_get_str(qdict, "enum1"), ==, "value1");
 350    g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "str");
 351    g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 41);
 352    g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, true);
 353
 354    qapi_free_UserDefFlatUnion(tmp);
 355}
 356
 357static void test_visitor_out_alternate(TestOutputVisitorData *data,
 358                                       const void *unused)
 359{
 360    UserDefAlternate *tmp;
 361    QNum *qnum;
 362    QString *qstr;
 363    QDict *qdict;
 364    int64_t val;
 365
 366    tmp = g_new0(UserDefAlternate, 1);
 367    tmp->type = QTYPE_QNUM;
 368    tmp->u.i = 42;
 369
 370    visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
 371    qnum = qobject_to(QNum, visitor_get(data));
 372    g_assert(qnum);
 373    g_assert(qnum_get_try_int(qnum, &val));
 374    g_assert_cmpint(val, ==, 42);
 375
 376    qapi_free_UserDefAlternate(tmp);
 377
 378    visitor_reset(data);
 379    tmp = g_new0(UserDefAlternate, 1);
 380    tmp->type = QTYPE_QSTRING;
 381    tmp->u.e = ENUM_ONE_VALUE1;
 382
 383    visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
 384    qstr = qobject_to(QString, visitor_get(data));
 385    g_assert(qstr);
 386    g_assert_cmpstr(qstring_get_str(qstr), ==, "value1");
 387
 388    qapi_free_UserDefAlternate(tmp);
 389
 390    visitor_reset(data);
 391    tmp = g_new0(UserDefAlternate, 1);
 392    tmp->type = QTYPE_QNULL;
 393    tmp->u.n = qnull();
 394
 395    visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
 396    g_assert_cmpint(qobject_type(visitor_get(data)), ==, QTYPE_QNULL);
 397
 398    qapi_free_UserDefAlternate(tmp);
 399
 400    visitor_reset(data);
 401    tmp = g_new0(UserDefAlternate, 1);
 402    tmp->type = QTYPE_QDICT;
 403    tmp->u.udfu.integer = 1;
 404    tmp->u.udfu.string = g_strdup("str");
 405    tmp->u.udfu.enum1 = ENUM_ONE_VALUE1;
 406    tmp->u.udfu.u.value1.boolean = true;
 407
 408    visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
 409    qdict = qobject_to(QDict, visitor_get(data));
 410    g_assert(qdict);
 411    g_assert_cmpint(qdict_size(qdict), ==, 4);
 412    g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 1);
 413    g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "str");
 414    g_assert_cmpstr(qdict_get_str(qdict, "enum1"), ==, "value1");
 415    g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, true);
 416
 417    qapi_free_UserDefAlternate(tmp);
 418}
 419
 420static void test_visitor_out_null(TestOutputVisitorData *data,
 421                                  const void *unused)
 422{
 423    QNull *null = NULL;
 424    QDict *qdict;
 425    QObject *nil;
 426
 427    visit_start_struct(data->ov, NULL, NULL, 0, &error_abort);
 428    visit_type_null(data->ov, "a", &null, &error_abort);
 429    visit_check_struct(data->ov, &error_abort);
 430    visit_end_struct(data->ov, NULL);
 431    qdict = qobject_to(QDict, visitor_get(data));
 432    g_assert(qdict);
 433    g_assert_cmpint(qdict_size(qdict), ==, 1);
 434    nil = qdict_get(qdict, "a");
 435    g_assert(nil);
 436    g_assert(qobject_type(nil) == QTYPE_QNULL);
 437}
 438
 439static void test_visitor_out_list_struct(TestOutputVisitorData *data,
 440                                         const void *unused)
 441{
 442    const char *int_member[] = {
 443        "integer", "s8", "s16", "s32", "s64", "u8", "u16", "u32", "u64" };
 444    g_autoptr(ArrayStruct) arrs = g_new0(ArrayStruct, 1);
 445    int i, j;
 446    QDict *qdict;
 447    QList *qlist;
 448    QListEntry *e;
 449
 450    for (i = 31; i >= 0; i--) {
 451        QAPI_LIST_PREPEND(arrs->integer, i);
 452    }
 453
 454    for (i = 31; i >= 0; i--) {
 455        QAPI_LIST_PREPEND(arrs->s8, i);
 456    }
 457
 458    for (i = 31; i >= 0; i--) {
 459        QAPI_LIST_PREPEND(arrs->s16, i);
 460    }
 461
 462    for (i = 31; i >= 0; i--) {
 463        QAPI_LIST_PREPEND(arrs->s32, i);
 464    }
 465
 466    for (i = 31; i >= 0; i--) {
 467        QAPI_LIST_PREPEND(arrs->s64, i);
 468    }
 469
 470    for (i = 31; i >= 0; i--) {
 471        QAPI_LIST_PREPEND(arrs->u8, i);
 472    }
 473
 474    for (i = 31; i >= 0; i--) {
 475        QAPI_LIST_PREPEND(arrs->u16, i);
 476    }
 477
 478    for (i = 31; i >= 0; i--) {
 479        QAPI_LIST_PREPEND(arrs->u32, i);
 480    }
 481
 482    for (i = 31; i >= 0; i--) {
 483        QAPI_LIST_PREPEND(arrs->u64, i);
 484    }
 485
 486    for (i = 31; i >= 0; i--) {
 487        QAPI_LIST_PREPEND(arrs->number, (double)i / 3);
 488    }
 489
 490    for (i = 31; i >= 0; i--) {
 491        QAPI_LIST_PREPEND(arrs->boolean, QEMU_IS_ALIGNED(i, 3));
 492    }
 493
 494    for (i = 31; i >= 0; i--) {
 495        QAPI_LIST_PREPEND(arrs->string, g_strdup_printf("%d", i));
 496    }
 497
 498    visit_type_ArrayStruct(data->ov, NULL, &arrs, &error_abort);
 499
 500    qdict = qobject_to(QDict, visitor_get(data));
 501    g_assert(qdict);
 502
 503    for (i = 0; i < G_N_ELEMENTS(int_member); i++) {
 504        qlist = qdict_get_qlist(qdict, int_member[i]);
 505        g_assert(qlist);
 506        j = 0;
 507        QLIST_FOREACH_ENTRY(qlist, e) {
 508            QNum *qvalue = qobject_to(QNum, qlist_entry_obj(e));
 509            g_assert(qvalue);
 510            g_assert_cmpint(qnum_get_int(qvalue), ==, j);
 511            j++;
 512        }
 513    }
 514
 515    qlist = qdict_get_qlist(qdict, "number");
 516    g_assert(qlist);
 517    i = 0;
 518    QLIST_FOREACH_ENTRY(qlist, e) {
 519        QNum *qvalue = qobject_to(QNum, qlist_entry_obj(e));
 520        char expected[32], actual[32];
 521
 522        g_assert(qvalue);
 523        sprintf(expected, "%.6f", (double)i / 3);
 524        sprintf(actual, "%.6f", qnum_get_double(qvalue));
 525        g_assert_cmpstr(actual, ==, expected);
 526        i++;
 527    }
 528
 529    qlist = qdict_get_qlist(qdict, "boolean");
 530    g_assert(qlist);
 531    i = 0;
 532    QLIST_FOREACH_ENTRY(qlist, e) {
 533        QBool *qvalue = qobject_to(QBool, qlist_entry_obj(e));
 534        g_assert(qvalue);
 535        g_assert_cmpint(qbool_get_bool(qvalue), ==, i % 3 == 0);
 536        i++;
 537    }
 538
 539    qlist = qdict_get_qlist(qdict, "string");
 540    g_assert(qlist);
 541    i = 0;
 542    QLIST_FOREACH_ENTRY(qlist, e) {
 543        QString *qvalue = qobject_to(QString, qlist_entry_obj(e));
 544        char expected[32];
 545
 546        g_assert(qvalue);
 547        sprintf(expected, "%d", i);
 548        g_assert_cmpstr(qstring_get_str(qvalue), ==, expected);
 549        i++;
 550    }
 551}
 552
 553static void output_visitor_test_add(const char *testpath,
 554                                    TestOutputVisitorData *data,
 555                                    void (*test_func)(TestOutputVisitorData *data, const void *user_data))
 556{
 557    g_test_add(testpath, TestOutputVisitorData, data, visitor_output_setup,
 558               test_func, visitor_output_teardown);
 559}
 560
 561int main(int argc, char **argv)
 562{
 563    TestOutputVisitorData out_visitor_data;
 564
 565    g_test_init(&argc, &argv, NULL);
 566
 567    output_visitor_test_add("/visitor/output/int",
 568                            &out_visitor_data, test_visitor_out_int);
 569    output_visitor_test_add("/visitor/output/bool",
 570                            &out_visitor_data, test_visitor_out_bool);
 571    output_visitor_test_add("/visitor/output/number",
 572                            &out_visitor_data, test_visitor_out_number);
 573    output_visitor_test_add("/visitor/output/string",
 574                            &out_visitor_data, test_visitor_out_string);
 575    output_visitor_test_add("/visitor/output/no-string",
 576                            &out_visitor_data, test_visitor_out_no_string);
 577    output_visitor_test_add("/visitor/output/enum",
 578                            &out_visitor_data, test_visitor_out_enum);
 579    output_visitor_test_add("/visitor/output/struct",
 580                            &out_visitor_data, test_visitor_out_struct);
 581    output_visitor_test_add("/visitor/output/struct-nested",
 582                            &out_visitor_data, test_visitor_out_struct_nested);
 583    output_visitor_test_add("/visitor/output/list",
 584                            &out_visitor_data, test_visitor_out_list);
 585    output_visitor_test_add("/visitor/output/any",
 586                            &out_visitor_data, test_visitor_out_any);
 587    output_visitor_test_add("/visitor/output/list-qapi-free",
 588                            &out_visitor_data, test_visitor_out_list_qapi_free);
 589    output_visitor_test_add("/visitor/output/union-flat",
 590                            &out_visitor_data, test_visitor_out_union_flat);
 591    output_visitor_test_add("/visitor/output/alternate",
 592                            &out_visitor_data, test_visitor_out_alternate);
 593    output_visitor_test_add("/visitor/output/null",
 594                            &out_visitor_data, test_visitor_out_null);
 595    output_visitor_test_add("/visitor/output/list_struct",
 596                            &out_visitor_data, test_visitor_out_list_struct);
 597
 598    g_test_run();
 599
 600    return 0;
 601}
 602