Statistics
| Branch: | Revision:

root / tests / test-qmp-input-visitor.c @ e92cfa0d

History | View | Annotate | Download (9.8 kB)

1
/*
2
 * QMP Input Visitor unit-tests.
3
 *
4
 * Copyright (C) 2011 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 <glib.h>
14
#include <stdarg.h>
15

    
16
#include "qemu-common.h"
17
#include "qapi/qmp-input-visitor.h"
18
#include "test-qapi-types.h"
19
#include "test-qapi-visit.h"
20
#include "qapi/qmp/types.h"
21

    
22
typedef struct TestInputVisitorData {
23
    QObject *obj;
24
    QmpInputVisitor *qiv;
25
} TestInputVisitorData;
26

    
27
static void visitor_input_teardown(TestInputVisitorData *data,
28
                                   const void *unused)
29
{
30
    qobject_decref(data->obj);
31
    data->obj = NULL;
32

    
33
    if (data->qiv) {
34
        qmp_input_visitor_cleanup(data->qiv);
35
        data->qiv = NULL;
36
    }
37
}
38

    
39
/* This is provided instead of a test setup function so that the JSON
40
   string used by the tests are kept in the test functions (and not
41
   int main()) */
42
static GCC_FMT_ATTR(2, 3)
43
Visitor *visitor_input_test_init(TestInputVisitorData *data,
44
                                 const char *json_string, ...)
45
{
46
    Visitor *v;
47
    va_list ap;
48

    
49
    va_start(ap, json_string);
50
    data->obj = qobject_from_jsonv(json_string, &ap);
51
    va_end(ap);
52

    
53
    g_assert(data->obj != NULL);
54

    
55
    data->qiv = qmp_input_visitor_new(data->obj);
56
    g_assert(data->qiv != NULL);
57

    
58
    v = qmp_input_get_visitor(data->qiv);
59
    g_assert(v != NULL);
60

    
61
    return v;
62
}
63

    
64
static void test_visitor_in_int(TestInputVisitorData *data,
65
                                const void *unused)
66
{
67
    int64_t res = 0, value = -42;
68
    Error *errp = NULL;
69
    Visitor *v;
70

    
71
    v = visitor_input_test_init(data, "%" PRId64, value);
72

    
73
    visit_type_int(v, &res, NULL, &errp);
74
    g_assert(!error_is_set(&errp));
75
    g_assert_cmpint(res, ==, value);
76
}
77

    
78
static void test_visitor_in_int_overflow(TestInputVisitorData *data,
79
                                         const void *unused)
80
{
81
    int64_t res = 0;
82
    Error *errp = NULL;
83
    Visitor *v;
84

    
85
    /* this will overflow a Qint/int64, so should be deserialized into
86
     * a QFloat/double field instead, leading to an error if we pass it
87
     * to visit_type_int. confirm this.
88
     */
89
    v = visitor_input_test_init(data, "%f", DBL_MAX);
90

    
91
    visit_type_int(v, &res, NULL, &errp);
92
    g_assert(error_is_set(&errp));
93
    error_free(errp);
94
}
95

    
96
static void test_visitor_in_bool(TestInputVisitorData *data,
97
                                 const void *unused)
98
{
99
    Error *errp = NULL;
100
    bool res = false;
101
    Visitor *v;
102

    
103
    v = visitor_input_test_init(data, "true");
104

    
105
    visit_type_bool(v, &res, NULL, &errp);
106
    g_assert(!error_is_set(&errp));
107
    g_assert_cmpint(res, ==, true);
108
}
109

    
110
static void test_visitor_in_number(TestInputVisitorData *data,
111
                                   const void *unused)
112
{
113
    double res = 0, value = 3.14;
114
    Error *errp = NULL;
115
    Visitor *v;
116

    
117
    v = visitor_input_test_init(data, "%f", value);
118

    
119
    visit_type_number(v, &res, NULL, &errp);
120
    g_assert(!error_is_set(&errp));
121
    g_assert_cmpfloat(res, ==, value);
122
}
123

    
124
static void test_visitor_in_string(TestInputVisitorData *data,
125
                                   const void *unused)
