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