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->dict3->userdef = g_new0(UserDefOne, 1);
 186    ud2->dict1->dict3->userdef->string = g_strdup(string);
 187    ud2->dict1->dict3->userdef->integer = value;
 188    ud2->dict1->dict3->string = g_strdup(strings[3]);
 189
 190    visit_type_UserDefTwo(data->ov, "unused", &ud2, &error_abort);
 191
 192    qdict = qobject_to(QDict, visitor_get(data));
 193    g_assert(qdict);
 194    g_assert_cmpint(qdict_size(qdict), ==, 2);
 195    g_assert_cmpstr(qdict_get_str(qdict, "string0"), ==, strings[0]);
 196
 197    dict1 = qdict_get_qdict(qdict, "dict1");
 198    g_assert_cmpint(qdict_size(dict1), ==, 3);
 199    g_assert_cmpstr(qdict_get_str(dict1, "string1"), ==, strings[1]);
 200
 201    dict2 = qdict_get_qdict(dict1, "dict2");
 202    g_assert_cmpint(qdict_size(dict2), ==, 2);
 203    g_assert_cmpstr(qdict_get_str(dict2, "string"), ==, strings[2]);
 204    userdef = qdict_get_qdict(dict2, "userdef");
 205    g_assert_cmpint(qdict_size(userdef), ==, 2);
 206    g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
 207    g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
 208
 209    dict3 = qdict_get_qdict(dict1, "dict3");
 210    g_assert_cmpint(qdict_size(dict3), ==, 2);
 211    g_assert_cmpstr(qdict_get_str(dict3, "string"), ==, strings[3]);
 212    userdef = qdict_get_qdict(dict3, "userdef");
 213    g_assert_cmpint(qdict_size(userdef), ==, 2);
 214    g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
 215    g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
 216
 217    qapi_free_UserDefTwo(ud2);
 218}
 219
 220static void test_visitor_out_list(TestOutputVisitorData *data,
 221                                  const void *unused)
 222{
 223    const char *value_str = "list value";
 224    TestStruct *value;
 225    TestStructList *head = NULL;
 226    const int max_items = 10;
 227    bool value_bool = true;
 228    int value_int = 10;
 229    QListEntry *entry;
 230    QList *qlist;
 231    int i;
 232
 233    /* Build the list in reverse order... */
 234    for (i = 0; i < max_items; i++) {
 235        value = g_malloc0(sizeof(*value));
 236        value->integer = value_int + (max_items - i - 1);
 237        value->boolean = value_bool;
 238        value->string = g_strdup(value_str);
 239
 240        QAPI_LIST_PREPEND(head, value);
 241    }
 242
 243    visit_type_TestStructList(data->ov, NULL, &head, &error_abort);
 244
 245    qlist = qobject_to(QList, visitor_get(data));
 246    g_assert(qlist);
 247    g_assert(!qlist_empty(qlist));
 248
 249    /* ...and ensure that the visitor sees it in order */
 250    i = 0;
 251    QLIST_FOREACH_ENTRY(qlist, entry) {
 252        QDict *qdict;
 253
 254        qdict = qobject_to(QDict, entry->value);
 255        g_assert(qdict);
 256        g_assert_cmpint(qdict_size(qdict), ==, 3);
 257        g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, value_int + i);
 258        g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, value_bool);
 259        g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, value_str);
 260        i++;
 261    }
 262    g_assert_cmpint(i, ==, max_items);
 263
 264    qapi_free_TestStructList(head);
 265}
 266
 267static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data,
 268                                            const void *unused)
 269{
 270    UserDefTwo *value;
 271    UserDefTwoList *head = NULL;
 272    const char string[] = "foo bar";
 273    int i, max_count = 1024;
 274
 275    for (i = 0; i < max_count; i++) {
 276        value = g_malloc0(sizeof(*value));
 277
 278        value->string0 = g_strdup(string);
 279        value->dict1 = g_new0(UserDefTwoDict, 1);
 280        value->dict1->string1 = g_strdup(string);
 281        value->dict1->dict2 = g_new0(UserDefTwoDictDict, 1);
 282        value->dict1->dict2->userdef = g_new0(UserDefOne, 1);
 283        value->dict1->dict2->userdef->string = g_strdup(string);
 284        value->dict1->dict2->userdef->integer = 42;
 285        value->dict1->dict2->string = g_strdup(string);
 286
 287        QAPI_LIST_PREPEND(head, value);
 288    }
 289
 290    qapi_free_UserDefTwoList(head);
 291}
 292
 293static void test_visitor_out_any(TestOutputVisitorData *data,
 294                                 const void *unused)
 295{
 296    QObject *qobj;
 297    QNum *qnum;
 298    QBool *qbool;
 299    QString *qstring;
 300    QDict *qdict;
 301    int64_t val;
 302
 303    qobj = QOBJECT(qnum_from_int(-42));
 304    visit_type_any(data->ov, NULL, &qobj, &error_abort);
 305    qnum = qobject_to(QNum, visitor_get(data));
 306    g_assert(qnum);
 307    g_assert(qnum_get_try_int(qnum, &val));
 308    g_assert_cmpint(val, ==, -42);
 309    qobject_unref(qobj);
 310
 311    visitor_reset(data);
 312    qdict = qdict_new();
 313    qdict_put_int(qdict, "integer", -42);
 314    qdict_put_bool(qdict, "boolean", true);
 315    qdict_put_str(qdict, "string", "foo");
 316    qobj = QOBJECT(qdict);
 317    visit_type_any(data->ov, NULL, &qobj, &error_abort);
 318    qobject_unref(qobj);
 319    qdict = qobject_to(QDict, visitor_get(data));
 320    g_assert(qdict);
 321    qnum = qobject_to(QNum, qdict_get(qdict, "integer"));
 322    g_assert(qnum);
 323    g_assert(qnum_get_try_int(qnum, &val));
 324    g_assert_cmpint(val, ==, -42);
 325    qbool = qobject_to(QBool, qdict_get(qdict, "boolean"));
 326    g_assert(qbool);
 327    g_assert(qbool_get_bool(qbool) == true);
 328    qstring = qobject_to(QString, qdict_get(qdict, "string"));
 329    g_assert(qstring);
 330    g_assert_cmpstr(qstring_get_str(qstring), ==, "foo");
 331}
 332
 333static void test_visitor_out_union_flat(TestOutputVisitorData *data,
 334                                        const void *unused)
 335{
 336    QDict *qdict;
 337
 338    UserDefFlatUnion *tmp = g_new0(UserDefFlatUnion, 1);
 339    tmp->enum1 = ENUM_ONE_VALUE1;
 340    tmp->string = g_strdup("str");
 341    tmp->integer = 41;
 342    tmp->u.value1.boolean = true;
 343
 344    visit_type_UserDefFlatUnion(data->ov, NULL, &tmp, &error_abort);
 345    qdict = qobject_to(QDict, visitor_get(data));
 346    g_assert(qdict);
 347    g_assert_cmpstr(qdict_get_str(qdict, "enum1"), ==, "value1");
 348    g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "str");
 349    g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 41);
 350    g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, true);
 351
 352    qapi_free_UserDefFlatUnion(tmp);
 353}
 354
 355static void test_visitor_out_alternate(TestOutputVisitorData *data,
 356                                       const void *unused)
 357{
 358    UserDefAlternate *tmp;
 359    QNum *qnum;
 360    QString *qstr;
 361    QDict *qdict;
 362    int64_t val;
 363
 364    tmp = g_new0(UserDefAlternate, 1);
 365    tmp->type = QTYPE_QNUM;
 366    tmp->u.i = 42;
 367
 368    visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
 369    qnum = qobject_to(QNum, visitor_get(data));
 370    g_assert(qnum);
 371    g_assert(qnum_get_try_int(qnum, &val));
 372    g_assert_cmpint(val, ==, 42);
 373
 374    qapi_free_UserDefAlternate(tmp);
 375
 376    visitor_reset(data);
 377    tmp = g_new0(UserDefAlternate, 1);
 378    tmp->type = QTYPE_QSTRING;
 379    tmp->u.e = ENUM_ONE_VALUE1;
 380
 381    visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
 382    qstr = qobject_to(QString, visitor_get(data));
 383    g_assert(qstr);
 384    g_assert_cmpstr(qstring_get_str(qstr), ==, "value1");
 385
 386    qapi_free_UserDefAlternate(tmp);
 387
 388    visitor_reset(data);
 389    tmp = g_new0(UserDefAlternate, 1);
 390    tmp->type = QTYPE_QNULL;
 391    tmp->u.n = qnull();
 392
 393    visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
 394    g_assert_cmpint(qobject_type(visitor_get(data)), ==, QTYPE_QNULL);
 395
 396    qapi_free_UserDefAlternate(tmp);
 397
 398    visitor_reset(data);
 399    tmp = g_new0(UserDefAlternate, 1);
 400    tmp->type = QTYPE_QDICT;
 401    tmp->u.udfu.integer = 1;
 402    tmp->u.udfu.string = g_strdup("str");
 403    tmp->u.udfu.enum1 = ENUM_ONE_VALUE1;
 404    tmp->u.udfu.u.value1.boolean = true;
 405
 406    visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
 407    qdict = qobject_to(QDict, visitor_get(data));
 408    g_assert(qdict);
 409    g_assert_cmpint(qdict_size(qdict), ==, 4);
 410    g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 1);
 411    g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "str");
 412    g_assert_cmpstr(qdict_get_str(qdict, "enum1"), ==, "value1");
 413    g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, true);
 414
 415    qapi_free_UserDefAlternate(tmp);
 416}
 417
 418static void test_visitor_out_null(TestOutputVisitorData *data,
 419                                  const void *unused)
 420{
 421    QNull *null = NULL;
 422    QDict *qdict;
 423    QObject *nil;
 424
 425    visit_start_struct(data->ov, NULL, NULL, 0, &error_abort);
 426    visit_type_null(data->ov, "a", &null, &error_abort);
 427    visit_check_struct(data->ov, &error_abort);
 428    visit_end_struct(data->ov, NULL);
 429    qdict = qobject_to(QDict, visitor_get(data));
 430    g_assert(qdict);
 431    g_assert_cmpint(qdict_size(qdict), ==, 1);
 432    nil = qdict_get(qdict, "a");
 433    g_assert(nil);
 434    g_assert(qobject_type(nil) == QTYPE_QNULL);
 435}
 436
 437static void test_visitor_out_list_struct(TestOutputVisitorData *data,
 438                                         const void *unused)
 439{
 440    const char *int_member[] = {
 441        "integer", "s8", "s16", "s32", "s64", "u8", "u16", "u32", "u64" };
 442    g_autoptr(ArrayStruct) arrs = g_new0(ArrayStruct, 1);
 443    int i, j;
 444    QDict *qdict;
 445    QList *qlist;
 446    QListEntry *e;
 447
 448    for (i = 31; i >= 0; i--) {
 449        QAPI_LIST_PREPEND(arrs->integer, i);
 450    }
 451
 452    for (i = 31; i >= 0; i--) {
 453        QAPI_LIST_PREPEND(arrs->s8, i);
 454    }
 455
 456    for (i = 31; i >= 0; i--) {
 457        QAPI_LIST_PREPEND(arrs->s16, i);
 458    }
 459
 460    for (i = 31; i >= 0; i--) {
 461        QAPI_LIST_PREPEND(arrs->s32, i);
 462    }
 463
 464    for (i = 31; i >= 0; i--) {
 465        QAPI_LIST_PREPEND(arrs->s64, i);
 466    }
 467
 468    for (i = 31; i >= 0; i--) {
 469        QAPI_LIST_PREPEND(arrs->u8, i);
 470    }
 471
 472    for (i = 31; i >= 0; i--) {
 473        QAPI_LIST_PREPEND(arrs->u16, i);
 474    }
 475
 476    for (i = 31; i >= 0; i--) {
 477        QAPI_LIST_PREPEND(arrs->u32, i);
 478    }
 479
 480    for (i = 31; i >= 0; i--) {
 481        QAPI_LIST_PREPEND(arrs->u64, i);
 482    }
 483
 484    for (i = 31; i >= 0; i--) {
 485        QAPI_LIST_PREPEND(arrs->number, (double)i / 3);
 486    }
 487
 488    for (i = 31; i >= 0; i--) {
 489        QAPI_LIST_PREPEND(arrs->boolean, QEMU_IS_ALIGNED(i, 3));
 490    }
 491
 492    for (i = 31; i >= 0; i--) {
 493        QAPI_LIST_PREPEND(arrs->string, g_strdup_printf("%d", i));
 494    }
 495
 496    visit_type_ArrayStruct(data->ov, NULL, &arrs, &error_abort);
 497
 498    qdict = qobject_to(QDict, visitor_get(data));
 499    g_assert(qdict);
 500
 501    for (i = 0; i < G_N_ELEMENTS(int_member); i++) {
 502        qlist = qdict_get_qlist(qdict, int_member[i]);
 503        g_assert(qlist);
 504        j = 0;
 505        QLIST_FOREACH_ENTRY(qlist, e) {
 506            QNum *qvalue = qobject_to(QNum, qlist_entry_obj(e));
 507            g_assert(qvalue);
 508            g_assert_cmpint(qnum_get_int(qvalue), ==, j);
 509            j++;
 510        }
 511    }
 512
 513    qlist = qdict_get_qlist(qdict, "number");
 514    g_assert(qlist);
 515    i = 0;
 516    QLIST_FOREACH_ENTRY(qlist, e) {
 517        QNum *qvalue = qobject_to(QNum, qlist_entry_obj(e));
 518        char expected[32], actual[32];
 519
 520        g_assert(qvalue);
 521        sprintf(expected, "%.6f", (double)i / 3);
 522        sprintf(actual, "%.6f", qnum_get_double(qvalue));
 523        g_assert_cmpstr(actual, ==, expected);
 524        i++;
 525    }
 526
 527    qlist = qdict_get_qlist(qdict, "boolean");
 528    g_assert(qlist);
 529    i = 0;
 530    QLIST_FOREACH_ENTRY(qlist, e) {
 531        QBool *qvalue = qobject_to(QBool, qlist_entry_obj(e));
 532        g_assert(qvalue);
 533        g_assert_cmpint(qbool_get_bool(qvalue), ==, i % 3 == 0);
 534        i++;
 535    }
 536
 537    qlist = qdict_get_qlist(qdict, "string");
 538    g_assert(qlist);
 539    i = 0;
 540    QLIST_FOREACH_ENTRY(qlist, e) {
 541        QString *qvalue = qobject_to(QString, qlist_entry_obj(e));
 542        char expected[32];
 543
 544        g_assert(qvalue);
 545        sprintf(expected, "%d", i);
 546        g_assert_cmpstr(qstring_get_str(qvalue), ==, expected);
 547        i++;
 548    }
 549}
 550
 551static void output_visitor_test_add(const char *testpath,
 552                                    TestOutputVisitorData *data,
 553                                    void (*test_func)(TestOutputVisitorData *data, const void *user_data))
 554{
 555    g_test_add(testpath, TestOutputVisitorData, data, visitor_output_setup,
 556               test_func, visitor_output_teardown);
 557}
 558
 559int main(int argc, char **argv)
 560{
 561    TestOutputVisitorData out_visitor_data;
 562
 563    g_test_init(&argc, &argv, NULL);
 564
 565    output_visitor_test_add("/visitor/output/int",
 566                            &out_visitor_data, test_visitor_out_int);
 567    output_visitor_test_add("/visitor/output/bool",
 568                            &out_visitor_data, test_visitor_out_bool);
 569    output_visitor_test_add("/visitor/output/number",
 570                            &out_visitor_data, test_visitor_out_number);
 571    output_visitor_test_add("/visitor/output/string",
 572                            &out_visitor_data, test_visitor_out_string);
 573    output_visitor_test_add("/visitor/output/no-string",
 574                            &out_visitor_data, test_visitor_out_no_string);
 575    output_visitor_test_add("/visitor/output/enum",
 576                            &out_visitor_data, test_visitor_out_enum);
 577    output_visitor_test_add("/visitor/output/struct",
 578                            &out_visitor_data, test_visitor_out_struct);
 579    output_visitor_test_add("/visitor/output/struct-nested",
 580                            &out_visitor_data, test_visitor_out_struct_nested);
 581    output_visitor_test_add("/visitor/output/list",
 582                            &out_visitor_data, test_visitor_out_list);
 583    output_visitor_test_add("/visitor/output/any",
 584                            &out_visitor_data, test_visitor_out_any);
 585    output_visitor_test_add("/visitor/output/list-qapi-free",
 586                            &out_visitor_data, test_visitor_out_list_qapi_free);
 587    output_visitor_test_add("/visitor/output/union-flat",
 588                            &out_visitor_data, test_visitor_out_union_flat);
 589    output_visitor_test_add("/visitor/output/alternate",
 590                            &out_visitor_data, test_visitor_out_alternate);
 591    output_visitor_test_add("/visitor/output/null",
 592                            &out_visitor_data, test_visitor_out_null);
 593    output_visitor_test_add("/visitor/output/list_struct",
 594                            &out_visitor_data, test_visitor_out_list_struct);
 595
 596    g_test_run();
 597
 598    return 0;
 599}
 600