Statistics
| Branch: | Revision:

root / tests / test-visitor-serialization.c @ 6141f3bd

History | View | Annotate | Download (33.4 kB)

1 2d496105 Michael Roth
/*
2 2d496105 Michael Roth
 * Unit-tests for visitor-based serialization
3 2d496105 Michael Roth
 *
4 2d496105 Michael Roth
 * Copyright IBM, Corp. 2012
5 2d496105 Michael Roth
 *
6 2d496105 Michael Roth
 * Authors:
7 2d496105 Michael Roth
 *  Michael Roth <mdroth@linux.vnet.ibm.com>
8 2d496105 Michael Roth
 *
9 2d496105 Michael Roth
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 2d496105 Michael Roth
 * See the COPYING file in the top-level directory.
11 2d496105 Michael Roth
 */
12 2d496105 Michael Roth
13 2d496105 Michael Roth
#include <glib.h>
14 2d496105 Michael Roth
#include <stdlib.h>
15 2d496105 Michael Roth
#include <stdint.h>
16 2d496105 Michael Roth
#include <float.h>
17 79ee7df8 Paolo Bonzini
18 79ee7df8 Paolo Bonzini
#include "qemu-common.h"
19 2d496105 Michael Roth
#include "test-qapi-types.h"
20 2d496105 Michael Roth
#include "test-qapi-visit.h"
21 7b1b5d19 Paolo Bonzini
#include "qapi/qmp/types.h"
22 2d496105 Michael Roth
#include "qapi/qmp-input-visitor.h"
23 2d496105 Michael Roth
#include "qapi/qmp-output-visitor.h"
24 0d30b0a2 Michael Roth
#include "qapi/string-input-visitor.h"
25 0d30b0a2 Michael Roth
#include "qapi/string-output-visitor.h"
26 8addacdd Michael Roth
#include "qapi-types.h"
27 8addacdd Michael Roth
#include "qapi-visit.h"
28 8addacdd Michael Roth
#include "qapi/dealloc-visitor.h"
29 8addacdd Michael Roth
30 8addacdd Michael Roth
enum PrimitiveTypeKind {
31 8addacdd Michael Roth
    PTYPE_STRING = 0,
32 8addacdd Michael Roth
    PTYPE_BOOLEAN,
33 8addacdd Michael Roth
    PTYPE_NUMBER,
34 8addacdd Michael Roth
    PTYPE_INTEGER,
35 8addacdd Michael Roth
    PTYPE_U8,
36 8addacdd Michael Roth
    PTYPE_U16,
37 8addacdd Michael Roth
    PTYPE_U32,
38 8addacdd Michael Roth
    PTYPE_U64,
39 8addacdd Michael Roth
    PTYPE_S8,
40 8addacdd Michael Roth
    PTYPE_S16,
41 8addacdd Michael Roth
    PTYPE_S32,
42 8addacdd Michael Roth
    PTYPE_S64,
43 8addacdd Michael Roth
    PTYPE_EOL,
44 8addacdd Michael Roth
};
45 2d496105 Michael Roth
46 2d496105 Michael Roth
typedef struct PrimitiveType {
47 2d496105 Michael Roth
    union {
48 2d496105 Michael Roth
        const char *string;
49 2d496105 Michael Roth
        bool boolean;
50 2d496105 Michael Roth
        double number;
51 2d496105 Michael Roth
        int64_t integer;
52 2d496105 Michael Roth
        uint8_t u8;
53 2d496105 Michael Roth
        uint16_t u16;
54 2d496105 Michael Roth
        uint32_t u32;
55 2d496105 Michael Roth
        uint64_t u64;
56 2d496105 Michael Roth
        int8_t s8;
57 2d496105 Michael Roth
        int16_t s16;
58 2d496105 Michael Roth
        int32_t s32;
59 2d496105 Michael Roth
        int64_t s64;
60 2d496105 Michael Roth
        intmax_t max;
61 2d496105 Michael Roth
    } value;
62 8addacdd Michael Roth
    enum PrimitiveTypeKind type;
63 2d496105 Michael Roth
    const char *description;
64 2d496105 Michael Roth
} PrimitiveType;
65 2d496105 Michael Roth
66 8addacdd Michael Roth
typedef struct PrimitiveList {
67 8addacdd Michael Roth
    union {
68 8addacdd Michael Roth
        strList *strings;
69 8addacdd Michael Roth
        boolList *booleans;
70 8addacdd Michael Roth
        numberList *numbers;
71 8addacdd Michael Roth
        intList *integers;
72 8addacdd Michael Roth
        int8List *s8_integers;
73 8addacdd Michael Roth
        int16List *s16_integers;
74 8addacdd Michael Roth
        int32List *s32_integers;
75 8addacdd Michael Roth
        int64List *s64_integers;
76 8addacdd Michael Roth
        uint8List *u8_integers;
77 8addacdd Michael Roth
        uint16List *u16_integers;
78 8addacdd Michael Roth
        uint32List *u32_integers;
79 8addacdd Michael Roth
        uint64List *u64_integers;
80 8addacdd Michael Roth
    } value;
81 8addacdd Michael Roth
    enum PrimitiveTypeKind type;
82 8addacdd Michael Roth
    const char *description;
83 8addacdd Michael Roth
} PrimitiveList;
84 8addacdd Michael Roth
85 2d496105 Michael Roth
/* test helpers */
86 2d496105 Michael Roth
87 8addacdd Michael Roth
typedef void (*VisitorFunc)(Visitor *v, void **native, Error **errp);
88 8addacdd Michael Roth
89 8addacdd Michael Roth
static void dealloc_helper(void *native_in, VisitorFunc visit, Error **errp)
90 8addacdd Michael Roth
{
91 8addacdd Michael Roth
    QapiDeallocVisitor *qdv = qapi_dealloc_visitor_new();
92 8addacdd Michael Roth
93 8addacdd Michael Roth
    visit(qapi_dealloc_get_visitor(qdv), &native_in, errp);
94 8addacdd Michael Roth
95 8addacdd Michael Roth
    qapi_dealloc_visitor_cleanup(qdv);
96 8addacdd Michael Roth
}
97 8addacdd Michael Roth
98 2d496105 Michael Roth
static void visit_primitive_type(Visitor *v, void **native, Error **errp)
99 2d496105 Michael Roth
{
100 2d496105 Michael Roth
    PrimitiveType *pt = *native;
101 2d496105 Michael Roth
    switch(pt->type) {
102 2d496105 Michael Roth
    case PTYPE_STRING:
103 2d496105 Michael Roth
        visit_type_str(v, (char **)&pt->value.string, NULL, errp);
104 2d496105 Michael Roth
        break;
105 2d496105 Michael Roth
    case PTYPE_BOOLEAN:
106 2d496105 Michael Roth
        visit_type_bool(v, &pt->value.boolean, NULL, errp);
107 2d496105 Michael Roth
        break;
108 2d496105 Michael Roth
    case PTYPE_NUMBER:
109 2d496105 Michael Roth
        visit_type_number(v, &pt->value.number, NULL, errp);
110 2d496105 Michael Roth
        break;
111 2d496105 Michael Roth
    case PTYPE_INTEGER:
112 2d496105 Michael Roth
        visit_type_int(v, &pt->value.integer, NULL, errp);
113 2d496105 Michael Roth
        break;
114 2d496105 Michael Roth
    case PTYPE_U8:
115 2d496105 Michael Roth
        visit_type_uint8(v, &pt->value.u8, NULL, errp);
116 2d496105 Michael Roth
        break;
117 2d496105 Michael Roth
    case PTYPE_U16:
118 2d496105 Michael Roth
        visit_type_uint16(v, &pt->value.u16, NULL, errp);
119 2d496105 Michael Roth
        break;
120 2d496105 Michael Roth
    case PTYPE_U32:
121 2d496105 Michael Roth
        visit_type_uint32(v, &pt->value.u32, NULL, errp);
122 2d496105 Michael Roth
        break;
123 2d496105 Michael Roth
    case PTYPE_U64:
124 2d496105 Michael Roth
        visit_type_uint64(v, &pt->value.u64, NULL, errp);
125 2d496105 Michael Roth
        break;
126 2d496105 Michael Roth
    case PTYPE_S8:
127 2d496105 Michael Roth
        visit_type_int8(v, &pt->value.s8, NULL, errp);
128 2d496105 Michael Roth
        break;
129 2d496105 Michael Roth
    case PTYPE_S16:
130 2d496105 Michael Roth
        visit_type_int16(v, &pt->value.s16, NULL, errp);
131 2d496105 Michael Roth
        break;
132 2d496105 Michael Roth
    case PTYPE_S32:
133 2d496105 Michael Roth
        visit_type_int32(v, &pt->value.s32, NULL, errp);
134 2d496105 Michael Roth
        break;
135 2d496105 Michael Roth
    case PTYPE_S64:
136 2d496105 Michael Roth
        visit_type_int64(v, &pt->value.s64, NULL, errp);
137 2d496105 Michael Roth
        break;
138 2d496105 Michael Roth
    case PTYPE_EOL:
139 dfc6f865 Stefan Weil
        g_assert_not_reached();
140 2d496105 Michael Roth
    }
141 2d496105 Michael Roth
}
142 2d496105 Michael Roth
143 8addacdd Michael Roth
static void visit_primitive_list(Visitor *v, void **native, Error **errp)
144 8addacdd Michael Roth
{
145 8addacdd Michael Roth
    PrimitiveList *pl = *native;
146 8addacdd Michael Roth
    switch (pl->type) {
147 8addacdd Michael Roth
    case PTYPE_STRING:
148 8addacdd Michael Roth
        visit_type_strList(v, &pl->value.strings, NULL, errp);
149 8addacdd Michael Roth
        break;
150 8addacdd Michael Roth
    case PTYPE_BOOLEAN:
151 8addacdd Michael Roth
        visit_type_boolList(v, &pl->value.booleans, NULL, errp);
152 8addacdd Michael Roth
        break;
153 8addacdd Michael Roth
    case PTYPE_NUMBER:
154 8addacdd Michael Roth
        visit_type_numberList(v, &pl->value.numbers, NULL, errp);
155 8addacdd Michael Roth
        break;
156 8addacdd Michael Roth
    case PTYPE_INTEGER:
157 8addacdd Michael Roth
        visit_type_intList(v, &pl->value.integers, NULL, errp);
158 8addacdd Michael Roth
        break;
159 8addacdd Michael Roth
    case PTYPE_S8:
160 8addacdd Michael Roth
        visit_type_int8List(v, &pl->value.s8_integers, NULL, errp);
161 8addacdd Michael Roth
        break;
162 8addacdd Michael Roth
    case PTYPE_S16:
163 8addacdd Michael Roth
        visit_type_int16List(v, &pl->value.s16_integers, NULL, errp);
164 8addacdd Michael Roth
        break;
165 8addacdd Michael Roth
    case PTYPE_S32:
166 8addacdd Michael Roth
        visit_type_int32List(v, &pl->value.s32_integers, NULL, errp);
167 8addacdd Michael Roth
        break;
168 8addacdd Michael Roth
    case PTYPE_S64:
169 8addacdd Michael Roth
        visit_type_int64List(v, &pl->value.s64_integers, NULL, errp);
170 8addacdd Michael Roth
        break;
171 8addacdd Michael Roth
    case PTYPE_U8:
172 8addacdd Michael Roth
        visit_type_uint8List(v, &pl->value.u8_integers, NULL, errp);
173 8addacdd Michael Roth
        break;
174 8addacdd Michael Roth
    case PTYPE_U16:
175 8addacdd Michael Roth
        visit_type_uint16List(v, &pl->value.u16_integers, NULL, errp);
176 8addacdd Michael Roth
        break;
177 8addacdd Michael Roth
    case PTYPE_U32:
178 8addacdd Michael Roth
        visit_type_uint32List(v, &pl->value.u32_integers, NULL, errp);
179 8addacdd Michael Roth
        break;
180 8addacdd Michael Roth
    case PTYPE_U64:
181 8addacdd Michael Roth
        visit_type_uint64List(v, &pl->value.u64_integers, NULL, errp);
182 8addacdd Michael Roth
        break;
183 8addacdd Michael Roth
    default:
184 dfc6f865 Stefan Weil
        g_assert_not_reached();
185 8addacdd Michael Roth
    }
186 8addacdd Michael Roth
}
187 8addacdd Michael Roth
188 2d496105 Michael Roth
typedef struct TestStruct
189 2d496105 Michael Roth
{
190 2d496105 Michael Roth
    int64_t integer;
191 2d496105 Michael Roth
    bool boolean;
192 2d496105 Michael Roth
    char *string;
193 2d496105 Michael Roth
} TestStruct;
194 2d496105 Michael Roth
195 2d496105 Michael Roth
static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
196 2d496105 Michael Roth
                                  const char *name, Error **errp)
