xref: /qemu/tests/qtest/readconfig-test.c (revision 5a7d4dc9f84b1531cfd741404f44f3ad9c30faa7)
1f6a5f380SDaniel P. Berrangé /*
2f6a5f380SDaniel P. Berrangé  * Validate -readconfig
3f6a5f380SDaniel P. Berrangé  *
4f6a5f380SDaniel P. Berrangé  * Copyright (c) 2022 Red Hat, Inc.
5f6a5f380SDaniel P. Berrangé  *
6f6a5f380SDaniel P. Berrangé  * This work is licensed under the terms of the GNU GPL, version 2 or later.
7f6a5f380SDaniel P. Berrangé  * See the COPYING file in the top-level directory.
8f6a5f380SDaniel P. Berrangé  */
9f6a5f380SDaniel P. Berrangé 
10f6a5f380SDaniel P. Berrangé #include "qemu/osdep.h"
11f6a5f380SDaniel P. Berrangé #include "libqtest.h"
12f6a5f380SDaniel P. Berrangé #include "qapi/error.h"
13f6a5f380SDaniel P. Berrangé #include "qapi/qapi-visit-machine.h"
14f6a5f380SDaniel P. Berrangé #include "qapi/qapi-visit-qom.h"
15f6a5f380SDaniel P. Berrangé #include "qapi/qapi-visit-ui.h"
16f6a5f380SDaniel P. Berrangé #include "qapi/qmp/qdict.h"
17f6a5f380SDaniel P. Berrangé #include "qapi/qmp/qlist.h"
18f6a5f380SDaniel P. Berrangé #include "qapi/qobject-input-visitor.h"
19f6a5f380SDaniel P. Berrangé #include "qapi/qmp/qstring.h"
20f6a5f380SDaniel P. Berrangé #include "qemu/units.h"
21f6a5f380SDaniel P. Berrangé 
22f6a5f380SDaniel P. Berrangé static QTestState *qtest_init_with_config(const char *cfgdata)
23f6a5f380SDaniel P. Berrangé {
24f6a5f380SDaniel P. Berrangé     GError *error = NULL;
25f6a5f380SDaniel P. Berrangé     g_autofree char *args = NULL;
26f6a5f380SDaniel P. Berrangé     int cfgfd = -1;
27f6a5f380SDaniel P. Berrangé     g_autofree char *cfgpath = NULL;
28f6a5f380SDaniel P. Berrangé     QTestState *qts;
29f6a5f380SDaniel P. Berrangé     ssize_t ret;
30f6a5f380SDaniel P. Berrangé 
31f6a5f380SDaniel P. Berrangé     cfgfd = g_file_open_tmp("readconfig-test-XXXXXX", &cfgpath, &error);
32f6a5f380SDaniel P. Berrangé     g_assert_no_error(error);
33f6a5f380SDaniel P. Berrangé     g_assert_cmpint(cfgfd, >=, 0);
34f6a5f380SDaniel P. Berrangé 
35f6a5f380SDaniel P. Berrangé     ret = qemu_write_full(cfgfd, cfgdata, strlen(cfgdata));
369c23d719SDaniel P. Berrangé     close(cfgfd);
37f6a5f380SDaniel P. Berrangé     if (ret < 0) {
38f6a5f380SDaniel P. Berrangé         unlink(cfgpath);
39f6a5f380SDaniel P. Berrangé     }
40f6a5f380SDaniel P. Berrangé     g_assert_cmpint(ret, ==, strlen(cfgdata));
41f6a5f380SDaniel P. Berrangé 
42f6a5f380SDaniel P. Berrangé     args = g_strdup_printf("-nodefaults -machine none -readconfig %s", cfgpath);
43f6a5f380SDaniel P. Berrangé 
44f6a5f380SDaniel P. Berrangé     qts = qtest_init(args);
45f6a5f380SDaniel P. Berrangé 
46f6a5f380SDaniel P. Berrangé     unlink(cfgpath);
47f6a5f380SDaniel P. Berrangé 
48f6a5f380SDaniel P. Berrangé     return qts;
49f6a5f380SDaniel P. Berrangé }
50f6a5f380SDaniel P. Berrangé 
51*5a7d4dc9SThomas Huth static void test_x86_memdev_resp(QObject *res, const char *mem_id, int size)
52f6a5f380SDaniel P. Berrangé {
53f6a5f380SDaniel P. Berrangé     Visitor *v;
54f6a5f380SDaniel P. Berrangé     g_autoptr(MemdevList) memdevs = NULL;
55f6a5f380SDaniel P. Berrangé     Memdev *memdev;
56f6a5f380SDaniel P. Berrangé 
57f6a5f380SDaniel P. Berrangé     g_assert(res);
58f6a5f380SDaniel P. Berrangé     v = qobject_input_visitor_new(res);
59f6a5f380SDaniel P. Berrangé     visit_type_MemdevList(v, NULL, &memdevs, &error_abort);
60f6a5f380SDaniel P. Berrangé 
61f6a5f380SDaniel P. Berrangé     g_assert(memdevs);
62f6a5f380SDaniel P. Berrangé     g_assert(memdevs->value);
63f6a5f380SDaniel P. Berrangé     g_assert(!memdevs->next);
64f6a5f380SDaniel P. Berrangé 
65f6a5f380SDaniel P. Berrangé     memdev = memdevs->value;
66*5a7d4dc9SThomas Huth     g_assert_cmpstr(memdev->id, ==, mem_id);
67*5a7d4dc9SThomas Huth     g_assert_cmpint(memdev->size, ==, size * MiB);
68f6a5f380SDaniel P. Berrangé 
69f6a5f380SDaniel P. Berrangé     visit_free(v);
70f6a5f380SDaniel P. Berrangé }
71f6a5f380SDaniel P. Berrangé 
72f6a5f380SDaniel P. Berrangé static void test_x86_memdev(void)
73f6a5f380SDaniel P. Berrangé {
74f6a5f380SDaniel P. Berrangé     QDict *resp;
75f6a5f380SDaniel P. Berrangé     QTestState *qts;
76f6a5f380SDaniel P. Berrangé     const char *cfgdata =
77f6a5f380SDaniel P. Berrangé         "[memory]\n"
78f6a5f380SDaniel P. Berrangé         "size = \"200\"";
79f6a5f380SDaniel P. Berrangé 
80f6a5f380SDaniel P. Berrangé     qts = qtest_init_with_config(cfgdata);
81f6a5f380SDaniel P. Berrangé     /* Test valid command */
82f6a5f380SDaniel P. Berrangé     resp = qtest_qmp(qts, "{ 'execute': 'query-memdev' }");
83*5a7d4dc9SThomas Huth     test_x86_memdev_resp(qdict_get(resp, "return"), "ram", 200);
84f6a5f380SDaniel P. Berrangé     qobject_unref(resp);
85f6a5f380SDaniel P. Berrangé 
86f6a5f380SDaniel P. Berrangé     qtest_quit(qts);
87f6a5f380SDaniel P. Berrangé }
88f6a5f380SDaniel P. Berrangé 
8901013d2cSThomas Huth /* FIXME: The test is currently broken on FreeBSD */
9001013d2cSThomas Huth #if defined(CONFIG_SPICE) && !defined(__FreeBSD__)
91f6a5f380SDaniel P. Berrangé static void test_spice_resp(QObject *res)
92f6a5f380SDaniel P. Berrangé {
93f6a5f380SDaniel P. Berrangé     Visitor *v;
94f6a5f380SDaniel P. Berrangé     g_autoptr(SpiceInfo) spice = NULL;
95f6a5f380SDaniel P. Berrangé 
96f6a5f380SDaniel P. Berrangé     g_assert(res);
97f6a5f380SDaniel P. Berrangé     v = qobject_input_visitor_new(res);
989c23d719SDaniel P. Berrangé     visit_type_SpiceInfo(v, "spice", &spice, &error_abort);
99f6a5f380SDaniel P. Berrangé 
100f6a5f380SDaniel P. Berrangé     g_assert(spice);
101f6a5f380SDaniel P. Berrangé     g_assert(spice->enabled);
102f6a5f380SDaniel P. Berrangé 
103f6a5f380SDaniel P. Berrangé     visit_free(v);
104f6a5f380SDaniel P. Berrangé }
105f6a5f380SDaniel P. Berrangé 
106f6a5f380SDaniel P. Berrangé static void test_spice(void)
107f6a5f380SDaniel P. Berrangé {
108f6a5f380SDaniel P. Berrangé     QDict *resp;
109f6a5f380SDaniel P. Berrangé     QTestState *qts;
110f6a5f380SDaniel P. Berrangé     const char *cfgdata =
111f6a5f380SDaniel P. Berrangé         "[spice]\n"
112beecc4b7SMarc-André Lureau #ifndef WIN32
113beecc4b7SMarc-André Lureau         "unix = \"on\"\n"
114beecc4b7SMarc-André Lureau #endif
115beecc4b7SMarc-André Lureau         "disable-ticketing = \"on\"\n";
116f6a5f380SDaniel P. Berrangé 
117f6a5f380SDaniel P. Berrangé     qts = qtest_init_with_config(cfgdata);
118f6a5f380SDaniel P. Berrangé     /* Test valid command */
119f6a5f380SDaniel P. Berrangé     resp = qtest_qmp(qts, "{ 'execute': 'query-spice' }");
120f6a5f380SDaniel P. Berrangé     test_spice_resp(qdict_get(resp, "return"));
121f6a5f380SDaniel P. Berrangé     qobject_unref(resp);
122f6a5f380SDaniel P. Berrangé 
123f6a5f380SDaniel P. Berrangé     qtest_quit(qts);
124f6a5f380SDaniel P. Berrangé }
125f6a5f380SDaniel P. Berrangé #endif
126f6a5f380SDaniel P. Berrangé 
12779571e7fSThomas Huth static void test_object_available(QObject *res, const char *name,
12879571e7fSThomas Huth                                   const char *type)
129f6a5f380SDaniel P. Berrangé {
130f6a5f380SDaniel P. Berrangé     Visitor *v;
131f6a5f380SDaniel P. Berrangé     g_autoptr(ObjectPropertyInfoList) objs = NULL;
132f6a5f380SDaniel P. Berrangé     ObjectPropertyInfoList *tmp;
133f6a5f380SDaniel P. Berrangé     ObjectPropertyInfo *obj;
13479571e7fSThomas Huth     bool object_available = false;
13579571e7fSThomas Huth     g_autofree char *childtype = g_strdup_printf("child<%s>", type);
136f6a5f380SDaniel P. Berrangé 
137f6a5f380SDaniel P. Berrangé     g_assert(res);
138f6a5f380SDaniel P. Berrangé     v = qobject_input_visitor_new(res);
139f6a5f380SDaniel P. Berrangé     visit_type_ObjectPropertyInfoList(v, NULL, &objs, &error_abort);
140f6a5f380SDaniel P. Berrangé 
141f6a5f380SDaniel P. Berrangé     g_assert(objs);
142f6a5f380SDaniel P. Berrangé     tmp = objs;
143f6a5f380SDaniel P. Berrangé     while (tmp) {
144f6a5f380SDaniel P. Berrangé         g_assert(tmp->value);
145f6a5f380SDaniel P. Berrangé 
146f6a5f380SDaniel P. Berrangé         obj = tmp->value;
14779571e7fSThomas Huth         if (g_str_equal(obj->name, name) && g_str_equal(obj->type, childtype)) {
14879571e7fSThomas Huth             object_available = true;
1499c23d719SDaniel P. Berrangé             break;
150f6a5f380SDaniel P. Berrangé         }
151f6a5f380SDaniel P. Berrangé 
152f6a5f380SDaniel P. Berrangé         tmp = tmp->next;
153f6a5f380SDaniel P. Berrangé     }
154f6a5f380SDaniel P. Berrangé 
15579571e7fSThomas Huth     g_assert(object_available);
156f6a5f380SDaniel P. Berrangé 
157f6a5f380SDaniel P. Berrangé     visit_free(v);
158f6a5f380SDaniel P. Berrangé }
159f6a5f380SDaniel P. Berrangé 
160f6a5f380SDaniel P. Berrangé static void test_object_rng(void)
161f6a5f380SDaniel P. Berrangé {
162f6a5f380SDaniel P. Berrangé     QDict *resp;
163f6a5f380SDaniel P. Berrangé     QTestState *qts;
164f6a5f380SDaniel P. Berrangé     const char *cfgdata =
165f6a5f380SDaniel P. Berrangé         "[object]\n"
166f6a5f380SDaniel P. Berrangé         "qom-type = \"rng-builtin\"\n"
167f6a5f380SDaniel P. Berrangé         "id = \"rng0\"\n";
168f6a5f380SDaniel P. Berrangé 
169f6a5f380SDaniel P. Berrangé     qts = qtest_init_with_config(cfgdata);
170f6a5f380SDaniel P. Berrangé     /* Test valid command */
171f6a5f380SDaniel P. Berrangé     resp = qtest_qmp(qts,
172f6a5f380SDaniel P. Berrangé                      "{ 'execute': 'qom-list',"
173f6a5f380SDaniel P. Berrangé                      "  'arguments': {'path': '/objects' }}");
17479571e7fSThomas Huth     test_object_available(qdict_get(resp, "return"), "rng0", "rng-builtin");
175f6a5f380SDaniel P. Berrangé     qobject_unref(resp);
176f6a5f380SDaniel P. Berrangé 
177f6a5f380SDaniel P. Berrangé     qtest_quit(qts);
178f6a5f380SDaniel P. Berrangé }
179f6a5f380SDaniel P. Berrangé 
180201aa17eSThomas Huth static void test_docs_config_ich9(void)
181201aa17eSThomas Huth {
182201aa17eSThomas Huth     QTestState *qts;
183201aa17eSThomas Huth     QDict *resp;
184201aa17eSThomas Huth     QObject *qobj;
185201aa17eSThomas Huth 
186201aa17eSThomas Huth     qts = qtest_initf("-nodefaults -readconfig docs/config/ich9-ehci-uhci.cfg");
187201aa17eSThomas Huth 
188201aa17eSThomas Huth     resp = qtest_qmp(qts, "{ 'execute': 'qom-list',"
189201aa17eSThomas Huth                           "  'arguments': {'path': '/machine/peripheral' }}");
190201aa17eSThomas Huth     qobj = qdict_get(resp, "return");
191201aa17eSThomas Huth     test_object_available(qobj, "ehci", "ich9-usb-ehci1");
192201aa17eSThomas Huth     test_object_available(qobj, "uhci-1", "ich9-usb-uhci1");
193201aa17eSThomas Huth     test_object_available(qobj, "uhci-2", "ich9-usb-uhci2");
194201aa17eSThomas Huth     test_object_available(qobj, "uhci-3", "ich9-usb-uhci3");
195201aa17eSThomas Huth     qobject_unref(resp);
196201aa17eSThomas Huth 
197201aa17eSThomas Huth     qtest_quit(qts);
198201aa17eSThomas Huth }
199201aa17eSThomas Huth 
200f6a5f380SDaniel P. Berrangé int main(int argc, char *argv[])
201f6a5f380SDaniel P. Berrangé {
202f6a5f380SDaniel P. Berrangé     const char *arch;
203f6a5f380SDaniel P. Berrangé     g_test_init(&argc, &argv, NULL);
204f6a5f380SDaniel P. Berrangé 
205f6a5f380SDaniel P. Berrangé     arch = qtest_get_arch();
206f6a5f380SDaniel P. Berrangé 
207f6a5f380SDaniel P. Berrangé     if (g_str_equal(arch, "i386") ||
208f6a5f380SDaniel P. Berrangé         g_str_equal(arch, "x86_64")) {
209f6a5f380SDaniel P. Berrangé         qtest_add_func("readconfig/x86/memdev", test_x86_memdev);
210335da811SThomas Huth         if (qtest_has_device("ich9-usb-ehci1") &&
211335da811SThomas Huth             qtest_has_device("ich9-usb-uhci1")) {
212201aa17eSThomas Huth             qtest_add_func("readconfig/x86/ich9-ehci-uhci", test_docs_config_ich9);
213f6a5f380SDaniel P. Berrangé         }
214335da811SThomas Huth     }
21501013d2cSThomas Huth #if defined(CONFIG_SPICE) && !defined(__FreeBSD__)
216f6a5f380SDaniel P. Berrangé     qtest_add_func("readconfig/spice", test_spice);
217f6a5f380SDaniel P. Berrangé #endif
218f6a5f380SDaniel P. Berrangé 
219f6a5f380SDaniel P. Berrangé     qtest_add_func("readconfig/object-rng", test_object_rng);
220f6a5f380SDaniel P. Berrangé 
221f6a5f380SDaniel P. Berrangé     return g_test_run();
222f6a5f380SDaniel P. Berrangé }
223