1 /* 2 * Validate -readconfig 3 * 4 * Copyright (c) 2022 Red Hat, Inc. 5 * 6 * This work is licensed under the terms of the GNU GPL, version 2 or later. 7 * See the COPYING file in the top-level directory. 8 */ 9 10 #include "qemu/osdep.h" 11 #include "libqtest.h" 12 #include "qapi/error.h" 13 #include "qapi/qapi-visit-machine.h" 14 #include "qapi/qapi-visit-qom.h" 15 #include "qapi/qapi-visit-ui.h" 16 #include "qapi/qmp/qdict.h" 17 #include "qapi/qmp/qlist.h" 18 #include "qapi/qobject-input-visitor.h" 19 #include "qapi/qmp/qstring.h" 20 #include "qemu/units.h" 21 22 static QTestState *qtest_init_with_config(const char *cfgdata) 23 { 24 GError *error = NULL; 25 g_autofree char *args = NULL; 26 int cfgfd = -1; 27 g_autofree char *cfgpath = NULL; 28 QTestState *qts; 29 ssize_t ret; 30 31 cfgfd = g_file_open_tmp("readconfig-test-XXXXXX", &cfgpath, &error); 32 g_assert_no_error(error); 33 g_assert_cmpint(cfgfd, >=, 0); 34 35 ret = qemu_write_full(cfgfd, cfgdata, strlen(cfgdata)); 36 if (ret < 0) { 37 unlink(cfgpath); 38 } 39 g_assert_cmpint(ret, ==, strlen(cfgdata)); 40 41 close(cfgfd); 42 43 args = g_strdup_printf("-nodefaults -machine none -readconfig %s", cfgpath); 44 45 qts = qtest_init(args); 46 47 unlink(cfgpath); 48 49 return qts; 50 } 51 52 static void test_x86_memdev_resp(QObject *res) 53 { 54 Visitor *v; 55 g_autoptr(MemdevList) memdevs = NULL; 56 Memdev *memdev; 57 58 g_assert(res); 59 v = qobject_input_visitor_new(res); 60 visit_type_MemdevList(v, NULL, &memdevs, &error_abort); 61 62 g_assert(memdevs); 63 g_assert(memdevs->value); 64 g_assert(!memdevs->next); 65 66 memdev = memdevs->value; 67 g_assert_cmpstr(memdev->id, ==, "ram"); 68 g_assert_cmpint(memdev->size, ==, 200 * MiB); 69 70 visit_free(v); 71 } 72 73 static void test_x86_memdev(void) 74 { 75 QDict *resp; 76 QTestState *qts; 77 const char *cfgdata = 78 "[memory]\n" 79 "size = \"200\""; 80 81 qts = qtest_init_with_config(cfgdata); 82 /* Test valid command */ 83 resp = qtest_qmp(qts, "{ 'execute': 'query-memdev' }"); 84 test_x86_memdev_resp(qdict_get(resp, "return")); 85 qobject_unref(resp); 86 87 qtest_quit(qts); 88 } 89 90 91 #ifdef CONFIG_SPICE 92 static void test_spice_resp(QObject *res) 93 { 94 Visitor *v; 95 g_autoptr(SpiceInfo) spice = NULL; 96 97 g_assert(res); 98 v = qobject_input_visitor_new(res); 99 visit_type_SpiceInfo(v, "spcie", &spice, &error_abort); 100 101 g_assert(spice); 102 g_assert(spice->enabled); 103 104 visit_free(v); 105 } 106 107 static void test_spice(void) 108 { 109 QDict *resp; 110 QTestState *qts; 111 const char *cfgdata = 112 "[spice]\n" 113 "disable-ticketing = \"on\"\n" 114 "unix = \"on\"\n"; 115 116 qts = qtest_init_with_config(cfgdata); 117 /* Test valid command */ 118 resp = qtest_qmp(qts, "{ 'execute': 'query-spice' }"); 119 test_spice_resp(qdict_get(resp, "return")); 120 qobject_unref(resp); 121 122 qtest_quit(qts); 123 } 124 #endif 125 126 static void test_object_rng_resp(QObject *res) 127 { 128 Visitor *v; 129 g_autoptr(ObjectPropertyInfoList) objs = NULL; 130 ObjectPropertyInfoList *tmp; 131 ObjectPropertyInfo *obj; 132 bool seen_rng = false; 133 134 g_assert(res); 135 v = qobject_input_visitor_new(res); 136 visit_type_ObjectPropertyInfoList(v, NULL, &objs, &error_abort); 137 138 g_assert(objs); 139 tmp = objs; 140 while (tmp) { 141 g_assert(tmp->value); 142 143 obj = tmp->value; 144 if (g_str_equal(obj->name, "rng0") && 145 g_str_equal(obj->type, "child<rng-builtin>")) { 146 seen_rng = true; 147 } 148 149 tmp = tmp->next; 150 } 151 152 g_assert(seen_rng); 153 154 visit_free(v); 155 } 156 157 static void test_object_rng(void) 158 { 159 QDict *resp; 160 QTestState *qts; 161 const char *cfgdata = 162 "[object]\n" 163 "qom-type = \"rng-builtin\"\n" 164 "id = \"rng0\"\n"; 165 166 qts = qtest_init_with_config(cfgdata); 167 /* Test valid command */ 168 resp = qtest_qmp(qts, 169 "{ 'execute': 'qom-list'," 170 " 'arguments': {'path': '/objects' }}"); 171 test_object_rng_resp(qdict_get(resp, "return")); 172 qobject_unref(resp); 173 174 qtest_quit(qts); 175 } 176 177 int main(int argc, char *argv[]) 178 { 179 const char *arch; 180 g_test_init(&argc, &argv, NULL); 181 182 arch = qtest_get_arch(); 183 184 if (g_str_equal(arch, "i386") || 185 g_str_equal(arch, "x86_64")) { 186 qtest_add_func("readconfig/x86/memdev", test_x86_memdev); 187 } 188 #ifdef CONFIG_SPICE 189 qtest_add_func("readconfig/spice", test_spice); 190 #endif 191 192 qtest_add_func("readconfig/object-rng", test_object_rng); 193 194 return g_test_run(); 195 } 196