197 2d496105 Michael Roth
{
198 2d496105 Michael Roth
    visit_start_struct(v, (void **)obj, NULL, name, sizeof(TestStruct), errp);
199 2d496105 Michael Roth
200 2d496105 Michael Roth
    visit_type_int(v, &(*obj)->integer, "integer", errp);
201 2d496105 Michael Roth
    visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
202 2d496105 Michael Roth
    visit_type_str(v, &(*obj)->string, "string", errp);
203 2d496105 Michael Roth
204 2d496105 Michael Roth
    visit_end_struct(v, errp);
205 2d496105 Michael Roth
}
206 2d496105 Michael Roth
207 2d496105 Michael Roth
static TestStruct *struct_create(void)
208 2d496105 Michael Roth
{
209 2d496105 Michael Roth
    TestStruct *ts = g_malloc0(sizeof(*ts));
210 2d496105 Michael Roth
    ts->integer = -42;
211 2d496105 Michael Roth
    ts->boolean = true;
212 2d496105 Michael Roth
    ts->string = strdup("test string");
213 2d496105 Michael Roth
    return ts;
214 2d496105 Michael Roth
}
215 2d496105 Michael Roth
216 2d496105 Michael Roth
static void struct_compare(TestStruct *ts1, TestStruct *ts2)
217 2d496105 Michael Roth
{
218 2d496105 Michael Roth
    g_assert(ts1);
219 2d496105 Michael Roth
    g_assert(ts2);
220 2d496105 Michael Roth
    g_assert_cmpint(ts1->integer, ==, ts2->integer);
221 2d496105 Michael Roth
    g_assert(ts1->boolean == ts2->boolean);
222 2d496105 Michael Roth
    g_assert_cmpstr(ts1->string, ==, ts2->string);
223 2d496105 Michael Roth
}
224 2d496105 Michael Roth
225 2d496105 Michael Roth
static void struct_cleanup(TestStruct *ts)
226 2d496105 Michael Roth
{
227 2d496105 Michael Roth
    g_free(ts->string);
228 2d496105 Michael Roth
    g_free(ts);
229 2d496105 Michael Roth
}
230 2d496105 Michael Roth
231 2d496105 Michael Roth
static void visit_struct(Visitor *v, void **native, Error **errp)
232 2d496105 Michael Roth
{
233 2d496105 Michael Roth
    visit_type_TestStruct(v, (TestStruct **)native, NULL, errp);
234 2d496105 Michael Roth
}
235 2d496105 Michael Roth
236 2d496105 Michael Roth
static UserDefNested *nested_struct_create(void)
237 2d496105 Michael Roth
{
238 2d496105 Michael Roth
    UserDefNested *udnp = g_malloc0(sizeof(*udnp));
239 2d496105 Michael Roth
    udnp->string0 = strdup("test_string0");
240 2d496105 Michael Roth
    udnp->dict1.string1 = strdup("test_string1");
241 2d496105 Michael Roth
    udnp->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
242 2d496105 Michael Roth
    udnp->dict1.dict2.userdef1->integer = 42;
243 2d496105 Michael Roth
    udnp->dict1.dict2.userdef1->string = strdup("test_string");
244 2d496105 Michael Roth
    udnp->dict1.dict2.string2 = strdup("test_string2");
245 2d496105 Michael Roth
    udnp->dict1.has_dict3 = true;
246 2d496105 Michael Roth
    udnp->dict1.dict3.userdef2 = g_malloc0(sizeof(UserDefOne));
247 2d496105 Michael Roth
    udnp->dict1.dict3.userdef2->integer = 43;
248 2d496105 Michael Roth
    udnp->dict1.dict3.userdef2->string = strdup("test_string");
249 2d496105 Michael Roth
    udnp->dict1.dict3.string3 = strdup("test_string3");
250 2d496105 Michael Roth
    return udnp;
251 2d496105 Michael Roth
}
252 2d496105 Michael Roth
253 2d496105 Michael Roth
static void nested_struct_compare(UserDefNested *udnp1, UserDefNested *udnp2)
254 2d496105 Michael Roth
{
255 2d496105 Michael Roth
    g_assert(udnp1);
256 2d496105 Michael Roth
    g_assert(udnp2);
257 2d496105 Michael Roth
    g_assert_cmpstr(udnp1->string0, ==, udnp2->string0);
258 2d496105 Michael Roth
    g_assert_cmpstr(udnp1->dict1.string1, ==, udnp2->dict1.string1);
259 2d496105 Michael Roth
    g_assert_cmpint(udnp1->dict1.dict2.userdef1->integer, ==,
260 2d496105 Michael Roth
                    udnp2->dict1.dict2.userdef1->integer);
261 2d496105 Michael Roth
    g_assert_cmpstr(udnp1->dict1.dict2.userdef1->string, ==,
262 2d496105 Michael Roth
                    udnp2->dict1.dict2.userdef1->string);
263 2d496105 Michael Roth
    g_assert_cmpstr(udnp1->dict1.dict2.string2, ==, udnp2->dict1.dict2.string2);
264 2d496105 Michael Roth
    g_assert(udnp1->dict1.has_dict3 == udnp2->dict1.has_dict3);
265 2d496105 Michael Roth
    g_assert_cmpint(udnp1->dict1.dict3.userdef2->integer, ==,
266 2d496105 Michael Roth
                    udnp2->dict1.dict3.userdef2->integer);
267 2d496105 Michael Roth
    g_assert_cmpstr(udnp1->dict1.dict3.userdef2->string, ==,
268 2d496105 Michael Roth
                    udnp2->dict1.dict3.userdef2->string);
269 2d496105 Michael Roth
    g_assert_cmpstr(udnp1->dict1.dict3.string3, ==, udnp2->dict1.dict3.string3);
270 2d496105 Michael Roth
}
271 2d496105 Michael Roth
272 2d496105 Michael Roth
static void nested_struct_cleanup(UserDefNested *udnp)
273 2d496105 Michael Roth
{
274 2d496105 Michael Roth
    qapi_free_UserDefNested(udnp);
275 2d496105 Michael Roth
}
276 2d496105 Michael Roth
277 2d496105 Michael Roth
static void visit_nested_struct(Visitor *v, void **native, Error **errp)
278 2d496105 Michael Roth
{
279 2d496105 Michael Roth
    visit_type_UserDefNested(v, (UserDefNested **)native, NULL, errp);
280 2d496105 Michael Roth
}
281 2d496105 Michael Roth
282 2d496105 Michael Roth
static void visit_nested_struct_list(Visitor *v, void **native, Error **errp)
283 2d496105 Michael Roth
{
284 2d496105 Michael Roth
    visit_type_UserDefNestedList(v, (UserDefNestedList **)native, NULL, errp);
285 2d496105 Michael Roth
}
286 2d496105 Michael Roth
287 2d496105 Michael Roth
/* test cases */
288 2d496105 Michael Roth
289 2d496105 Michael Roth
typedef enum VisitorCapabilities {
290 2d496105 Michael Roth
    VCAP_PRIMITIVES = 1,
291 2d496105 Michael Roth
    VCAP_STRUCTURES = 2,
292 2d496105 Michael Roth
    VCAP_LISTS = 4,
293 8addacdd Michael Roth
    VCAP_PRIMITIVE_LISTS = 8,
294 2d496105 Michael Roth
} VisitorCapabilities;
295 2d496105 Michael Roth
296 2d496105 Michael Roth
typedef struct SerializeOps {
297 2d496105 Michael Roth
    void (*serialize)(void *native_in, void **datap,
298 2d496105 Michael Roth
                      VisitorFunc visit, Error **errp);
299 2d496105 Michael Roth
    void (*deserialize)(void **native_out, void *datap,
300 2d496105 Michael Roth
                            VisitorFunc visit, Error **errp);
301 2d496105 Michael Roth
    void (*cleanup)(void *datap);
302 2d496105 Michael Roth
    const char *type;
303 2d496105 Michael Roth
    VisitorCapabilities caps;
304 2d496105 Michael Roth
} SerializeOps;
305 2d496105 Michael Roth
306 2d496105 Michael Roth
typedef struct TestArgs {
307 2d496105 Michael Roth
    const SerializeOps *ops;
308 2d496105 Michael Roth
    void *test_data;
309 2d496105 Michael Roth
} TestArgs;
310 2d496105 Michael Roth
311 2d496105 Michael Roth
static void test_primitives(gconstpointer opaque)
312 2d496105 Michael Roth
{
313 2d496105 Michael Roth
    TestArgs *args = (TestArgs *) opaque;
314 2d496105 Michael Roth
    const SerializeOps *ops = args->ops;
315 2d496105 Michael Roth
    PrimitiveType *pt = args->test_data;
316 2d496105 Michael Roth
    PrimitiveType *pt_copy = g_malloc0(sizeof(*pt_copy));
317 2d496105 Michael Roth
    Error *err = NULL;
318 2d496105 Michael Roth
    void *serialize_data;
319 2d496105 Michael Roth
320 2d496105 Michael Roth
    pt_copy->type = pt->type;
321 2d496105 Michael Roth
    ops->serialize(pt, &serialize_data, visit_primitive_type, &err);
322 2d496105 Michael Roth
    ops->deserialize((void **)&pt_copy, serialize_data, visit_primitive_type, &err);
323 2d496105 Michael Roth
324 2d496105 Michael Roth
    g_assert(err == NULL);
325 2d496105 Michael Roth
    g_assert(pt_copy != NULL);
326 2d496105 Michael Roth
    if (pt->type == PTYPE_STRING) {
327 2d496105 Michael Roth
        g_assert_cmpstr(pt->value.string, ==, pt_copy->value.string);
328 2bd01ac1 Stefan Berger
        g_free((char *)pt_copy->value.string);
329 2d496105 Michael Roth
    } else if (pt->type == PTYPE_NUMBER) {
330 089f26bb Michael Roth
        GString *double_expected = g_string_new("");
331 089f26bb Michael Roth
        GString *double_actual = g_string_new("");
332 2d496105 Michael Roth
        /* we serialize with %f for our reference visitors, so rather than fuzzy
333 2d496105 Michael Roth
         * floating math to test "equality", just compare the formatted values
334 2d496105 Michael Roth
         */
335 089f26bb Michael Roth
        g_string_printf(double_expected, "%.6f", pt->value.number);
336 089f26bb Michael Roth
        g_string_printf(double_actual, "%.6f", pt_copy->value.number);
337 089f26bb Michael Roth
        g_assert_cmpstr(double_actual->str, ==, double_expected->str);
338 089f26bb Michael Roth
339 089f26bb Michael Roth
        g_string_free(double_expected, true);
340 089f26bb Michael Roth
        g_string_free(double_actual, true);
341 2d496105 Michael Roth
    } else if (pt->type == PTYPE_BOOLEAN) {
342 2d496105 Michael Roth
        g_assert_cmpint(!!pt->value.max, ==, !!pt->value.max);
343 2d496105 Michael Roth
    } else {
344 2d496105 Michael Roth
        g_assert_cmpint(pt->value.max, ==, pt_copy->value.max);
345 2d496105 Michael Roth
    }
346 2d496105 Michael Roth
347 2d496105 Michael Roth
    ops->cleanup(serialize_data);
348 2d496105 Michael Roth
    g_free(args);
349 2bd01ac1 Stefan Berger
    g_free(pt_copy);
350 2d496105 Michael Roth
}
351 2d496105 Michael Roth
352 8addacdd Michael Roth
static void test_primitive_lists(gconstpointer opaque)
353 8addacdd Michael Roth
{
354 8addacdd Michael Roth
    TestArgs *args = (TestArgs *) opaque;
355 8addacdd Michael Roth
    const SerializeOps *ops = args->ops;
356 8addacdd Michael Roth
    PrimitiveType *pt = args->test_data;
357 8addacdd Michael Roth
    PrimitiveList pl = { .value = { 0 } };
358 8addacdd Michael Roth
    PrimitiveList pl_copy = { .value = { 0 } };
359 8addacdd Michael Roth
    PrimitiveList *pl_copy_ptr = &pl_copy;
360 8addacdd Michael Roth
    Error *err = NULL;
361 8addacdd Michael Roth
    void *serialize_data;
362 8addacdd Michael Roth
    void *cur_head = NULL;
363 8addacdd Michael Roth
    int i;
364 8addacdd Michael Roth
365 8addacdd Michael Roth
    pl.type = pl_copy.type = pt->type;
366 8addacdd Michael Roth
367 8addacdd Michael Roth
    /* build up our list of primitive types */
368 8addacdd Michael Roth
    for (i = 0; i < 32; i++) {
369 8addacdd Michael Roth
        switch (pl.type) {
370 8addacdd Michael Roth
        case PTYPE_STRING: {
371 8addacdd Michael Roth
            strList *tmp = g_new0(strList, 1);
372 8addacdd Michael Roth
            tmp->value = g_strdup(pt->value.string);
373 8addacdd Michael Roth
            if (pl.value.strings == NULL) {
374 8addacdd Michael Roth
                pl.value.strings = tmp;
375 8addacdd Michael Roth
            } else {
376 8addacdd Michael Roth
                tmp->next = pl.value.strings;
377 8addacdd Michael Roth
                pl.value.strings = tmp;
378 8addacdd Michael Roth
            }
379 8addacdd Michael Roth
            break;
380 8addacdd Michael Roth
        }
381 8addacdd Michael Roth
        case PTYPE_INTEGER: {
382 8addacdd Michael Roth
            intList *tmp = g_new0(intList, 1);
383 8addacdd Michael Roth
            tmp->value = pt->value.integer;
384 8addacdd Michael Roth
            if (pl.value.integers == NULL) {
385 8addacdd Michael Roth
                pl.value.integers = tmp;
386 8addacdd Michael Roth
            } else {
387 8addacdd Michael Roth
                tmp->next = pl.value.integers;
388 8addacdd Michael Roth
                pl.value.integers = tmp;
389 8addacdd Michael Roth
            }
390 8addacdd Michael Roth
            break;
391 8addacdd Michael Roth
        }
392 8addacdd Michael Roth
        case PTYPE_S8: {
393 8addacdd Michael Roth
            int8List *tmp = g_new0(int8List, 1);
394 8addacdd Michael Roth
            tmp->value = pt->value.s8;
395 8addacdd Michael Roth
            if (pl.value.s8_integers == NULL) {
396 8addacdd Michael Roth
                pl.value.s8_integers = tmp;
397 8addacdd Michael Roth
            } else {
398 8addacdd Michael Roth
                tmp->next = pl.value.s8_integers;
399 8addacdd Michael Roth
                pl.value.s8_integers = tmp;
400 8addacdd Michael Roth
            }
401 8addacdd Michael Roth
            break;
402 8addacdd Michael Roth
        }
403 8addacdd Michael Roth
        case PTYPE_S16: {
404 8addacdd Michael Roth
            int16List *tmp = g_new0(int16List, 1);
405 8addacdd Michael Roth
            tmp->value = pt->value.s16;
406 8addacdd Michael Roth
            if (pl.value.s16_integers == NULL) {
407 8addacdd Michael Roth
                pl.value.s16_integers = tmp;
408 8addacdd Michael Roth
            } else {
409 8addacdd Michael Roth
                tmp->next = pl.value.s16_integers;
410 8addacdd Michael Roth
                pl.value.s16_integers = tmp;
411 8addacdd Michael Roth
            }
412 8addacdd Michael Roth
            break;
413 8addacdd Michael Roth
        }
414 8addacdd Michael Roth
        case PTYPE_S32: {
415 8addacdd Michael Roth
            int32List *tmp = g_new0(int32List, 1);
416 8addacdd Michael Roth
            tmp->value = pt->value.s32;
417 8addacdd Michael Roth
            if (pl.value.s32_integers == NULL) {
418 8addacdd Michael Roth
                pl.value.s32_integers = tmp;
419 8addacdd Michael Roth
            } else {
420 8addacdd Michael Roth
                tmp->next = pl.value.s32_integers;
421 8addacdd Michael Roth
                pl.value.s32_integers = tmp;
422 8addacdd Michael Roth
            }
423 8addacdd Michael Roth
            break;
424 8addacdd Michael Roth
        }
425 8addacdd Michael Roth
        case PTYPE_S64: {
426 8addacdd Michael Roth
            int64List *tmp = g_new0(int64List, 1);
427 8addacdd Michael Roth
            tmp->value = pt->value.s64;
428 8addacdd Michael Roth
            if (pl.value.s64_integers == NULL) {
429 8addacdd Michael Roth
                pl.value.s64_integers = tmp;
430 8addacdd Michael Roth
            } else {
431 8addacdd Michael Roth
                tmp->next = pl.value.s64_integers;
432 8addacdd Michael Roth
                pl.value.s64_integers = tmp;
433 8addacdd Michael Roth
            }
434 8addacdd Michael Roth
            break;
435 8addacdd Michael Roth
        }
436 8addacdd Michael Roth
        case PTYPE_U8: {
437 8addacdd Michael Roth
            uint8List *tmp = g_new0(uint8List, 1);
438 8addacdd Michael Roth
            tmp->value = pt->value.u8;
439 8addacdd Michael Roth
            if (pl.value.u8_integers == NULL) {
440 8addacdd Michael Roth
                pl.value.u8_integers = tmp;
441 8addacdd Michael Roth
            } else {
442 8addacdd Michael Roth
                tmp->next = pl.value.u8_integers;
443 8addacdd Michael Roth
                pl.value.u8_integers = tmp;
444 8addacdd Michael Roth
            }
445 8addacdd Michael Roth
            break;
446 8addacdd Michael Roth
        }
447 8addacdd Michael Roth
        case PTYPE_U16: {
448 8addacdd Michael Roth
            uint16List *tmp = g_new0(uint16List, 1);
449 8addacdd Michael Roth
            tmp->value = pt->value.u16;
450 8addacdd Michael Roth
            if (pl.value.u16_integers == NULL) {
451 8addacdd Michael Roth
                pl.value.u16_integers = tmp;
452 8addacdd Michael Roth
            } else {
453 8addacdd Michael Roth
                tmp->next = pl.value.u16_integers;
454 8addacdd Michael Roth
                pl.value.u16_integers = tmp;
455 8addacdd Michael Roth
            }
456 8addacdd Michael Roth
            break;
457 8addacdd Michael Roth
        }
458 8addacdd Michael Roth
        case PTYPE_U32: {
459 8addacdd Michael Roth
            uint32List *tmp = g_new0(uint32List, 1);
460 8addacdd Michael Roth
            tmp->value = pt->value.u32;
461 8addacdd Michael Roth
            if (pl.value.u32_integers == NULL) {
462 8addacdd Michael Roth
                pl.value.u32_integers = tmp;
463 8addacdd Michael Roth
            } else {
464 8addacdd Michael Roth
                tmp->next = pl.value.u32_integers;
465 8addacdd Michael Roth
                pl.value.u32_integers = tmp;
466 8addacdd Michael Roth
            }
467 8addacdd Michael Roth
            break;
468 8addacdd Michael Roth
        }
469 8addacdd Michael Roth
        case PTYPE_U64: {
470 8addacdd Michael Roth
            uint64List *tmp = g_new0(uint64List, 1);
471 8addacdd Michael Roth
            tmp->value = pt->value.u64;
472 8addacdd Michael Roth
            if (pl.value.u64_integers == NULL) {
473 8addacdd Michael Roth
                pl.value.u64_integers = tmp;
474 8addacdd Michael Roth
            } else {
475 8addacdd Michael Roth
                tmp->next = pl.value.u64_integers;
476 8addacdd Michael Roth
                pl.value.u64_integers = tmp;
477 8addacdd Michael Roth
            }
478 8addacdd Michael Roth
            break;
479 8addacdd Michael Roth
        }
480 8addacdd Michael Roth
        case PTYPE_NUMBER: {
481 8addacdd Michael Roth
            numberList *tmp = g_new0(numberList, 1);
482 8addacdd Michael Roth
            tmp->value = pt->value.number;
483 8addacdd Michael Roth
            if (pl.value.numbers == NULL) {
484 8addacdd Michael Roth
                pl.value.numbers = tmp;
485 8addacdd Michael Roth
            } else {
486 8addacdd Michael Roth
                tmp->next = pl.value.numbers;
487 8addacdd Michael Roth
                pl.value.numbers = tmp;
488 8addacdd Michael Roth
            }
489 8addacdd Michael Roth
            break;
490 8addacdd Michael Roth
        }
491 8addacdd Michael Roth
        case PTYPE_BOOLEAN: {
492 8addacdd Michael Roth
            boolList *tmp = g_new0(boolList, 1);
493 8addacdd Michael Roth
            tmp->value = pt->value.boolean;
494 8addacdd Michael Roth
            if (pl.value.booleans == NULL) {
495 8addacdd Michael Roth
                pl.value.booleans = tmp;
496 8addacdd Michael Roth
            } else {
497 8addacdd Michael Roth
                tmp->next = pl.value.booleans;
498 8addacdd Michael Roth
                pl.value.booleans = tmp;
499 8addacdd Michael Roth
            }
500 8addacdd Michael Roth
            break;
501 8addacdd Michael Roth
        }
502 8addacdd Michael Roth
        default:
503 dfc6f865 Stefan Weil
            g_assert_not_reached();
504 8addacdd Michael Roth
        }
505 8addacdd Michael Roth
    }
506 8addacdd Michael Roth
507 8addacdd Michael Roth
    ops->serialize((void **)&pl, &serialize_data, visit_primitive_list, &err);
508 8addacdd Michael Roth
    ops->deserialize((void **)&pl_copy_ptr, serialize_data, visit_primitive_list, &err);
509 8addacdd Michael Roth
510 8addacdd Michael Roth
    g_assert(err == NULL);
511 8addacdd Michael Roth
    i = 0;
512 8addacdd Michael Roth
513 8addacdd Michael Roth
    /* compare our deserialized list of primitives to the original */
514 8addacdd Michael Roth
    do {
515 8addacdd Michael Roth
        switch (pl_copy.type) {
516 8addacdd Michael Roth
        case PTYPE_STRING: {
517 8addacdd Michael Roth
            strList *ptr;
518 8addacdd Michael Roth
            if (cur_head) {
519 8addacdd Michael Roth
                ptr = cur_head;
520 8addacdd Michael Roth
                cur_head = ptr->next;
521 8addacdd Michael Roth
            } else {
522 8addacdd Michael Roth
                cur_head = ptr = pl_copy.value.strings;
523 8addacdd Michael Roth
            }
524 8addacdd Michael Roth
            g_assert_cmpstr(pt->value.string, ==, ptr->value);
525 8addacdd Michael Roth
            break;
526 8addacdd Michael Roth
        }
527 8addacdd Michael Roth
        case PTYPE_INTEGER: {
528 8addacdd Michael Roth
            intList *ptr;
529 8addacdd Michael Roth
            if (cur_head) {
530 8addacdd Michael Roth
                ptr = cur_head;
531 8addacdd Michael Roth
                cur_head = ptr->next;
532 8addacdd Michael Roth
            } else {
533 8addacdd Michael Roth
                cur_head = ptr = pl_copy.value.integers;
534 8addacdd Michael Roth
            }
535 8addacdd Michael Roth
            g_assert_cmpint(pt->value.integer, ==, ptr->value);
536 8addacdd Michael Roth
            break;
537 8addacdd Michael Roth
        }
538 8addacdd Michael Roth
        case PTYPE_S8: {
539 8addacdd Michael Roth
            int8List *ptr;
540 8addacdd Michael Roth
            if (cur_head) {
541 8addacdd Michael Roth
                ptr = cur_head;
542 8addacdd Michael Roth
                cur_head = ptr->next;
543 8addacdd Michael Roth
            } else {
544 8addacdd Michael Roth
                cur_head = ptr = pl_copy.value.s8_integers;
545 8addacdd Michael Roth
            }
546 8addacdd Michael Roth
            g_assert_cmpint(pt->value.s8, ==, ptr->value);
547 8addacdd Michael Roth
            break;
548 8addacdd Michael Roth
        }
549 8addacdd Michael Roth
        case PTYPE_S16: {
550 8addacdd Michael Roth
            int16List *ptr;
551 8addacdd Michael Roth
            if (cur_head) {
552 8addacdd Michael Roth
                ptr = cur_head;
553 8addacdd Michael Roth
                cur_head = ptr->next;
554 8addacdd Michael Roth
            } else {
555 8addacdd Michael Roth
                cur_head = ptr = pl_copy.value.s16_integers;
556 8addacdd Michael Roth
            }
557 8addacdd Michael Roth
            g_assert_cmpint(pt->value.s16, ==, ptr->value);
558 8addacdd Michael Roth
            break;
559 8addacdd Michael Roth
        }
560 8addacdd Michael Roth
        case PTYPE_S32: {
561 8addacdd Michael Roth
            int32List *ptr;
562 8addacdd Michael Roth
            if (cur_head) {
563 8addacdd Michael Roth
                ptr = cur_head;
564 8addacdd Michael Roth
                cur_head = ptr->next;
565 8addacdd Michael Roth
            } else {
566 8addacdd Michael Roth
                cur_head = ptr = pl_copy.value.s32_integers;
567 8addacdd Michael Roth
            }
568 8addacdd Michael Roth
            g_assert_cmpint(pt->value.s32, ==, ptr->value);
569 8addacdd Michael Roth
            break;
570 8addacdd Michael Roth
        }
571 8addacdd Michael Roth
        case PTYPE_S64: {
572 8addacdd Michael Roth
            int64List *ptr;
573 8addacdd Michael Roth
            if (cur_head) {
574 8addacdd Michael Roth
                ptr = cur_head;
575 8addacdd Michael Roth
                cur_head = ptr->next;
576 8addacdd Michael Roth
            } else {
577 8addacdd Michael Roth
                cur_head = ptr = pl_copy.value.s64_integers;
578 8addacdd Michael Roth
            }
579 8addacdd Michael Roth
            g_assert_cmpint(pt->value.s64, ==, ptr->value);
580 8addacdd Michael Roth
            break;
581 8addacdd Michael Roth
        }
582 8addacdd Michael Roth
        case PTYPE_U8: {
583 8addacdd Michael Roth
            uint8List *ptr;
584 8addacdd Michael Roth
            if (cur_head) {
585 8addacdd Michael Roth
                ptr = cur_head;
586 8addacdd Michael Roth
                cur_head = ptr->next;
587 8addacdd Michael Roth
            } else {
588 8addacdd Michael Roth
                cur_head = ptr = pl_copy.value.u8_integers;
589 8addacdd Michael Roth
            }
590 8addacdd Michael Roth
            g_assert_cmpint(pt->value.u8, ==, ptr->value);
591 8addacdd Michael Roth
            break;
592 8addacdd Michael Roth
        }
593 8addacdd Michael Roth
        case PTYPE_U16: {
594 8addacdd Michael Roth
            uint16List *ptr;
595 8addacdd Michael Roth
            if (cur_head) {
596 8addacdd Michael Roth
                ptr = cur_head;
597 8addacdd Michael Roth
                cur_head = ptr->next;
598 8addacdd Michael Roth
            } else {
599 8addacdd Michael Roth
                cur_head = ptr = pl_copy.value.u16_integers;
600 8addacdd Michael Roth
            }
601 8addacdd Michael Roth
            g_assert_cmpint(pt->value.u16, ==, ptr->value);
602 8addacdd Michael Roth
            break;
603 8addacdd Michael Roth
        }
604 8addacdd Michael Roth
        case PTYPE_U32: {
605 8addacdd Michael Roth
            uint32List *ptr;
606 8addacdd Michael Roth
            if (cur_head) {
607 8addacdd Michael Roth
                ptr = cur_head;
608 8addacdd Michael Roth
                cur_head = ptr->next;
609 8addacdd Michael Roth
            } else {
610 8addacdd Michael Roth
                cur_head = ptr = pl_copy.value.u32_integers;
611 8addacdd Michael Roth
            }
612 8addacdd Michael Roth
            g_assert_cmpint(pt->value.u32, ==, ptr->value);
613 8addacdd Michael Roth
            break;
614 8addacdd Michael Roth
        }
615 8addacdd Michael Roth
        case PTYPE_U64: {
616 8addacdd Michael Roth
            uint64List *ptr;
617 8addacdd Michael Roth
            if (cur_head) {
618 8addacdd Michael Roth
                ptr = cur_head;
619 8addacdd Michael Roth
                cur_head = ptr->next;
620 8addacdd Michael Roth
            } else {
621 8addacdd Michael Roth
                cur_head = ptr = pl_copy.value.u64_integers;
622 8addacdd Michael Roth
            }
623 8addacdd Michael Roth
            g_assert_cmpint(pt->value.u64, ==, ptr->value);
624 8addacdd Michael Roth
            break;
625 8addacdd Michael Roth
        }
626 8addacdd Michael Roth
        case PTYPE_NUMBER: {
627 8addacdd Michael Roth
            numberList *ptr;
628 8addacdd Michael Roth
            GString *double_expected = g_string_new("");
629 8addacdd Michael Roth
            GString *double_actual = g_string_new("");
630 8addacdd Michael Roth
            if (cur_head) {
631 8addacdd Michael Roth
                ptr = cur_head;
632 8addacdd Michael Roth
                cur_head = ptr->next;
633 8addacdd Michael Roth
            } else {
634 8addacdd Michael Roth
                cur_head = ptr = pl_copy.value.numbers;
635 8addacdd Michael Roth
            }
636 8addacdd Michael Roth
            /* we serialize with %f for our reference visitors, so rather than
637 8addacdd Michael Roth
             * fuzzy floating math to test "equality", just compare the
638 8addacdd Michael Roth
             * formatted values
639 8addacdd Michael Roth
             */
640 8addacdd Michael Roth
            g_string_printf(double_expected, "%.6f", pt->value.number);
641 8addacdd Michael Roth
            g_string_printf(double_actual, "%.6f", ptr->value);
642 8addacdd Michael Roth
            g_assert_cmpstr(double_actual->str, ==, double_expected->str);
643 8addacdd Michael Roth
            g_string_free(double_expected, true);
644 8addacdd Michael Roth
            g_string_free(double_actual, true);
645 8addacdd Michael Roth
            break;
646 8addacdd Michael Roth
        }
647 8addacdd Michael Roth
        case PTYPE_BOOLEAN: {
648 8addacdd Michael Roth
            boolList *ptr;
649 8addacdd Michael Roth
            if (cur_head) {
650 8addacdd Michael Roth
                ptr = cur_head;
651 8addacdd Michael Roth
                cur_head = ptr->next;
652 8addacdd Michael Roth
            } else {
653 8addacdd Michael Roth
                cur_head = ptr = pl_copy.value.booleans;
654 8addacdd Michael Roth
            }
655 8addacdd Michael Roth
            g_assert_cmpint(!!pt->value.boolean, ==, !!ptr->value);
656 8addacdd Michael Roth
            break;
657 8addacdd Michael Roth
        }
658 8addacdd Michael Roth
        default:
659 dfc6f865 Stefan Weil
            g_assert_not_reached();
660 8addacdd Michael Roth
        }
661 8addacdd Michael Roth
        i++;
662 8addacdd Michael Roth
    } while (cur_head);
663 8addacdd Michael Roth
664 8addacdd Michael Roth
    g_assert_cmpint(i, ==, 33);
665 8addacdd Michael Roth
666 8addacdd Michael Roth
    ops->cleanup(serialize_data);
667 8addacdd Michael Roth
    dealloc_helper(&pl, visit_primitive_list, &err);
668 8addacdd Michael Roth
    g_assert(!err);
669 8addacdd Michael Roth
    dealloc_helper(&pl_copy, visit_primitive_list, &err);
670 8addacdd Michael Roth
    g_assert(!err);
671 8addacdd Michael Roth
    g_free(args);
672 8addacdd Michael Roth
}
673 8addacdd Michael Roth
674 2d496105 Michael Roth
static void test_struct(gconstpointer opaque)
675 2d496105 Michael Roth
{
676 2d496105 Michael Roth
    TestArgs *args = (TestArgs *) opaque;
677 2d496105 Michael Roth
    const SerializeOps *ops = args->ops;
678 2d496105 Michael Roth
    TestStruct *ts = struct_create();
679 2d496105 Michael Roth
    TestStruct *ts_copy = NULL;
680 2d496105 Michael Roth
    Error *err = NULL;
681 2d496105 Michael Roth
    void *serialize_data;
682 2d496105 Michael Roth
683 2d496105 Michael Roth
    ops->serialize(ts, &serialize_data, visit_struct, &err);
684 2d496105 Michael Roth
    ops->deserialize((void **)&ts_copy, serialize_data, visit_struct, &err); 
685 2d496105 Michael Roth
686 2d496105 Michael Roth
    g_assert(err == NULL);
687 2d496105 Michael Roth
    struct_compare(ts, ts_copy);
688 2d496105 Michael Roth
689 2d496105 Michael Roth
    struct_cleanup(ts);
690 2d496105 Michael Roth
    struct_cleanup(ts_copy);
691 2d496105 Michael Roth
692 2d496105 Michael Roth
    ops->cleanup(serialize_data);
693 2d496105 Michael Roth
    g_free(args);
694 2d496105 Michael Roth
}
695 2d496105 Michael Roth
696 2d496105 Michael Roth
static void test_nested_struct(gconstpointer opaque)
697 2d496105 Michael Roth
{
698 2d496105 Michael Roth
    TestArgs *args = (TestArgs *) opaque;
699 2d496105 Michael Roth
    const SerializeOps *ops = args->ops;
700 2d496105 Michael Roth
    UserDefNested *udnp = nested_struct_create();
701 2d496105 Michael Roth
    UserDefNested *udnp_copy = NULL;
702 2d496105 Michael Roth
    Error *err = NULL;
703 2d496105 Michael Roth
    void *serialize_data;
704 2d496105 Michael Roth
    
705 2d496105 Michael Roth
    ops->serialize(udnp, &serialize_data, visit_nested_struct, &err);
706 2d496105 Michael Roth
    ops->deserialize((void **)&udnp_copy, serialize_data, visit_nested_struct, &err); 
707 2d496105 Michael Roth
708 2d496105 Michael Roth
    g_assert(err == NULL);
709 2d496105 Michael Roth
    nested_struct_compare(udnp, udnp_copy);
710 2d496105 Michael Roth
711 2d496105 Michael Roth
    nested_struct_cleanup(udnp);
712 2d496105 Michael Roth
    nested_struct_cleanup(udnp_copy);
713 2d496105 Michael Roth
714 2d496105 Michael Roth
    ops->cleanup(serialize_data);
715 2d496105 Michael Roth
    g_free(args);
716 2d496105 Michael Roth
}
717 2d496105 Michael Roth
718 2d496105 Michael Roth
static void test_nested_struct_list(gconstpointer opaque)
719 2d496105 Michael Roth
{
720 2d496105 Michael Roth
    TestArgs *args = (TestArgs *) opaque;
721 2d496105 Michael Roth
    const SerializeOps *ops = args->ops;
722 2d496105 Michael Roth
    UserDefNestedList *listp = NULL, *tmp, *tmp_copy, *listp_copy = NULL;
723 2d496105 Michael Roth
    Error *err = NULL;
724 2d496105 Michael Roth
    void *serialize_data;
725 2d496105 Michael Roth
    int i = 0;
726 2d496105 Michael Roth
727 2d496105 Michael Roth
    for (i = 0; i < 8; i++) {
728 2d496105 Michael Roth
        tmp = g_malloc0(sizeof(UserDefNestedList));
729 2d496105 Michael Roth
        tmp->value = nested_struct_create();
730 2d496105 Michael Roth
        tmp->next = listp;
731 2d496105 Michael Roth
        listp = tmp;
732 2d496105 Michael Roth
    }
733 2d496105 Michael Roth
    
734 2d496105 Michael Roth
    ops->serialize(listp, &serialize_data, visit_nested_struct_list, &err);
735 2d496105 Michael Roth
    ops->deserialize((void **)&listp_copy, serialize_data,
736 2d496105 Michael Roth
                     visit_nested_struct_list, &err); 
737 2d496105 Michael Roth
738 2d496105 Michael Roth
    g_assert(err == NULL);
739 2d496105 Michael Roth
740 2d496105 Michael Roth
    tmp = listp;
741 2d496105 Michael Roth
    tmp_copy = listp_copy;
742 2d496105 Michael Roth
    while (listp_copy) {
743 2d496105 Michael Roth
        g_assert(listp);
744 2d496105 Michael Roth
        nested_struct_compare(listp->value, listp_copy->value);
745 2d496105 Michael Roth
        listp = listp->next;
746 2d496105 Michael Roth
        listp_copy = listp_copy->next;
747 2d496105 Michael Roth
    }
748 2d496105 Michael Roth
749 2d496105 Michael Roth
    qapi_free_UserDefNestedList(tmp);
750 2d496105 Michael Roth
    qapi_free_UserDefNestedList(tmp_copy);
751 2d496105 Michael Roth
752 2d496105 Michael Roth
    ops->cleanup(serialize_data);
753 2d496105 Michael Roth
    g_free(args);
754 2d496105 Michael Roth
}
755 2d496105 Michael Roth
756 2d496105 Michael Roth
PrimitiveType pt_values[] = {
757 2d496105 Michael Roth
    /* string tests */
758 2d496105 Michael Roth
    {
759 2d496105 Michael Roth
        .description = "string_empty",
760 2d496105 Michael Roth
        .type = PTYPE_STRING,
761 2d496105 Michael Roth
        .value.string = "",
762 2d496105 Michael Roth
    },
763 2d496105 Michael Roth
    {
764 2d496105 Michael Roth
        .description = "string_whitespace",
765 2d496105 Michael Roth
        .type = PTYPE_STRING,
766 2d496105 Michael Roth
        .value.string = "a b  c\td",
767 2d496105 Michael Roth
    },
768 2d496105 Michael Roth
    {
769 2d496105 Michael Roth
        .description = "string_newlines",
770 2d496105 Michael Roth
        .type = PTYPE_STRING,
771 2d496105 Michael Roth
        .value.string = "a\nb\n",
772 2d496105 Michael Roth
    },
773 2d496105 Michael Roth
    {
774 2d496105 Michael Roth
        .description = "string_commas",
775 2d496105 Michael Roth
        .type = PTYPE_STRING,
776 2d496105 Michael Roth
        .value.string = "a,b, c,d",
777 2d496105 Michael Roth
    },
778 2d496105 Michael Roth
    {
779 2d496105 Michael Roth
        .description = "string_single_quoted",
780 2d496105 Michael Roth
        .type = PTYPE_STRING,
781 2d496105 Michael Roth
        .value.string = "'a b',cd",
782 2d496105 Michael Roth
    },
783 2d496105 Michael Roth
    {
784 2d496105 Michael Roth
        .description = "string_double_quoted",
785 2d496105 Michael Roth
        .type = PTYPE_STRING,
786 2d496105 Michael Roth
        .value.string = "\"a b\",cd",
787 2d496105 Michael Roth
    },
788 2d496105 Michael Roth
    /* boolean tests */
789 2d496105 Michael Roth
    {
790 2d496105 Michael Roth
        .description = "boolean_true1",
791 2d496105 Michael Roth
        .type = PTYPE_BOOLEAN,
792 2d496105 Michael Roth
        .value.boolean = true,
793 2d496105 Michael Roth
    },
794 2d496105 Michael Roth
    {
795 2d496105 Michael Roth
        .description = "boolean_true2",
796 2d496105 Michael Roth
        .type = PTYPE_BOOLEAN,
797 2d496105 Michael Roth
        .value.boolean = 8,
798 2d496105 Michael Roth
    },
799 2d496105 Michael Roth
    {
800 2d496105 Michael Roth
        .description = "boolean_true3",
801 2d496105 Michael Roth
        .type = PTYPE_BOOLEAN,
802 2d496105 Michael Roth
        .value.boolean = -1,
803 2d496105 Michael Roth
    },
804 2d496105 Michael Roth
    {
805 2d496105 Michael Roth
        .description = "boolean_false1",
806 2d496105 Michael Roth
        .type = PTYPE_BOOLEAN,
807 2d496105 Michael Roth
        .value.boolean = false,
808 2d496105 Michael Roth
    },
809 2d496105 Michael Roth
    {
810 2d496105 Michael Roth
        .description = "boolean_false2",
811 2d496105 Michael Roth
        .type = PTYPE_BOOLEAN,
812 2d496105 Michael Roth
        .value.boolean = 0,
813 2d496105 Michael Roth
    },
814 2d496105 Michael Roth
    /* number tests (double) */
815 2d496105 Michael Roth
    /* note: we format these to %.6f before comparing, since that's how
816 2d496105 Michael Roth
     * we serialize them and it doesn't make sense to check precision
817 2d496105 Michael Roth
     * beyond that.
818 2d496105 Michael Roth
     */
819 2d496105 Michael Roth
    {
820 2d496105 Michael Roth
        .description = "number_sanity1",
821 2d496105 Michael Roth
        .type = PTYPE_NUMBER,
822 2d496105 Michael Roth
        .value.number = -1,
823 2d496105 Michael Roth
    },
824 2d496105 Michael Roth
    {
825 2d496105 Michael Roth
        .description = "number_sanity2",
826 2d496105 Michael Roth
        .type = PTYPE_NUMBER,
827 2d496105 Michael Roth
        .value.number = 3.14159265,
828 2d496105 Michael Roth
    },
829 2d496105 Michael Roth
    {
830 2d496105 Michael Roth
        .description = "number_min",
831 2d496105 Michael Roth
        .type = PTYPE_NUMBER,
832 2d496105 Michael Roth
        .value.number = DBL_MIN,
833 2d496105 Michael Roth
    },
834 2d496105 Michael Roth
    {
835 2d496105 Michael Roth
        .description = "number_max",
836 2d496105 Michael Roth
        .type = PTYPE_NUMBER,
837 2d496105 Michael Roth
        .value.number = DBL_MAX,
838 2d496105 Michael Roth
    },
839 2d496105 Michael Roth
    /* integer tests (int64) */
840 2d496105 Michael Roth
    {
841 2d496105 Michael Roth
        .description = "integer_sanity1",
842 2d496105 Michael Roth
        .type = PTYPE_INTEGER,
843 2d496105 Michael Roth
        .value.integer = -1,
844 2d496105 Michael Roth
    },
845 2d496105 Michael Roth
    {
846 2d496105 Michael Roth
        .description = "integer_sanity2",
847 2d496105 Michael Roth
        .type = PTYPE_INTEGER,
848 2d496105 Michael Roth
        .value.integer = INT64_MAX / 2 + 1,
849 2d496105 Michael Roth
    },
850 2d496105 Michael Roth
    {
851 2d496105 Michael Roth
        .description = "integer_min",
852 2d496105 Michael Roth
        .type = PTYPE_INTEGER,
853 2d496105 Michael Roth
        .value.integer = INT64_MIN,
854 2d496105 Michael Roth
    },
855 2d496105 Michael Roth
    {
856 2d496105 Michael Roth
        .description = "integer_max",
857 2d496105 Michael Roth
        .type = PTYPE_INTEGER,
858 2d496105 Michael Roth
        .value.integer = INT64_MAX,
859 2d496105 Michael Roth
    },
860 2d496105 Michael Roth
    /* uint8 tests */
861 2d496105 Michael Roth
    {
862 2d496105 Michael Roth
        .description = "uint8_sanity1",
863 2d496105 Michael Roth
        .type = PTYPE_U8,
864 2d496105 Michael Roth
        .value.u8 = 1,
865 2d496105 Michael Roth
    },
866 2d496105 Michael Roth
    {
867 2d496105 Michael Roth
        .description = "uint8_sanity2",
868 2d496105 Michael Roth
        .type = PTYPE_U8,
869 2d496105 Michael Roth
        .value.u8 = UINT8_MAX / 2 + 1,
870 2d496105 Michael Roth
    },
871 2d496105 Michael Roth
    {
872 2d496105 Michael Roth
        .description = "uint8_min",
873 2d496105 Michael Roth
        .type = PTYPE_U8,
874 2d496105 Michael Roth
        .value.u8 = 0,
875 2d496105 Michael Roth
    },
876 2d496105 Michael Roth
    {
877 2d496105 Michael Roth
        .description = "uint8_max",
878 2d496105 Michael Roth
        .type = PTYPE_U8,
879 2d496105 Michael Roth
        .value.u8 = UINT8_MAX,
880 2d496105 Michael Roth
    },
881 2d496105 Michael Roth
    /* uint16 tests */
882 2d496105 Michael Roth
    {
883 2d496105 Michael Roth
        .description = "uint16_sanity1",
884 2d496105 Michael Roth
        .type = PTYPE_U16,
885 2d496105 Michael Roth
        .value.u16 = 1,
886 2d496105 Michael Roth
    },
887 2d496105 Michael Roth
    {
888 2d496105 Michael Roth
        .description = "uint16_sanity2",
889 2d496105 Michael Roth
        .type = PTYPE_U16,
890 2d496105 Michael Roth
        .value.u16 = UINT16_MAX / 2 + 1,
891 2d496105 Michael Roth
    },
892 2d496105 Michael Roth
    {
893 2d496105 Michael Roth
        .description = "uint16_min",
894 2d496105 Michael Roth
        .type = PTYPE_U16,
895 2d496105 Michael Roth
        .value.u16 = 0,
896 2d496105 Michael Roth
    },
897 2d496105 Michael Roth
    {
898 2d496105 Michael Roth
        .description = "uint16_max",
899 2d496105 Michael Roth
        .type = PTYPE_U16,
900 2d496105 Michael Roth
        .value.u16 = UINT16_MAX,
901 2d496105 Michael Roth
    },
902 2d496105 Michael Roth
    /* uint32 tests */
903 2d496105 Michael Roth
    {
904 2d496105 Michael Roth
        .description = "uint32_sanity1",
905 2d496105 Michael Roth
        .type = PTYPE_U32,
906 2d496105 Michael Roth
        .value.u32 = 1,
907 2d496105 Michael Roth
    },
908 2d496105 Michael Roth
    {
909 2d496105 Michael Roth
        .description = "uint32_sanity2",
910 2d496105 Michael Roth
        .type = PTYPE_U32,
911 2d496105 Michael Roth
        .value.u32 = UINT32_MAX / 2 + 1,
912 2d496105 Michael Roth
    },
913 2d496105 Michael Roth
    {
914 2d496105 Michael Roth
        .description = "uint32_min",
915 2d496105 Michael Roth
        .type = PTYPE_U32,
916 2d496105 Michael Roth
        .value.u32 = 0,
917 2d496105 Michael Roth
    },
918 2d496105 Michael Roth
    {
919 2d496105 Michael Roth
        .description = "uint32_max",
920 2d496105 Michael Roth
        .type = PTYPE_U32,
921 2d496105 Michael Roth
        .value.u32 = UINT32_MAX,
922 2d496105 Michael Roth
    },
923 2d496105 Michael Roth
    /* uint64 tests */
924 2d496105 Michael Roth
    {
925 2d496105 Michael Roth
        .description = "uint64_sanity1",
926 2d496105 Michael Roth
        .type = PTYPE_U64,
927 2d496105 Michael Roth
        .value.u64 = 1,
928 2d496105 Michael Roth
    },
929 2d496105 Michael Roth
    {
930 2d496105 Michael Roth
        .description = "uint64_sanity2",
931 2d496105 Michael Roth
        .type = PTYPE_U64,
932 2d496105 Michael Roth
        .value.u64 = UINT64_MAX / 2 + 1,
933 2d496105 Michael Roth
    },
934 2d496105 Michael Roth
    {
935 2d496105 Michael Roth
        .description = "uint64_min",
936 2d496105 Michael Roth
        .type = PTYPE_U64,
937 2d496105 Michael Roth
        .value.u64 = 0,
938 2d496105 Michael Roth
    },
939 2d496105 Michael Roth
    {
940 2d496105 Michael Roth
        .description = "uint64_max",
941 2d496105 Michael Roth
        .type = PTYPE_U64,
942 2d496105 Michael Roth
        .value.u64 = UINT64_MAX,
943 2d496105 Michael Roth
    },
944 2d496105 Michael Roth
    /* int8 tests */
945 2d496105 Michael Roth
    {
946 2d496105 Michael Roth
        .description = "int8_sanity1",
947 2d496105 Michael Roth
        .type = PTYPE_S8,
948 2d496105 Michael Roth
        .value.s8 = -1,
949 2d496105 Michael Roth
    },
950 2d496105 Michael Roth
    {
951 2d496105 Michael Roth
        .description = "int8_sanity2",
952 2d496105 Michael Roth
        .type = PTYPE_S8,
953 2d496105 Michael Roth
        .value.s8 = INT8_MAX / 2 + 1,
954 2d496105 Michael Roth
    },
955 2d496105 Michael Roth
    {
956 2d496105 Michael Roth
        .description = "int8_min",
957 2d496105 Michael Roth
        .type = PTYPE_S8,
958 2d496105 Michael Roth
        .value.s8 = INT8_MIN,
959 2d496105 Michael Roth
    },
960 2d496105 Michael Roth
    {
961 2d496105 Michael Roth
        .description = "int8_max",
962 2d496105 Michael Roth
        .type = PTYPE_S8,
963 2d496105 Michael Roth
        .value.s8 = INT8_MAX,
964 2d496105 Michael Roth
    },
965 2d496105 Michael Roth
    /* int16 tests */
966 2d496105 Michael Roth
    {
967 2d496105 Michael Roth
        .description = "int16_sanity1",
968 2d496105 Michael Roth
        .type = PTYPE_S16,
969 2d496105 Michael Roth
        .value.s16 = -1,
970 2d496105 Michael Roth
    },
971 2d496105 Michael Roth
    {
972 2d496105 Michael Roth
        .description = "int16_sanity2",
973 2d496105 Michael Roth
        .type = PTYPE_S16,
974 2d496105 Michael Roth
        .value.s16 = INT16_MAX / 2 + 1,
975 2d496105 Michael Roth
    },
976 2d496105 Michael Roth
    {
977 2d496105 Michael Roth
        .description = "int16_min",
978 2d496105 Michael Roth
        .type = PTYPE_S16,
979 2d496105 Michael Roth
        .value.s16 = INT16_MIN,
980 2d496105 Michael Roth
    },
981 2d496105 Michael Roth
    {
982 2d496105 Michael Roth
        .description = "int16_max",
983 2d496105 Michael Roth
        .type = PTYPE_S16,
984 2d496105 Michael Roth
        .value.s16 = INT16_MAX,
985 2d496105 Michael Roth
    },
986 2d496105 Michael Roth
    /* int32 tests */
987 2d496105 Michael Roth
    {
988 2d496105 Michael Roth
        .description = "int32_sanity1",
989 2d496105 Michael Roth
        .type = PTYPE_S32,
990 2d496105 Michael Roth
        .value.s32 = -1,
991 2d496105 Michael Roth
    },
992 2d496105 Michael Roth
    {
993 2d496105 Michael Roth
        .description = "int32_sanity2",
994 2d496105 Michael Roth
        .type = PTYPE_S32,
995 2d496105 Michael Roth
        .value.s32 = INT32_MAX / 2 + 1,
996 2d496105 Michael Roth
    },
997 2d496105 Michael Roth
    {
998 2d496105 Michael Roth
        .description = "int32_min",
999 2d496105 Michael Roth
        .type = PTYPE_S32,
1000 2d496105 Michael Roth
        .value.s32 = INT32_MIN,
1001 2d496105 Michael Roth
    },
1002 2d496105 Michael Roth
    {
1003 2d496105 Michael Roth
        .description = "int32_max",
1004 2d496105 Michael Roth
        .type = PTYPE_S32,
1005 2d496105 Michael Roth
        .value.s32 = INT32_MAX,
1006 2d496105 Michael Roth
    },
1007 2d496105 Michael Roth
    /* int64 tests */
1008 2d496105 Michael Roth
    {
1009 2d496105 Michael Roth
        .description = "int64_sanity1",
1010 2d496105 Michael Roth
        .type = PTYPE_S64,
1011 2d496105 Michael Roth
        .value.s64 = -1,
1012 2d496105 Michael Roth
    },
1013 2d496105 Michael Roth
    {
1014 2d496105 Michael Roth
        .description = "int64_sanity2",
1015 2d496105 Michael Roth
        .type = PTYPE_S64,
1016 2d496105 Michael Roth
        .value.s64 = INT64_MAX / 2 + 1,
1017 2d496105 Michael Roth
    },
1018 2d496105 Michael Roth
    {
1019 2d496105 Michael Roth
        .description = "int64_min",
1020 2d496105 Michael Roth
        .type = PTYPE_S64,
1021 2d496105 Michael Roth
        .value.s64 = INT64_MIN,
1022 2d496105 Michael Roth
    },
1023 2d496105 Michael Roth
    {
1024 2d496105 Michael Roth
        .description = "int64_max",
1025 2d496105 Michael Roth
        .type = PTYPE_S64,
1026 2d496105 Michael Roth
        .value.s64 = INT64_MAX,
1027 2d496105 Michael Roth
    },
1028 2d496105 Michael Roth
    { .type = PTYPE_EOL }
1029 2d496105 Michael Roth
};
1030 2d496105 Michael Roth
1031 2d496105 Michael Roth
/* visitor-specific op implementations */
1032 2d496105 Michael Roth
1033 2d496105 Michael Roth
typedef struct QmpSerializeData {
1034 2d496105 Michael Roth
    QmpOutputVisitor *qov;
1035 2d496105 Michael Roth
    QmpInputVisitor *qiv;
1036 2d496105 Michael Roth
} QmpSerializeData;
1037 2d496105 Michael Roth
1038 2d496105 Michael Roth
static void qmp_serialize(void *native_in, void **datap,
1039 2d496105 Michael Roth
                          VisitorFunc visit, Error **errp)
