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