126
{
127
    char *res = NULL, *value = (char *) "Q E M U";
128
    Error *errp = NULL;
129
    Visitor *v;
130

    
131
    v = visitor_input_test_init(data, "%s", value);
132

    
133
    visit_type_str(v, &res, NULL, &errp);
134
    g_assert(!error_is_set(&errp));
135
    g_assert_cmpstr(res, ==, value);
136

    
137
    g_free(res);
138
}
139

    
140
static void test_visitor_in_enum(TestInputVisitorData *data,
141
                                 const void *unused)
142
{
143
    Error *errp = NULL;
144
    Visitor *v;
145
    EnumOne i;
146

    
147
    for (i = 0; EnumOne_lookup[i]; i++) {
148
        EnumOne res = -1;
149

    
150
        v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]);
151

    
152
        visit_type_EnumOne(v, &res, NULL, &errp);
153
        g_assert(!error_is_set(&errp));
154
        g_assert_cmpint(i, ==, res);
155

    
156
        visitor_input_teardown(data, NULL);
157
    }
158

    
159
    data->obj = NULL;
160
    data->qiv = NULL;
161
}
162

    
163
typedef struct TestStruct
164
{
165
    int64_t integer;
166
    bool boolean;
167
    char *string;
168
} TestStruct;
169

    
170
static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
171
                                  const char *name, Error **errp)
172
{
173
    Error *err = NULL;
174
    if (!error_is_set(errp)) {
175
        visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
176
                           &err);
177
        if (!err) {
178
            visit_type_int(v, &(*obj)->integer, "integer", &err);
179
            visit_type_bool(v, &(*obj)->boolean, "boolean", &err);
180
            visit_type_str(v, &(*obj)->string, "string", &err);
181

    
182
            /* Always call end_struct if start_struct succeeded.  */
183
            error_propagate(errp, err);
184
            err = NULL;
185
            visit_end_struct(v, &err);
186
        }
187
        error_propagate(errp, err);
188
    }
189
}
190

    
191
static void test_visitor_in_struct(TestInputVisitorData *data,
192
                                   const void *unused)
193
{
194
    TestStruct *p = NULL;
195
    Error *errp = NULL;
196
    Visitor *v;
197

    
198
    v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
199

    
200
    visit_type_TestStruct(v, &p, NULL, &errp);
201
    g_assert(!error_is_set(&errp));
202
    g_assert_cmpint(p->integer, ==, -42);
203
    g_assert(p->boolean == true);
204
    g_assert_cmpstr(p->string, ==, "foo");
205

    
206
    g_free(p->string);
207
    g_free(p);
208
}
209

    
210
static void check_and_free_str(char *str, const char *cmp)
211
{
212
    g_assert_cmpstr(str, ==, cmp);
213
    g_free(str);
214
}
215

    
216
static void test_visitor_in_struct_nested(TestInputVisitorData *data,
217
                                          const void *unused)
218
{
219
    UserDefNested *udp = NULL;
220
    Error *errp = NULL;
221
    Visitor *v;
222

    
223
    v = visitor_input_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string' }, 'string2': 'string2'}}}");
224

    
225
    visit_type_UserDefNested(v, &udp, NULL, &errp);
226
    g_assert(!error_is_set(&errp));
227

    
228
    check_and_free_str(udp->string0, "string0");
229
    check_and_free_str(udp->dict1.string1, "string1");
230
    g_assert_cmpint(udp->dict1.dict2.userdef1->integer, ==, 42);
231
    check_and_free_str(udp->dict1.dict2.userdef1->string, "string");
232
    check_and_free_str(udp->dict1.dict2.string2, "string2");
233
    g_assert(udp->dict1.has_dict3 == false);
234

    
235
    g_free(udp->dict1.dict2.userdef1);
236
    g_free(udp);
237
}
238

    
239
static void test_visitor_in_list(TestInputVisitorData *data,
240
                                 const void *unused)
