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