1*1e8a1faeSThomas Huth /* 2*1e8a1faeSThomas Huth * Test HMP commands. 3*1e8a1faeSThomas Huth * 4*1e8a1faeSThomas Huth * Copyright (c) 2017 Red Hat Inc. 5*1e8a1faeSThomas Huth * 6*1e8a1faeSThomas Huth * Author: 7*1e8a1faeSThomas Huth * Thomas Huth <thuth@redhat.com> 8*1e8a1faeSThomas Huth * 9*1e8a1faeSThomas Huth * This work is licensed under the terms of the GNU GPL, version 2 10*1e8a1faeSThomas Huth * or later. See the COPYING file in the top-level directory. 11*1e8a1faeSThomas Huth * 12*1e8a1faeSThomas Huth * This test calls some HMP commands for all machines that the current 13*1e8a1faeSThomas Huth * QEMU binary provides, to check whether they terminate successfully 14*1e8a1faeSThomas Huth * (i.e. do not crash QEMU). 15*1e8a1faeSThomas Huth */ 16*1e8a1faeSThomas Huth 17*1e8a1faeSThomas Huth #include "qemu/osdep.h" 18*1e8a1faeSThomas Huth #include "libqtest.h" 19*1e8a1faeSThomas Huth 20*1e8a1faeSThomas Huth static int verbose; 21*1e8a1faeSThomas Huth 22*1e8a1faeSThomas Huth static const char *hmp_cmds[] = { 23*1e8a1faeSThomas Huth "announce_self", 24*1e8a1faeSThomas Huth "boot_set ndc", 25*1e8a1faeSThomas Huth "chardev-add null,id=testchardev1", 26*1e8a1faeSThomas Huth "chardev-send-break testchardev1", 27*1e8a1faeSThomas Huth "chardev-change testchardev1 ringbuf", 28*1e8a1faeSThomas Huth "chardev-remove testchardev1", 29*1e8a1faeSThomas Huth "commit all", 30*1e8a1faeSThomas Huth "cpu-add 1", 31*1e8a1faeSThomas Huth "cpu 0", 32*1e8a1faeSThomas Huth "device_add ?", 33*1e8a1faeSThomas Huth "device_add usb-mouse,id=mouse1", 34*1e8a1faeSThomas Huth "drive_add ignored format=help", 35*1e8a1faeSThomas Huth "mouse_button 7", 36*1e8a1faeSThomas Huth "mouse_move 10 10", 37*1e8a1faeSThomas Huth "mouse_button 0", 38*1e8a1faeSThomas Huth "device_del mouse1", 39*1e8a1faeSThomas Huth "dump-guest-memory /dev/null 0 4096", 40*1e8a1faeSThomas Huth "dump-guest-memory /dev/null", 41*1e8a1faeSThomas Huth "gdbserver", 42*1e8a1faeSThomas Huth "gva2gpa 0", 43*1e8a1faeSThomas Huth "hostfwd_add tcp::43210-:43210", 44*1e8a1faeSThomas Huth "hostfwd_remove tcp::43210-:43210", 45*1e8a1faeSThomas Huth "i /w 0", 46*1e8a1faeSThomas Huth "log all", 47*1e8a1faeSThomas Huth "log none", 48*1e8a1faeSThomas Huth "memsave 0 4096 \"/dev/null\"", 49*1e8a1faeSThomas Huth "migrate_set_cache_size 1", 50*1e8a1faeSThomas Huth "migrate_set_downtime 1", 51*1e8a1faeSThomas Huth "migrate_set_speed 1", 52*1e8a1faeSThomas Huth "netdev_add user,id=net1", 53*1e8a1faeSThomas Huth "set_link net1 off", 54*1e8a1faeSThomas Huth "set_link net1 on", 55*1e8a1faeSThomas Huth "netdev_del net1", 56*1e8a1faeSThomas Huth "nmi", 57*1e8a1faeSThomas Huth "o /w 0 0x1234", 58*1e8a1faeSThomas Huth "object_add memory-backend-ram,id=mem1,size=256M", 59*1e8a1faeSThomas Huth "object_del mem1", 60*1e8a1faeSThomas Huth "pmemsave 0 4096 \"/dev/null\"", 61*1e8a1faeSThomas Huth "p $pc + 8", 62*1e8a1faeSThomas Huth "qom-list /", 63*1e8a1faeSThomas Huth "qom-set /machine initrd test", 64*1e8a1faeSThomas Huth "screendump /dev/null", 65*1e8a1faeSThomas Huth "sendkey x", 66*1e8a1faeSThomas Huth "singlestep on", 67*1e8a1faeSThomas Huth "wavcapture /dev/null", 68*1e8a1faeSThomas Huth "stopcapture 0", 69*1e8a1faeSThomas Huth "sum 0 512", 70*1e8a1faeSThomas Huth "x /8i 0x100", 71*1e8a1faeSThomas Huth "xp /16x 0", 72*1e8a1faeSThomas Huth NULL 73*1e8a1faeSThomas Huth }; 74*1e8a1faeSThomas Huth 75*1e8a1faeSThomas Huth /* Run through the list of pre-defined commands */ 76*1e8a1faeSThomas Huth static void test_commands(QTestState *qts) 77*1e8a1faeSThomas Huth { 78*1e8a1faeSThomas Huth char *response; 79*1e8a1faeSThomas Huth int i; 80*1e8a1faeSThomas Huth 81*1e8a1faeSThomas Huth for (i = 0; hmp_cmds[i] != NULL; i++) { 82*1e8a1faeSThomas Huth response = qtest_hmp(qts, "%s", hmp_cmds[i]); 83*1e8a1faeSThomas Huth if (verbose) { 84*1e8a1faeSThomas Huth fprintf(stderr, 85*1e8a1faeSThomas Huth "\texecute HMP command: %s\n" 86*1e8a1faeSThomas Huth "\tresult : %s\n", 87*1e8a1faeSThomas Huth hmp_cmds[i], response); 88*1e8a1faeSThomas Huth } 89*1e8a1faeSThomas Huth g_free(response); 90*1e8a1faeSThomas Huth } 91*1e8a1faeSThomas Huth 92*1e8a1faeSThomas Huth } 93*1e8a1faeSThomas Huth 94*1e8a1faeSThomas Huth /* Run through all info commands and call them blindly (without arguments) */ 95*1e8a1faeSThomas Huth static void test_info_commands(QTestState *qts) 96*1e8a1faeSThomas Huth { 97*1e8a1faeSThomas Huth char *resp, *info, *info_buf, *endp; 98*1e8a1faeSThomas Huth 99*1e8a1faeSThomas Huth info_buf = info = qtest_hmp(qts, "help info"); 100*1e8a1faeSThomas Huth 101*1e8a1faeSThomas Huth while (*info) { 102*1e8a1faeSThomas Huth /* Extract the info command, ignore parameters and description */ 103*1e8a1faeSThomas Huth g_assert(strncmp(info, "info ", 5) == 0); 104*1e8a1faeSThomas Huth endp = strchr(&info[5], ' '); 105*1e8a1faeSThomas Huth g_assert(endp != NULL); 106*1e8a1faeSThomas Huth *endp = '\0'; 107*1e8a1faeSThomas Huth /* Now run the info command */ 108*1e8a1faeSThomas Huth if (verbose) { 109*1e8a1faeSThomas Huth fprintf(stderr, "\t%s\n", info); 110*1e8a1faeSThomas Huth } 111*1e8a1faeSThomas Huth resp = qtest_hmp(qts, "%s", info); 112*1e8a1faeSThomas Huth g_free(resp); 113*1e8a1faeSThomas Huth /* And move forward to the next line */ 114*1e8a1faeSThomas Huth info = strchr(endp + 1, '\n'); 115*1e8a1faeSThomas Huth if (!info) { 116*1e8a1faeSThomas Huth break; 117*1e8a1faeSThomas Huth } 118*1e8a1faeSThomas Huth info += 1; 119*1e8a1faeSThomas Huth } 120*1e8a1faeSThomas Huth 121*1e8a1faeSThomas Huth g_free(info_buf); 122*1e8a1faeSThomas Huth } 123*1e8a1faeSThomas Huth 124*1e8a1faeSThomas Huth static void test_machine(gconstpointer data) 125*1e8a1faeSThomas Huth { 126*1e8a1faeSThomas Huth const char *machine = data; 127*1e8a1faeSThomas Huth char *args; 128*1e8a1faeSThomas Huth QTestState *qts; 129*1e8a1faeSThomas Huth 130*1e8a1faeSThomas Huth args = g_strdup_printf("-S -M %s", machine); 131*1e8a1faeSThomas Huth qts = qtest_init(args); 132*1e8a1faeSThomas Huth 133*1e8a1faeSThomas Huth test_info_commands(qts); 134*1e8a1faeSThomas Huth test_commands(qts); 135*1e8a1faeSThomas Huth 136*1e8a1faeSThomas Huth qtest_quit(qts); 137*1e8a1faeSThomas Huth g_free(args); 138*1e8a1faeSThomas Huth g_free((void *)data); 139*1e8a1faeSThomas Huth } 140*1e8a1faeSThomas Huth 141*1e8a1faeSThomas Huth static void add_machine_test_case(const char *mname) 142*1e8a1faeSThomas Huth { 143*1e8a1faeSThomas Huth char *path; 144*1e8a1faeSThomas Huth 145*1e8a1faeSThomas Huth /* Ignore blacklisted machines that have known problems */ 146*1e8a1faeSThomas Huth if (!strcmp("xenfv", mname) || !strcmp("xenpv", mname)) { 147*1e8a1faeSThomas Huth return; 148*1e8a1faeSThomas Huth } 149*1e8a1faeSThomas Huth 150*1e8a1faeSThomas Huth path = g_strdup_printf("hmp/%s", mname); 151*1e8a1faeSThomas Huth qtest_add_data_func(path, g_strdup(mname), test_machine); 152*1e8a1faeSThomas Huth g_free(path); 153*1e8a1faeSThomas Huth } 154*1e8a1faeSThomas Huth 155*1e8a1faeSThomas Huth int main(int argc, char **argv) 156*1e8a1faeSThomas Huth { 157*1e8a1faeSThomas Huth char *v_env = getenv("V"); 158*1e8a1faeSThomas Huth 159*1e8a1faeSThomas Huth if (v_env && *v_env >= '2') { 160*1e8a1faeSThomas Huth verbose = true; 161*1e8a1faeSThomas Huth } 162*1e8a1faeSThomas Huth 163*1e8a1faeSThomas Huth g_test_init(&argc, &argv, NULL); 164*1e8a1faeSThomas Huth 165*1e8a1faeSThomas Huth qtest_cb_for_every_machine(add_machine_test_case, g_test_quick()); 166*1e8a1faeSThomas Huth 167*1e8a1faeSThomas Huth /* as none machine has no memory by default, add a test case with memory */ 168*1e8a1faeSThomas Huth qtest_add_data_func("hmp/none+2MB", g_strdup("none -m 2"), test_machine); 169*1e8a1faeSThomas Huth 170*1e8a1faeSThomas Huth return g_test_run(); 171*1e8a1faeSThomas Huth } 172