241
{
242
    UserDefOneList *item, *head = NULL;
243
    Error *errp = NULL;
244
    Visitor *v;
245
    int i;
246

    
247
    v = visitor_input_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
248

    
249
    visit_type_UserDefOneList(v, &head, NULL, &errp);
250
    g_assert(!error_is_set(&errp));
251
    g_assert(head != NULL);
252

    
253
    for (i = 0, item = head; item; item = item->next, i++) {
254
        char string[12];
255

    
256
        snprintf(string, sizeof(string), "string%d", i);
257
        g_assert_cmpstr(item->value->string, ==, string);
258
        g_assert_cmpint(item->value->integer, ==, 42 + i);
259
    }
260

    
261
    qapi_free_UserDefOneList(head);
262
}
263

    
264
static void test_visitor_in_union(TestInputVisitorData *data,
265
                                  const void *unused)
266
{
267
    Visitor *v;
268
    Error *err = NULL;
269
    UserDefUnion *tmp;
270

    
271
    v = visitor_input_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 } }");
272

    
273
    visit_type_UserDefUnion(v, &tmp, NULL, &err);
274
    g_assert(err == NULL);
275
    g_assert_cmpint(tmp->kind, ==, USER_DEF_UNION_KIND_B);
276
    g_assert_cmpint(tmp->b->integer, ==, 42);
277
    qapi_free_UserDefUnion(tmp);
278
}
279

    
280
static void input_visitor_test_add(const char *testpath,
281
                                   TestInputVisitorData *data,
282
                                   void (*test_func)(TestInputVisitorData *data, const void *user_data))
283
{
284
    g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
285
               visitor_input_teardown);
286
}
287

    
288
static void test_visitor_in_errors(TestInputVisitorData *data,
289
                                   const void *unused)
290
{
291
    TestStruct *p = NULL;
292
    Error *errp = NULL;
293
    Visitor *v;
294

    
295
    v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', 'string': -42 }");
296

    
297
    visit_type_TestStruct(v, &p, NULL, &errp);
298
    g_assert(error_is_set(&errp));
299
    g_assert(p->string == NULL);
300

    
301
    g_free(p->string);
302
    g_free(p);
303
}
304

    
305
int main(int argc, char **argv)
306
{
307
    TestInputVisitorData in_visitor_data;
308

    
309
    g_test_init(&argc, &argv, NULL);
310

    
311
    input_visitor_test_add("/visitor/input/int",
312
                           &in_visitor_data, test_visitor_in_int);
313
    input_visitor_test_add("/visitor/input/int_overflow",
314
                           &in_visitor_data, test_visitor_in_int_overflow);
315
    input_visitor_test_add("/visitor/input/bool",
316
                           &in_visitor_data, test_visitor_in_bool);
317
    input_visitor_test_add("/visitor/input/number",
318
                           &in_visitor_data, test_visitor_in_number);
319
    input_visitor_test_add("/visitor/input/string",
320
                            &in_visitor_data, test_visitor_in_string);
321
    input_visitor_test_add("/visitor/input/enum",
322
                            &in_visitor_data, test_visitor_in_enum);
323
    input_visitor_test_add("/visitor/input/struct",
324
                            &in_visitor_data, test_visitor_in_struct);
325
    input_visitor_test_add("/visitor/input/struct-nested",
326
                            &in_visitor_data, test_visitor_in_struct_nested);
327
    input_visitor_test_add("/visitor/input/list",
328
                            &in_visitor_data, test_visitor_in_list);
329
    input_visitor_test_add("/visitor/input/union",
330
                            &in_visitor_data, test_visitor_in_union);
331
    input_visitor_test_add("/visitor/input/errors",
332
                            &in_visitor_data, test_visitor_in_errors);
333

    
334
    g_test_run();
335

    
336
    return 0;
337
}