xref: /qemu/tests/unit/test-string-output-visitor.c (revision 23d1705f425ca847f11d92e4363cd7f67f369fd8)
1 /*
2  * String Output Visitor unit-tests.
3  *
4  * Copyright (C) 2012 Red Hat Inc.
5  *
6  * Authors:
7  *  Paolo Bonzini <pbonzini@redhat.com> (based on test-qmp-output-visitor)
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 "qemu-common.h"
16 #include "qapi/error.h"
17 #include "qapi/string-output-visitor.h"
18 #include "test-qapi-types.h"
19 #include "test-qapi-visit.h"
20 #include "qapi/qmp/types.h"
21 
22 typedef struct TestOutputVisitorData {
23     StringOutputVisitor *sov;
24     Visitor *ov;
25     char *str;
26     bool human;
27 } TestOutputVisitorData;
28 
29 static void visitor_output_setup_internal(TestOutputVisitorData *data,
30                                           bool human)
31 {
32     data->human = human;
33     data->sov = string_output_visitor_new(human);
34     g_assert(data->sov);
35     data->ov = string_output_get_visitor(data->sov);
36     g_assert(data->ov);
37 }
38 
39 static void visitor_output_setup(TestOutputVisitorData *data,
40                                  const void *unused)
41 {
42     return visitor_output_setup_internal(data, false);
43 }
44 
45 static void visitor_output_setup_human(TestOutputVisitorData *data,
46                                        const void *unused)
47 {
48     return visitor_output_setup_internal(data, true);
49 }
50 
51 static void visitor_output_teardown(TestOutputVisitorData *data,
52                                     const void *unused)
53 {
54     visit_free(data->ov);
55     data->sov = NULL;
56     data->ov = NULL;
57     g_free(data->str);
58     data->str = NULL;
59 }
60 
61 static char *visitor_get(TestOutputVisitorData *data)
62 {
63     data->str = string_output_get_string(data->sov);
64     g_assert(data->str);
65     return data->str;
66 }
67 
68 static void visitor_reset(TestOutputVisitorData *data)
69 {
70     bool human = data->human;
71 
72     visitor_output_teardown(data, NULL);
73     visitor_output_setup_internal(data, human);
74 }
75 
76 static void test_visitor_out_int(TestOutputVisitorData *data,
77                                  const void *unused)
78 {
79     int64_t value = 42;
80     Error *err = NULL;
81     char *str;
82 
83     visit_type_int(data->ov, NULL, &value, &err);
84     g_assert(!err);
85 
86     str = visitor_get(data);
87     if (data->human) {
88         g_assert_cmpstr(str, ==, "42 (0x2a)");
89     } else {
90         g_assert_cmpstr(str, ==, "42");
91     }
92 }
93 
94 static void test_visitor_out_intList(TestOutputVisitorData *data,
95                                      const void *unused)
96 {
97     int64_t value[] = {0, 1, 9, 10, 16, 15, 14,
98         3, 4, 5, 6, 11, 12, 13, 21, 22, INT64_MAX - 1, INT64_MAX};
99     intList *list = NULL, **tmp = &list;
100     int i;
101     Error *err = NULL;
102     char *str;
103 
104     for (i = 0; i < sizeof(value) / sizeof(value[0]); i++) {
105         *tmp = g_malloc0(sizeof(**tmp));
106         (*tmp)->value = value[i];
107         tmp = &(*tmp)->next;
108     }
109 
110     visit_type_intList(data->ov, NULL, &list, &err);
111     g_assert(err == NULL);
112 
113     str = visitor_get(data);
114     if (data->human) {
115         g_assert_cmpstr(str, ==,
116             "0-1,3-6,9-16,21-22,9223372036854775806-9223372036854775807 "
117             "(0x0-0x1,0x3-0x6,0x9-0x10,0x15-0x16,"
118             "0x7ffffffffffffffe-0x7fffffffffffffff)");
119     } else {
120         g_assert_cmpstr(str, ==,
121             "0-1,3-6,9-16,21-22,9223372036854775806-9223372036854775807");
122     }
123     qapi_free_intList(list);
124 }
125 
126 static void test_visitor_out_bool(TestOutputVisitorData *data,
127                                   const void *unused)
128 {
129     Error *err = NULL;
130     bool value = true;
131     char *str;
132 
133     visit_type_bool(data->ov, NULL, &value, &err);
134     g_assert(!err);
135 
136     str = visitor_get(data);
137     g_assert_cmpstr(str, ==, "true");
138 }
139 
140 static void test_visitor_out_number(TestOutputVisitorData *data,
141                                     const void *unused)
142 {
143     double value = 3.14;
144     Error *err = NULL;
145     char *str;
146 
147     visit_type_number(data->ov, NULL, &value, &err);
148     g_assert(!err);
149 
150     str = visitor_get(data);
151     g_assert_cmpstr(str, ==, "3.140000");
152 }
153 
154 static void test_visitor_out_string(TestOutputVisitorData *data,
155                                     const void *unused)
156 {
157     char *string = (char *) "Q E M U";
158     const char *string_human = "\"Q E M U\"";
159     Error *err = NULL;
160     char *str;
161 
162     visit_type_str(data->ov, NULL, &string, &err);
163     g_assert(!err);
164 
165     str = visitor_get(data);
166     if (data->human) {
167         g_assert_cmpstr(str, ==, string_human);
168     } else {
169         g_assert_cmpstr(str, ==, string);
170     }
171 }
172 
173 static void test_visitor_out_no_string(TestOutputVisitorData *data,
174                                        const void *unused)
175 {
176     char *string = NULL;
177     char *str;
178 
179     /* A null string should return "" */
180     visit_type_str(data->ov, NULL, &string, &error_abort);
181 
182     str = visitor_get(data);
183     if (data->human) {
184         g_assert_cmpstr(str, ==, "<null>");
185     } else {
186         g_assert_cmpstr(str, ==, "");
187     }
188 }
189 
190 static void test_visitor_out_enum(TestOutputVisitorData *data,
191                                   const void *unused)
192 {
193     char *str;
194     EnumOne i;
195 
196     for (i = 0; i < ENUM_ONE__MAX; i++) {
197         visit_type_EnumOne(data->ov, "unused", &i, &error_abort);
198 
199         str = visitor_get(data);
200         if (data->human) {
201             char *str_human = g_strdup_printf("\"%s\"", EnumOne_lookup[i]);
202 
203             g_assert_cmpstr(str, ==, str_human);
204             g_free(str_human);
205         } else {
206             g_assert_cmpstr(str, ==, EnumOne_lookup[i]);
207         }
208         visitor_reset(data);
209     }
210 }
211 
212 static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
213                                          const void *unused)
214 {
215     EnumOne i, bad_values[] = { ENUM_ONE__MAX, -1 };
216     Error *err;
217 
218     for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
219         err = NULL;
220         visit_type_EnumOne(data->ov, "unused", &bad_values[i], &err);
221         error_free_or_abort(&err);
222     }
223 }
224 
225 static void
226 output_visitor_test_add(const char *testpath,
227                         TestOutputVisitorData *data,
228                         void (*test_func)(TestOutputVisitorData *data,
229                                           const void *user_data),
230                         bool human)
231 {
232     g_test_add(testpath, TestOutputVisitorData, data,
233                human ? visitor_output_setup_human : visitor_output_setup,
234                test_func, visitor_output_teardown);
235 }
236 
237 int main(int argc, char **argv)
238 {
239     TestOutputVisitorData out_visitor_data;
240 
241     g_test_init(&argc, &argv, NULL);
242 
243     output_visitor_test_add("/string-visitor/output/int",
244                             &out_visitor_data, test_visitor_out_int, false);
245     output_visitor_test_add("/string-visitor/output/int-human",
246                             &out_visitor_data, test_visitor_out_int, true);
247     output_visitor_test_add("/string-visitor/output/bool",
248                             &out_visitor_data, test_visitor_out_bool, false);
249     output_visitor_test_add("/string-visitor/output/bool-human",
250                             &out_visitor_data, test_visitor_out_bool, true);
251     output_visitor_test_add("/string-visitor/output/number",
252                             &out_visitor_data, test_visitor_out_number, false);
253     output_visitor_test_add("/string-visitor/output/number-human",
254                             &out_visitor_data, test_visitor_out_number, true);
255     output_visitor_test_add("/string-visitor/output/string",
256                             &out_visitor_data, test_visitor_out_string, false);
257     output_visitor_test_add("/string-visitor/output/string-human",
258                             &out_visitor_data, test_visitor_out_string, true);
259     output_visitor_test_add("/string-visitor/output/no-string",
260                             &out_visitor_data, test_visitor_out_no_string,
261                             false);
262     output_visitor_test_add("/string-visitor/output/no-string-human",
263                             &out_visitor_data, test_visitor_out_no_string,
264                             true);
265     output_visitor_test_add("/string-visitor/output/enum",
266                             &out_visitor_data, test_visitor_out_enum, false);
267     output_visitor_test_add("/string-visitor/output/enum-human",
268                             &out_visitor_data, test_visitor_out_enum, true);
269     output_visitor_test_add("/string-visitor/output/enum-errors",
270                             &out_visitor_data, test_visitor_out_enum_errors,
271                             false);
272     output_visitor_test_add("/string-visitor/output/enum-errors-human",
273                             &out_visitor_data, test_visitor_out_enum_errors,
274                             true);
275     output_visitor_test_add("/string-visitor/output/intList",
276                             &out_visitor_data, test_visitor_out_intList, false);
277     output_visitor_test_add("/string-visitor/output/intList-human",
278                             &out_visitor_data, test_visitor_out_intList, true);
279 
280     g_test_run();
281 
282     return 0;
283 }
284