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