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