11e8a1faeSThomas Huth /* 21e8a1faeSThomas Huth * Test HMP commands. 31e8a1faeSThomas Huth * 41e8a1faeSThomas Huth * Copyright (c) 2017 Red Hat Inc. 51e8a1faeSThomas Huth * 61e8a1faeSThomas Huth * Author: 71e8a1faeSThomas Huth * Thomas Huth <thuth@redhat.com> 81e8a1faeSThomas Huth * 91e8a1faeSThomas Huth * This work is licensed under the terms of the GNU GPL, version 2 101e8a1faeSThomas Huth * or later. See the COPYING file in the top-level directory. 111e8a1faeSThomas Huth * 121e8a1faeSThomas Huth * This test calls some HMP commands for all machines that the current 131e8a1faeSThomas Huth * QEMU binary provides, to check whether they terminate successfully 141e8a1faeSThomas Huth * (i.e. do not crash QEMU). 151e8a1faeSThomas Huth */ 161e8a1faeSThomas Huth 171e8a1faeSThomas Huth #include "qemu/osdep.h" 18907b5105SMarc-André Lureau #include "libqtest.h" 191e8a1faeSThomas Huth 201e8a1faeSThomas Huth static int verbose; 211e8a1faeSThomas Huth 221e8a1faeSThomas Huth static const char *hmp_cmds[] = { 231e8a1faeSThomas Huth "announce_self", 241e8a1faeSThomas Huth "boot_set ndc", 251e8a1faeSThomas Huth "chardev-add null,id=testchardev1", 261e8a1faeSThomas Huth "chardev-send-break testchardev1", 271e8a1faeSThomas Huth "chardev-change testchardev1 ringbuf", 281e8a1faeSThomas Huth "chardev-remove testchardev1", 291e8a1faeSThomas Huth "commit all", 301e8a1faeSThomas Huth "cpu 0", 311e8a1faeSThomas Huth "device_add ?", 321e8a1faeSThomas Huth "device_add usb-mouse,id=mouse1", 331e8a1faeSThomas Huth "drive_add ignored format=help", 341e8a1faeSThomas Huth "mouse_button 7", 351e8a1faeSThomas Huth "mouse_move 10 10", 361e8a1faeSThomas Huth "mouse_button 0", 371e8a1faeSThomas Huth "device_del mouse1", 381e8a1faeSThomas Huth "dump-guest-memory /dev/null 0 4096", 391e8a1faeSThomas Huth "dump-guest-memory /dev/null", 401e8a1faeSThomas Huth "gdbserver", 411e8a1faeSThomas Huth "gva2gpa 0", 421e8a1faeSThomas Huth "hostfwd_add tcp::43210-:43210", 431e8a1faeSThomas Huth "hostfwd_remove tcp::43210-:43210", 441e8a1faeSThomas Huth "i /w 0", 451e8a1faeSThomas Huth "log all", 461e8a1faeSThomas Huth "log none", 471e8a1faeSThomas Huth "memsave 0 4096 \"/dev/null\"", 48cbde7be9SDaniel P. Berrangé "migrate_set_parameter xbzrle_cache_size 1", 49cbde7be9SDaniel P. Berrangé "migrate_set_parameter downtime_limit 1", 50cbde7be9SDaniel P. Berrangé "migrate_set_parameter max_bandwidth 1", 511e8a1faeSThomas Huth "netdev_add user,id=net1", 521e8a1faeSThomas Huth "set_link net1 off", 531e8a1faeSThomas Huth "set_link net1 on", 541e8a1faeSThomas Huth "netdev_del net1", 551e8a1faeSThomas Huth "nmi", 561e8a1faeSThomas Huth "o /w 0 0x1234", 571e8a1faeSThomas Huth "object_add memory-backend-ram,id=mem1,size=256M", 581e8a1faeSThomas Huth "object_del mem1", 59*e9ccfdd9SPeter Maydell "one-insn-per-tb on", 601e8a1faeSThomas Huth "pmemsave 0 4096 \"/dev/null\"", 611e8a1faeSThomas Huth "p $pc + 8", 621e8a1faeSThomas Huth "qom-list /", 631e8a1faeSThomas Huth "qom-set /machine initrd test", 6489cf4fe3SDr. David Alan Gilbert "qom-get /machine initrd", 651e8a1faeSThomas Huth "screendump /dev/null", 661e8a1faeSThomas Huth "sendkey x", 671e8a1faeSThomas Huth "singlestep on", 681e8a1faeSThomas Huth "wavcapture /dev/null", 691e8a1faeSThomas Huth "stopcapture 0", 701e8a1faeSThomas Huth "sum 0 512", 711e8a1faeSThomas Huth "x /8i 0x100", 721e8a1faeSThomas Huth "xp /16x 0", 731e8a1faeSThomas Huth NULL 741e8a1faeSThomas Huth }; 751e8a1faeSThomas Huth 761e8a1faeSThomas Huth /* Run through the list of pre-defined commands */ 771e8a1faeSThomas Huth static void test_commands(QTestState *qts) 781e8a1faeSThomas Huth { 791e8a1faeSThomas Huth char *response; 801e8a1faeSThomas Huth int i; 811e8a1faeSThomas Huth 821e8a1faeSThomas Huth for (i = 0; hmp_cmds[i] != NULL; i++) { 831e8a1faeSThomas Huth response = qtest_hmp(qts, "%s", hmp_cmds[i]); 841e8a1faeSThomas Huth if (verbose) { 851e8a1faeSThomas Huth fprintf(stderr, 861e8a1faeSThomas Huth "\texecute HMP command: %s\n" 871e8a1faeSThomas Huth "\tresult : %s\n", 881e8a1faeSThomas Huth hmp_cmds[i], response); 891e8a1faeSThomas Huth } 901e8a1faeSThomas Huth g_free(response); 911e8a1faeSThomas Huth } 921e8a1faeSThomas Huth 931e8a1faeSThomas Huth } 941e8a1faeSThomas Huth 951e8a1faeSThomas Huth /* Run through all info commands and call them blindly (without arguments) */ 961e8a1faeSThomas Huth static void test_info_commands(QTestState *qts) 971e8a1faeSThomas Huth { 981e8a1faeSThomas Huth char *resp, *info, *info_buf, *endp; 991e8a1faeSThomas Huth 1001e8a1faeSThomas Huth info_buf = info = qtest_hmp(qts, "help info"); 1011e8a1faeSThomas Huth 1021e8a1faeSThomas Huth while (*info) { 1031e8a1faeSThomas Huth /* Extract the info command, ignore parameters and description */ 1041e8a1faeSThomas Huth g_assert(strncmp(info, "info ", 5) == 0); 1051e8a1faeSThomas Huth endp = strchr(&info[5], ' '); 1061e8a1faeSThomas Huth g_assert(endp != NULL); 1071e8a1faeSThomas Huth *endp = '\0'; 1081e8a1faeSThomas Huth /* Now run the info command */ 1091e8a1faeSThomas Huth if (verbose) { 1101e8a1faeSThomas Huth fprintf(stderr, "\t%s\n", info); 1111e8a1faeSThomas Huth } 1121e8a1faeSThomas Huth resp = qtest_hmp(qts, "%s", info); 1131e8a1faeSThomas Huth g_free(resp); 1141e8a1faeSThomas Huth /* And move forward to the next line */ 1151e8a1faeSThomas Huth info = strchr(endp + 1, '\n'); 1161e8a1faeSThomas Huth if (!info) { 1171e8a1faeSThomas Huth break; 1181e8a1faeSThomas Huth } 1191e8a1faeSThomas Huth info += 1; 1201e8a1faeSThomas Huth } 1211e8a1faeSThomas Huth 1221e8a1faeSThomas Huth g_free(info_buf); 1231e8a1faeSThomas Huth } 1241e8a1faeSThomas Huth 1251e8a1faeSThomas Huth static void test_machine(gconstpointer data) 1261e8a1faeSThomas Huth { 1271e8a1faeSThomas Huth const char *machine = data; 1281e8a1faeSThomas Huth char *args; 1291e8a1faeSThomas Huth QTestState *qts; 1301e8a1faeSThomas Huth 1311e8a1faeSThomas Huth args = g_strdup_printf("-S -M %s", machine); 1321e8a1faeSThomas Huth qts = qtest_init(args); 1331e8a1faeSThomas Huth 1341e8a1faeSThomas Huth test_info_commands(qts); 1351e8a1faeSThomas Huth test_commands(qts); 1361e8a1faeSThomas Huth 1371e8a1faeSThomas Huth qtest_quit(qts); 1381e8a1faeSThomas Huth g_free(args); 1391e8a1faeSThomas Huth g_free((void *)data); 1401e8a1faeSThomas Huth } 1411e8a1faeSThomas Huth 1421e8a1faeSThomas Huth static void add_machine_test_case(const char *mname) 1431e8a1faeSThomas Huth { 1441e8a1faeSThomas Huth char *path; 1451e8a1faeSThomas Huth 1461e8a1faeSThomas Huth path = g_strdup_printf("hmp/%s", mname); 1471e8a1faeSThomas Huth qtest_add_data_func(path, g_strdup(mname), test_machine); 1481e8a1faeSThomas Huth g_free(path); 1491e8a1faeSThomas Huth } 1501e8a1faeSThomas Huth 1511e8a1faeSThomas Huth int main(int argc, char **argv) 1521e8a1faeSThomas Huth { 1531e8a1faeSThomas Huth char *v_env = getenv("V"); 1541e8a1faeSThomas Huth 1556eb71c6aSThomas Huth if (v_env && atoi(v_env) >= 2) { 1561e8a1faeSThomas Huth verbose = true; 1571e8a1faeSThomas Huth } 1581e8a1faeSThomas Huth 1591e8a1faeSThomas Huth g_test_init(&argc, &argv, NULL); 1601e8a1faeSThomas Huth 1611e8a1faeSThomas Huth qtest_cb_for_every_machine(add_machine_test_case, g_test_quick()); 1621e8a1faeSThomas Huth 1631e8a1faeSThomas Huth /* as none machine has no memory by default, add a test case with memory */ 1641e8a1faeSThomas Huth qtest_add_data_func("hmp/none+2MB", g_strdup("none -m 2"), test_machine); 1651e8a1faeSThomas Huth 1661e8a1faeSThomas Huth return g_test_run(); 1671e8a1faeSThomas Huth } 168