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 close(cfgfd); 37 if (ret < 0) { 38 unlink(cfgpath); 39 } 40 g_assert_cmpint(ret, ==, strlen(cfgdata)); 41 42 args = g_strdup_printf("-nodefaults -machine none -readconfig %s", cfgpath); 43 44 qts = qtest_init(args); 45 46 unlink(cfgpath); 47 48 return qts; 49 } 50 51 static void test_x86_memdev_resp(QObject *res) 52 { 53 Visitor *v; 54 g_autoptr(MemdevList) memdevs = NULL; 55 Memdev *memdev; 56 57 g_assert(res); 58 v = qobject_input_visitor_new(res); 59 visit_type_MemdevList(v, NULL, &memdevs, &error_abort); 60 61 g_assert(memdevs); 62 g_assert(memdevs->value); 63 g_assert(!memdevs->next); 64 65 memdev = memdevs->value; 66 g_assert_cmpstr(memdev->id, ==, "ram"); 67 g_assert_cmpint(memdev->size, ==, 200 * MiB); 68 69 visit_free(v); 70 } 71 72 static void test_x86_memdev(void) 73 { 74 QDict *resp; 75 QTestState *qts; 76 const char *cfgdata = 77 "[memory]\n" 78 "size = \"200\""; 79 80 qts = qtest_init_with_config(cfgdata); 81 /* Test valid command */ 82 resp = qtest_qmp(qts, "{ 'execute': 'query-memdev' }"); 83 test_x86_memdev_resp(qdict_get(resp, "return")); 84 qobject_unref(resp); 85 86 qtest_quit(qts); 87 } 88 89 90 #ifdef CONFIG_SPICE 91 static void test_spice_resp(QObject *res) 92 { 93 Visitor *v; 94 g_autoptr(SpiceInfo) spice = NULL; 95 96 g_assert(res); 97 v = qobject_input_visitor_new(res); 98 visit_type_SpiceInfo(v, "spice", &spice, &error_abort); 99 100 g_assert(spice); 101 g_assert(spice->enabled); 102 103 visit_free(v); 104 } 105 106 static void test_spice(void) 107 { 108 QDict *resp; 109 QTestState *qts; 110 const char *cfgdata = 111 "[spice]\n" 112 #ifndef WIN32 113 "unix = \"on\"\n" 114 #endif 115 "disable-ticketing = \"on\"\n"; 116 117 qts = qtest_init_with_config(cfgdata); 118 /* Test valid command */ 119 resp = qtest_qmp(qts, "{ 'execute': 'query-spice' }"); 120 test_spice_resp(qdict_get(resp, "return")); 121 qobject_unref(resp); 122 123 qtest_quit(qts); 124 } 125 #endif 126 127 static void test_object_rng_resp(QObject *res) 128 { 129 Visitor *v; 130 g_autoptr(ObjectPropertyInfoList) objs = NULL; 131 ObjectPropertyInfoList *tmp; 132 ObjectPropertyInfo *obj; 133 bool seen_rng = false; 134 135 g_assert(res); 136 v = qobject_input_visitor_new(res); 137 visit_type_ObjectPropertyInfoList(v, NULL, &objs, &error_abort); 138 139 g_assert(objs); 140 tmp = objs; 141 while (tmp) { 142 g_assert(tmp->value); 143 144 obj = tmp->value; 145 if (g_str_equal(obj->name, "rng0") && 146 g_str_equal(obj->type, "child<rng-builtin>")) { 147 seen_rng = true; 148 break; 149 } 150 151 tmp = tmp->next; 152 } 153 154 g_assert(seen_rng); 155 156 visit_free(v); 157 } 158 159 static void test_object_rng(void) 160 { 161 QDict *resp; 162 QTestState *qts; 163 const char *cfgdata = 164 "[object]\n" 165 "qom-type = \"rng-builtin\"\n" 166 "id = \"rng0\"\n"; 167 168 qts = qtest_init_with_config(cfgdata); 169 /* Test valid command */ 170 resp = qtest_qmp(qts, 171 "{ 'execute': 'qom-list'," 172 " 'arguments': {'path': '/objects' }}"); 173 test_object_rng_resp(qdict_get(resp, "return")); 174 qobject_unref(resp); 175 176 qtest_quit(qts); 177 } 178 179 int main(int argc, char *argv[]) 180 { 181 const char *arch; 182 g_test_init(&argc, &argv, NULL); 183 184 arch = qtest_get_arch(); 185 186 if (g_str_equal(arch, "i386") || 187 g_str_equal(arch, "x86_64")) { 188 qtest_add_func("readconfig/x86/memdev", test_x86_memdev); 189 } 190 #ifdef CONFIG_SPICE 191 qtest_add_func("readconfig/spice", test_spice); 192 #endif 193 194 qtest_add_func("readconfig/object-rng", test_object_rng); 195 196 return g_test_run(); 197 } 198