1040 2d496105 Michael Roth
{
1041 2d496105 Michael Roth
    QmpSerializeData *d = g_malloc0(sizeof(*d));
1042 2d496105 Michael Roth
1043 2d496105 Michael Roth
    d->qov = qmp_output_visitor_new();
1044 2d496105 Michael Roth
    visit(qmp_output_get_visitor(d->qov), &native_in, errp);
1045 2d496105 Michael Roth
    *datap = d;
1046 2d496105 Michael Roth
}
1047 2d496105 Michael Roth
1048 2d496105 Michael Roth
static void qmp_deserialize(void **native_out, void *datap,
1049 2d496105 Michael Roth
                            VisitorFunc visit, Error **errp)
1050 2d496105 Michael Roth
{
1051 2d496105 Michael Roth
    QmpSerializeData *d = datap;
1052 ad7f375d Michael Roth
    QString *output_json;
1053 ad7f375d Michael Roth
    QObject *obj_orig, *obj;
1054 ad7f375d Michael Roth
1055 ad7f375d Michael Roth
    obj_orig = qmp_output_get_qobject(d->qov);
1056 ad7f375d Michael Roth
    output_json = qobject_to_json(obj_orig);
1057 ad7f375d Michael Roth
    obj = qobject_from_json(qstring_get_str(output_json));
1058 2d496105 Michael Roth
1059 2d496105 Michael Roth
    QDECREF(output_json);
1060 2d496105 Michael Roth
    d->qiv = qmp_input_visitor_new(obj);
1061 ad7f375d Michael Roth
    qobject_decref(obj_orig);
1062 2bd01ac1 Stefan Berger
    qobject_decref(obj);
1063 2d496105 Michael Roth
    visit(qmp_input_get_visitor(d->qiv), native_out, errp);
1064 2d496105 Michael Roth
}
1065 2d496105 Michael Roth
1066 2d496105 Michael Roth
static void qmp_cleanup(void *datap)
1067 2d496105 Michael Roth
{
1068 2d496105 Michael Roth
    QmpSerializeData *d = datap;
1069 2d496105 Michael Roth
    qmp_output_visitor_cleanup(d->qov);
1070 2d496105 Michael Roth
    qmp_input_visitor_cleanup(d->qiv);
1071 2bd01ac1 Stefan Berger
1072 2bd01ac1 Stefan Berger
    g_free(d);
1073 2d496105 Michael Roth
}
1074 2d496105 Michael Roth
1075 0d30b0a2 Michael Roth
typedef struct StringSerializeData {
1076 2bd01ac1 Stefan Berger
    char *string;
1077 0d30b0a2 Michael Roth
    StringOutputVisitor *sov;
1078 0d30b0a2 Michael Roth
    StringInputVisitor *siv;
1079 0d30b0a2 Michael Roth
} StringSerializeData;
1080 0d30b0a2 Michael Roth
1081 0d30b0a2 Michael Roth
static void string_serialize(void *native_in, void **datap,
1082 0d30b0a2 Michael Roth
                             VisitorFunc visit, Error **errp)
1083 0d30b0a2 Michael Roth
{
1084 0d30b0a2 Michael Roth
    StringSerializeData *d = g_malloc0(sizeof(*d));
1085 0d30b0a2 Michael Roth
1086 0b7593e0 Paolo Bonzini
    d->sov = string_output_visitor_new(false);
1087 0d30b0a2 Michael Roth
    visit(string_output_get_visitor(d->sov), &native_in, errp);
1088 0d30b0a2 Michael Roth
    *datap = d;
1089 0d30b0a2 Michael Roth
}
1090 0d30b0a2 Michael Roth
1091 0d30b0a2 Michael Roth
static void string_deserialize(void **native_out, void *datap,
1092 0d30b0a2 Michael Roth
                               VisitorFunc visit, Error **errp)
1093 0d30b0a2 Michael Roth
{
1094 0d30b0a2 Michael Roth
    StringSerializeData *d = datap;
1095 0d30b0a2 Michael Roth
1096 2bd01ac1 Stefan Berger
    d->string = string_output_get_string(d->sov);
1097 2bd01ac1 Stefan Berger
    d->siv = string_input_visitor_new(d->string);
1098 0d30b0a2 Michael Roth
    visit(string_input_get_visitor(d->siv), native_out, errp);
1099 0d30b0a2 Michael Roth
}
1100 0d30b0a2 Michael Roth
1101 0d30b0a2 Michael Roth
static void string_cleanup(void *datap)
1102 0d30b0a2 Michael Roth
{
1103 0d30b0a2 Michael Roth
    StringSerializeData *d = datap;
1104 2bd01ac1 Stefan Berger
1105 0d30b0a2 Michael Roth
    string_output_visitor_cleanup(d->sov);
1106 0d30b0a2 Michael Roth
    string_input_visitor_cleanup(d->siv);
1107 2bd01ac1 Stefan Berger
    g_free(d->string);
1108 2bd01ac1 Stefan Berger
    g_free(d);
1109 0d30b0a2 Michael Roth
}
1110 0d30b0a2 Michael Roth
1111 2d496105 Michael Roth
/* visitor registration, test harness */
1112 2d496105 Michael Roth
1113 2d496105 Michael Roth
/* note: to function interchangeably as a serialization mechanism your
1114 2d496105 Michael Roth
 * visitor test implementation should pass the test cases for all visitor
1115 2d496105 Michael Roth
 * capabilities: primitives, structures, and lists
1116 2d496105 Michael Roth
 */
1117 2d496105 Michael Roth
static const SerializeOps visitors[] = {
1118 2d496105 Michael Roth
    {
1119 2d496105 Michael Roth
        .type = "QMP",
1120 2d496105 Michael Roth
        .serialize = qmp_serialize,
1121 2d496105 Michael Roth
        .deserialize = qmp_deserialize,
1122 2d496105 Michael Roth
        .cleanup = qmp_cleanup,
1123 8addacdd Michael Roth
        .caps = VCAP_PRIMITIVES | VCAP_STRUCTURES | VCAP_LISTS |
1124 8addacdd Michael Roth
                VCAP_PRIMITIVE_LISTS
1125 2d496105 Michael Roth
    },
1126 0d30b0a2 Michael Roth
    {
1127 0d30b0a2 Michael Roth
        .type = "String",
1128 0d30b0a2 Michael Roth
        .serialize = string_serialize,
1129 0d30b0a2 Michael Roth
        .deserialize = string_deserialize,
1130 0d30b0a2 Michael Roth
        .cleanup = string_cleanup,
1131 0d30b0a2 Michael Roth
        .caps = VCAP_PRIMITIVES
1132 0d30b0a2 Michael Roth
    },
1133 2d496105 Michael Roth
    { NULL }
1134 2d496105 Michael Roth
};
1135 2d496105 Michael Roth
1136 2d496105 Michael Roth
static void add_visitor_type(const SerializeOps *ops)
1137 2d496105 Michael Roth
{
1138 2d496105 Michael Roth
    char testname_prefix[128];
1139 2d496105 Michael Roth
    char testname[128];
1140 2d496105 Michael Roth
    TestArgs *args;
1141 2d496105 Michael Roth
    int i = 0;
1142 2d496105 Michael Roth
1143 2d496105 Michael Roth
    sprintf(testname_prefix, "/visitor/serialization/%s", ops->type);
1144 2d496105 Michael Roth
1145 2d496105 Michael Roth
    if (ops->caps & VCAP_PRIMITIVES) {
1146 2d496105 Michael Roth
        while (pt_values[i].type != PTYPE_EOL) {
1147 2d496105 Michael Roth
            sprintf(testname, "%s/primitives/%s", testname_prefix,
1148 2d496105 Michael Roth
                    pt_values[i].description);
1149 2d496105 Michael Roth
            args = g_malloc0(sizeof(*args));
1150 2d496105 Michael Roth
            args->ops = ops;
1151 2d496105 Michael Roth
            args->test_data = &pt_values[i];
1152 2d496105 Michael Roth
            g_test_add_data_func(testname, args, test_primitives);
1153 2d496105 Michael Roth
            i++;
1154 2d496105 Michael Roth
        }
1155 2d496105 Michael Roth
    }
1156 2d496105 Michael Roth
1157 2d496105 Michael Roth
    if (ops->caps & VCAP_STRUCTURES) {
1158 2d496105 Michael Roth
        sprintf(testname, "%s/struct", testname_prefix);
1159 2d496105 Michael Roth
        args = g_malloc0(sizeof(*args));
1160 2d496105 Michael Roth
        args->ops = ops;
1161 2d496105 Michael Roth
        args->test_data = NULL;
1162 2d496105 Michael Roth
        g_test_add_data_func(testname, args, test_struct);
1163 2d496105 Michael Roth
1164 2d496105 Michael Roth
        sprintf(testname, "%s/nested_struct", testname_prefix);
1165 2d496105 Michael Roth
        args = g_malloc0(sizeof(*args));
1166 2d496105 Michael Roth
        args->ops = ops;
1167 2d496105 Michael Roth
        args->test_data = NULL;
1168 2d496105 Michael Roth
        g_test_add_data_func(testname, args, test_nested_struct);
1169 2d496105 Michael Roth
    }
1170 2d496105 Michael Roth
1171 2d496105 Michael Roth
    if (ops->caps & VCAP_LISTS) {
1172 2d496105 Michael Roth
        sprintf(testname, "%s/nested_struct_list", testname_prefix);
1173 2d496105 Michael Roth
        args = g_malloc0(sizeof(*args));
1174 2d496105 Michael Roth
        args->ops = ops;
1175 2d496105 Michael Roth
        args->test_data = NULL;
1176 2d496105 Michael Roth
        g_test_add_data_func(testname, args, test_nested_struct_list);
1177 2d496105 Michael Roth
    }
1178 8addacdd Michael Roth
1179 8addacdd Michael Roth
    if (ops->caps & VCAP_PRIMITIVE_LISTS) {
1180 8addacdd Michael Roth
        i = 0;
1181 8addacdd Michael Roth
        while (pt_values[i].type != PTYPE_EOL) {
1182 8addacdd Michael Roth
            sprintf(testname, "%s/primitive_list/%s", testname_prefix,
1183 8addacdd Michael Roth
                    pt_values[i].description);
1184 8addacdd Michael Roth
            args = g_malloc0(sizeof(*args));
1185 8addacdd Michael Roth
            args->ops = ops;
1186 8addacdd Michael Roth
            args->test_data = &pt_values[i];
1187 8addacdd Michael Roth
            g_test_add_data_func(testname, args, test_primitive_lists);
1188 8addacdd Michael Roth
            i++;
1189 8addacdd Michael Roth
        }
1190 8addacdd Michael Roth
    }
1191 2d496105 Michael Roth
}
1192 2d496105 Michael Roth
1193 2d496105 Michael Roth
int main(int argc, char **argv)
1194 2d496105 Michael Roth
{
1195 2d496105 Michael Roth
    int i = 0;
1196 2d496105 Michael Roth
1197 2d496105 Michael Roth
    g_test_init(&argc, &argv, NULL);
1198 2d496105 Michael Roth
1199 2d496105 Michael Roth
    while (visitors[i].type != NULL) {
1200 2d496105 Michael Roth
        add_visitor_type(&visitors[i]);
1201 2d496105 Michael Roth
        i++;
1202 2d496105 Michael Roth
    }
1203 2d496105 Michael Roth
1204 2d496105 Michael Roth
    g_test_run();
1205 2d496105 Michael Roth
1206 2d496105 Michael Roth
    return 0;
1207 2d496105 Michael Roth
}