HMP pull, with tcg fix
-----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJZAKbSAAoJEAUWMx68W/3ntPQP/0a5TgBu2e7qbvch6+vIhwXH mucetctihCq371rTOd2hpMTiy7eL+tC8Yi3yfVCKIrXKszw5WOxZpvxQd4hfdCJ8 RtMHGzZ9NGkUA8wtnX9BEm9Rput1qfAW6qebeRmxmbUb64DEAJTSPDB2yOgqdSY+ 0AepiIR5hygsLAbqOiE9gI8E7HyhsKQGAvl33RcQlkSTy9PqvZFEvh3Hg6FdlPOH +jvlgVg4zqsxIDMQJSaqu3wyrp001I2UG1PHfFyjNqcr4ztHJ7HTzULKKA5VJI8s tCDesA3wKKKFeMK3saTEE4XkofM4Ta0xTFWRXY0Waq5GfaF7ANT7E98Ze1H+XR6B yub4I1+T7QyvI/0hzd4qsGIKLzA7o9pKZYTYOIfQMDdzvVgk3+CHO8ntty4IkKRQ qof/iqCAZGTFW6YJpFSY3maVP9tFMXyx8JVWf1q9omEk4Ll26SJfhy3VqJpUiuVi hVj0bhVMuCYB2KA3JCdILEq1Y+dVkqx847aNKKeDl6aRhSDM3m/P1Bl676RrpaJE t7+Mq58wICxhDt2lNaAsbU6tw5iNrpOaKS5e4s7GDDNF5IiNqGhdZh7ERsGev6RC ibSFWgiwQyLLp4trIA8uZpFGL+OMcXlsKmfGGzmrVNJhuTdwWRPPxwjcJlpyR/Uz ET6tqlJ6DqUaAG/5RUAM =8UZd -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/dgilbert/tags/pull-hmp-20170426' into staging HMP pull, with tcg fix # gpg: Signature made Wed 26 Apr 2017 14:55:30 BST # gpg: using RSA key 0x0516331EBC5BFDE7 # gpg: Good signature from "Dr. David Alan Gilbert (RH2) <dgilbert@redhat.com>" # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 45F5 C71B 4A0C B7FB 977A 9FA9 0516 331E BC5B FDE7 * remotes/dgilbert/tags/pull-hmp-20170426: tests: Add a tester for HMP commands libqtest: Add a generic function to run a callback function for every machine libqtest: Ignore QMP events when parsing the response for HMP commands monitor: Check whether TCG is enabled before running the "info jit" code hmp: gpa2hva and gpa2hpa hostaddr command Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
41c7c7ef29
@ -523,6 +523,38 @@ Dump 80 16 bit values at the start of the video memory.
|
||||
0x000b8090: 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720
|
||||
@end smallexample
|
||||
@end itemize
|
||||
ETEXI
|
||||
|
||||
{
|
||||
.name = "gpa2hva",
|
||||
.args_type = "addr:l",
|
||||
.params = "addr",
|
||||
.help = "print the host virtual address corresponding to a guest physical address",
|
||||
.cmd = hmp_gpa2hva,
|
||||
},
|
||||
|
||||
STEXI
|
||||
@item gpa2hva @var{addr}
|
||||
@findex gpa2hva
|
||||
Print the host virtual address at which the guest's physical address @var{addr}
|
||||
is mapped.
|
||||
ETEXI
|
||||
|
||||
#ifdef CONFIG_LINUX
|
||||
{
|
||||
.name = "gpa2hpa",
|
||||
.args_type = "addr:l",
|
||||
.params = "addr",
|
||||
.help = "print the host physical address corresponding to a guest physical address",
|
||||
.cmd = hmp_gpa2hpa,
|
||||
},
|
||||
#endif
|
||||
|
||||
STEXI
|
||||
@item gpa2hpa @var{addr}
|
||||
@findex gpa2hpa
|
||||
Print the host physical address at which the guest's physical address @var{addr}
|
||||
is mapped.
|
||||
ETEXI
|
||||
|
||||
{
|
||||
|
106
monitor.c
106
monitor.c
@ -1086,6 +1086,11 @@ static void hmp_info_registers(Monitor *mon, const QDict *qdict)
|
||||
|
||||
static void hmp_info_jit(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
if (!tcg_enabled()) {
|
||||
error_report("JIT information is only available with accel=tcg");
|
||||
return;
|
||||
}
|
||||
|
||||
dump_exec_info((FILE *)mon, monitor_fprintf);
|
||||
dump_drift_info((FILE *)mon, monitor_fprintf);
|
||||
}
|
||||
@ -1421,6 +1426,107 @@ static void hmp_physical_memory_dump(Monitor *mon, const QDict *qdict)
|
||||
memory_dump(mon, count, format, size, addr, 1);
|
||||
}
|
||||
|
||||
static void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, Error **errp)
|
||||
{
|
||||
MemoryRegionSection mrs = memory_region_find(get_system_memory(),
|
||||
addr, 1);
|
||||
|
||||
if (!mrs.mr) {
|
||||
error_setg(errp, "No memory is mapped at address 0x%" HWADDR_PRIx, addr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!memory_region_is_ram(mrs.mr) && !memory_region_is_romd(mrs.mr)) {
|
||||
error_setg(errp, "Memory at address 0x%" HWADDR_PRIx "is not RAM", addr);
|
||||
memory_region_unref(mrs.mr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*p_mr = mrs.mr;
|
||||
return qemu_map_ram_ptr(mrs.mr->ram_block, mrs.offset_within_region);
|
||||
}
|
||||
|
||||
static void hmp_gpa2hva(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
hwaddr addr = qdict_get_int(qdict, "addr");
|
||||
Error *local_err = NULL;
|
||||
MemoryRegion *mr = NULL;
|
||||
void *ptr;
|
||||
|
||||
ptr = gpa2hva(&mr, addr, &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
monitor_printf(mon, "Host virtual address for 0x%" HWADDR_PRIx
|
||||
" (%s) is %p\n",
|
||||
addr, mr->name, ptr);
|
||||
|
||||
memory_region_unref(mr);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LINUX
|
||||
static uint64_t vtop(void *ptr, Error **errp)
|
||||
{
|
||||
uint64_t pinfo;
|
||||
uint64_t ret = -1;
|
||||
uintptr_t addr = (uintptr_t) ptr;
|
||||
uintptr_t pagesize = getpagesize();
|
||||
off_t offset = addr / pagesize * sizeof(pinfo);
|
||||
int fd;
|
||||
|
||||
fd = open("/proc/self/pagemap", O_RDONLY);
|
||||
if (fd == -1) {
|
||||
error_setg_errno(errp, errno, "Cannot open /proc/self/pagemap");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Force copy-on-write if necessary. */
|
||||
atomic_add((uint8_t *)ptr, 0);
|
||||
|
||||
if (pread(fd, &pinfo, sizeof(pinfo), offset) != sizeof(pinfo)) {
|
||||
error_setg_errno(errp, errno, "Cannot read pagemap");
|
||||
goto out;
|
||||
}
|
||||
if ((pinfo & (1ull << 63)) == 0) {
|
||||
error_setg(errp, "Page not present");
|
||||
goto out;
|
||||
}
|
||||
ret = ((pinfo & 0x007fffffffffffffull) * pagesize) | (addr & (pagesize - 1));
|
||||
|
||||
out:
|
||||
close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void hmp_gpa2hpa(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
hwaddr addr = qdict_get_int(qdict, "addr");
|
||||
Error *local_err = NULL;
|
||||
MemoryRegion *mr = NULL;
|
||||
void *ptr;
|
||||
uint64_t physaddr;
|
||||
|
||||
ptr = gpa2hva(&mr, addr, &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
physaddr = vtop(ptr, &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
} else {
|
||||
monitor_printf(mon, "Host physical address for 0x%" HWADDR_PRIx
|
||||
" (%s) is 0x%" PRIx64 "\n",
|
||||
addr, mr->name, (uint64_t) physaddr);
|
||||
}
|
||||
|
||||
memory_region_unref(mr);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void do_print(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
int format = qdict_get_int(qdict, "format");
|
||||
|
@ -331,6 +331,7 @@ check-qtest-xtensaeb-y = $(check-qtest-xtensa-y)
|
||||
check-qtest-s390x-y = tests/boot-serial-test$(EXESUF)
|
||||
|
||||
check-qtest-generic-y += tests/qom-test$(EXESUF)
|
||||
check-qtest-generic-y += tests/test-hmp$(EXESUF)
|
||||
|
||||
qapi-schema += alternate-any.json
|
||||
qapi-schema += alternate-array.json
|
||||
@ -720,6 +721,7 @@ tests/tpci200-test$(EXESUF): tests/tpci200-test.o
|
||||
tests/display-vga-test$(EXESUF): tests/display-vga-test.o
|
||||
tests/ipoctal232-test$(EXESUF): tests/ipoctal232-test.o
|
||||
tests/qom-test$(EXESUF): tests/qom-test.o
|
||||
tests/test-hmp$(EXESUF): tests/test-hmp.o
|
||||
tests/drive_del-test$(EXESUF): tests/drive_del-test.o $(libqos-pc-obj-y)
|
||||
tests/qdev-monitor-test$(EXESUF): tests/qdev-monitor-test.o $(libqos-pc-obj-y)
|
||||
tests/nvme-test$(EXESUF): tests/nvme-test.o
|
||||
|
@ -588,6 +588,12 @@ char *qtest_hmpv(QTestState *s, const char *fmt, va_list ap)
|
||||
" 'arguments': {'command-line': %s}}",
|
||||
cmd);
|
||||
ret = g_strdup(qdict_get_try_str(resp, "return"));
|
||||
while (ret == NULL && qdict_get_try_str(resp, "event")) {
|
||||
/* Ignore asynchronous QMP events */
|
||||
QDECREF(resp);
|
||||
resp = qtest_qmp_receive(s);
|
||||
ret = g_strdup(qdict_get_try_str(resp, "return"));
|
||||
}
|
||||
g_assert(ret);
|
||||
QDECREF(resp);
|
||||
g_free(cmd);
|
||||
@ -940,3 +946,33 @@ bool qtest_big_endian(QTestState *s)
|
||||
{
|
||||
return s->big_endian;
|
||||
}
|
||||
|
||||
void qtest_cb_for_every_machine(void (*cb)(const char *machine))
|
||||
{
|
||||
QDict *response, *minfo;
|
||||
QList *list;
|
||||
const QListEntry *p;
|
||||
QObject *qobj;
|
||||
QString *qstr;
|
||||
const char *mname;
|
||||
|
||||
qtest_start("-machine none");
|
||||
response = qmp("{ 'execute': 'query-machines' }");
|
||||
g_assert(response);
|
||||
list = qdict_get_qlist(response, "return");
|
||||
g_assert(list);
|
||||
|
||||
for (p = qlist_first(list); p; p = qlist_next(p)) {
|
||||
minfo = qobject_to_qdict(qlist_entry_obj(p));
|
||||
g_assert(minfo);
|
||||
qobj = qdict_get(minfo, "name");
|
||||
g_assert(qobj);
|
||||
qstr = qobject_to_qstring(qobj);
|
||||
g_assert(qstr);
|
||||
mname = qstring_get_str(qstr);
|
||||
cb(mname);
|
||||
}
|
||||
|
||||
qtest_end();
|
||||
QDECREF(response);
|
||||
}
|
||||
|
@ -132,11 +132,12 @@ void qtest_qmp_eventwait(QTestState *s, const char *event);
|
||||
QDict *qtest_qmp_eventwait_ref(QTestState *s, const char *event);
|
||||
|
||||
/**
|
||||
* qtest_hmpv:
|
||||
* qtest_hmp:
|
||||
* @s: #QTestState instance to operate on.
|
||||
* @fmt...: HMP command to send to QEMU
|
||||
*
|
||||
* Send HMP command to QEMU via QMP's human-monitor-command.
|
||||
* QMP events are discarded.
|
||||
*
|
||||
* Returns: the command's output. The caller should g_free() it.
|
||||
*/
|
||||
@ -149,6 +150,7 @@ char *qtest_hmp(QTestState *s, const char *fmt, ...);
|
||||
* @ap: HMP command arguments
|
||||
*
|
||||
* Send HMP command to QEMU via QMP's human-monitor-command.
|
||||
* QMP events are discarded.
|
||||
*
|
||||
* Returns: the command's output. The caller should g_free() it.
|
||||
*/
|
||||
@ -917,4 +919,12 @@ void qmp_fd_send(int fd, const char *fmt, ...);
|
||||
QDict *qmp_fdv(int fd, const char *fmt, va_list ap);
|
||||
QDict *qmp_fd(int fd, const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* qtest_cb_for_every_machine:
|
||||
* @cb: Pointer to the callback function
|
||||
*
|
||||
* Call a callback function for every name of all available machines.
|
||||
*/
|
||||
void qtest_cb_for_every_machine(void (*cb)(const char *machine));
|
||||
|
||||
#endif
|
||||
|
@ -79,69 +79,46 @@ static void test_data_free(gpointer data)
|
||||
g_free(pc);
|
||||
}
|
||||
|
||||
static void add_pc_test_cases(void)
|
||||
static void add_pc_test_case(const char *mname)
|
||||
{
|
||||
QDict *response, *minfo;
|
||||
QList *list;
|
||||
const QListEntry *p;
|
||||
QObject *qobj;
|
||||
QString *qstr;
|
||||
const char *mname;
|
||||
char *path;
|
||||
PCTestData *data;
|
||||
|
||||
qtest_start("-machine none");
|
||||
response = qmp("{ 'execute': 'query-machines' }");
|
||||
g_assert(response);
|
||||
list = qdict_get_qlist(response, "return");
|
||||
g_assert(list);
|
||||
|
||||
for (p = qlist_first(list); p; p = qlist_next(p)) {
|
||||
minfo = qobject_to_qdict(qlist_entry_obj(p));
|
||||
g_assert(minfo);
|
||||
qobj = qdict_get(minfo, "name");
|
||||
g_assert(qobj);
|
||||
qstr = qobject_to_qstring(qobj);
|
||||
g_assert(qstr);
|
||||
mname = qstring_get_str(qstr);
|
||||
if (!g_str_has_prefix(mname, "pc-")) {
|
||||
continue;
|
||||
}
|
||||
data = g_malloc(sizeof(PCTestData));
|
||||
data->machine = g_strdup(mname);
|
||||
data->cpu_model = "Haswell"; /* 1.3+ theoretically */
|
||||
data->sockets = 1;
|
||||
data->cores = 3;
|
||||
data->threads = 2;
|
||||
data->maxcpus = data->sockets * data->cores * data->threads * 2;
|
||||
if (g_str_has_suffix(mname, "-1.4") ||
|
||||
(strcmp(mname, "pc-1.3") == 0) ||
|
||||
(strcmp(mname, "pc-1.2") == 0) ||
|
||||
(strcmp(mname, "pc-1.1") == 0) ||
|
||||
(strcmp(mname, "pc-1.0") == 0) ||
|
||||
(strcmp(mname, "pc-0.15") == 0) ||
|
||||
(strcmp(mname, "pc-0.14") == 0) ||
|
||||
(strcmp(mname, "pc-0.13") == 0) ||
|
||||
(strcmp(mname, "pc-0.12") == 0) ||
|
||||
(strcmp(mname, "pc-0.11") == 0) ||
|
||||
(strcmp(mname, "pc-0.10") == 0)) {
|
||||
path = g_strdup_printf("cpu/%s/init/%ux%ux%u&maxcpus=%u",
|
||||
mname, data->sockets, data->cores,
|
||||
data->threads, data->maxcpus);
|
||||
qtest_add_data_func_full(path, data, test_pc_without_cpu_add,
|
||||
test_data_free);
|
||||
g_free(path);
|
||||
} else {
|
||||
path = g_strdup_printf("cpu/%s/add/%ux%ux%u&maxcpus=%u",
|
||||
mname, data->sockets, data->cores,
|
||||
data->threads, data->maxcpus);
|
||||
qtest_add_data_func_full(path, data, test_pc_with_cpu_add,
|
||||
test_data_free);
|
||||
g_free(path);
|
||||
}
|
||||
if (!g_str_has_prefix(mname, "pc-")) {
|
||||
return;
|
||||
}
|
||||
data = g_malloc(sizeof(PCTestData));
|
||||
data->machine = g_strdup(mname);
|
||||
data->cpu_model = "Haswell"; /* 1.3+ theoretically */
|
||||
data->sockets = 1;
|
||||
data->cores = 3;
|
||||
data->threads = 2;
|
||||
data->maxcpus = data->sockets * data->cores * data->threads * 2;
|
||||
if (g_str_has_suffix(mname, "-1.4") ||
|
||||
(strcmp(mname, "pc-1.3") == 0) ||
|
||||
(strcmp(mname, "pc-1.2") == 0) ||
|
||||
(strcmp(mname, "pc-1.1") == 0) ||
|
||||
(strcmp(mname, "pc-1.0") == 0) ||
|
||||
(strcmp(mname, "pc-0.15") == 0) ||
|
||||
(strcmp(mname, "pc-0.14") == 0) ||
|
||||
(strcmp(mname, "pc-0.13") == 0) ||
|
||||
(strcmp(mname, "pc-0.12") == 0) ||
|
||||
(strcmp(mname, "pc-0.11") == 0) ||
|
||||
(strcmp(mname, "pc-0.10") == 0)) {
|
||||
path = g_strdup_printf("cpu/%s/init/%ux%ux%u&maxcpus=%u",
|
||||
mname, data->sockets, data->cores,
|
||||
data->threads, data->maxcpus);
|
||||
qtest_add_data_func_full(path, data, test_pc_without_cpu_add,
|
||||
test_data_free);
|
||||
g_free(path);
|
||||
} else {
|
||||
path = g_strdup_printf("cpu/%s/add/%ux%ux%u&maxcpus=%u",
|
||||
mname, data->sockets, data->cores,
|
||||
data->threads, data->maxcpus);
|
||||
qtest_add_data_func_full(path, data, test_pc_with_cpu_add,
|
||||
test_data_free);
|
||||
g_free(path);
|
||||
}
|
||||
QDECREF(response);
|
||||
qtest_end();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
@ -151,7 +128,7 @@ int main(int argc, char **argv)
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
|
||||
add_pc_test_cases();
|
||||
qtest_cb_for_every_machine(add_pc_test_case);
|
||||
}
|
||||
|
||||
return g_test_run();
|
||||
|
@ -107,46 +107,22 @@ static void test_machine(gconstpointer data)
|
||||
g_free((void *)machine);
|
||||
}
|
||||
|
||||
static void add_machine_test_cases(void)
|
||||
static void add_machine_test_case(const char *mname)
|
||||
{
|
||||
const char *arch = qtest_get_arch();
|
||||
QDict *response, *minfo;
|
||||
QList *list;
|
||||
const QListEntry *p;
|
||||
QObject *qobj;
|
||||
QString *qstr;
|
||||
const char *mname;
|
||||
|
||||
qtest_start("-machine none");
|
||||
response = qmp("{ 'execute': 'query-machines' }");
|
||||
g_assert(response);
|
||||
list = qdict_get_qlist(response, "return");
|
||||
g_assert(list);
|
||||
|
||||
for (p = qlist_first(list); p; p = qlist_next(p)) {
|
||||
minfo = qobject_to_qdict(qlist_entry_obj(p));
|
||||
g_assert(minfo);
|
||||
qobj = qdict_get(minfo, "name");
|
||||
g_assert(qobj);
|
||||
qstr = qobject_to_qstring(qobj);
|
||||
g_assert(qstr);
|
||||
mname = qstring_get_str(qstr);
|
||||
if (!is_blacklisted(arch, mname)) {
|
||||
char *path = g_strdup_printf("qom/%s", mname);
|
||||
qtest_add_data_func(path, g_strdup(mname), test_machine);
|
||||
g_free(path);
|
||||
}
|
||||
if (!is_blacklisted(arch, mname)) {
|
||||
char *path = g_strdup_printf("qom/%s", mname);
|
||||
qtest_add_data_func(path, g_strdup(mname), test_machine);
|
||||
g_free(path);
|
||||
}
|
||||
|
||||
qtest_end();
|
||||
QDECREF(response);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
add_machine_test_cases();
|
||||
qtest_cb_for_every_machine(add_machine_test_case);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
|
161
tests/test-hmp.c
Normal file
161
tests/test-hmp.c
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Test HMP commands.
|
||||
*
|
||||
* Copyright (c) 2017 Red Hat Inc.
|
||||
*
|
||||
* Author:
|
||||
* Thomas Huth <thuth@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2
|
||||
* or later. See the COPYING file in the top-level directory.
|
||||
*
|
||||
* This test calls some HMP commands for all machines that the current
|
||||
* QEMU binary provides, to check whether they terminate successfully
|
||||
* (i.e. do not crash QEMU).
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "libqtest.h"
|
||||
|
||||
static int verbose;
|
||||
|
||||
static const char *hmp_cmds[] = {
|
||||
"boot_set ndc",
|
||||
"chardev-add null,id=testchardev1",
|
||||
"chardev-remove testchardev1",
|
||||
"commit all",
|
||||
"cpu-add 1",
|
||||
"cpu 0",
|
||||
"device_add ?",
|
||||
"device_add usb-mouse,id=mouse1",
|
||||
"mouse_button 7",
|
||||
"mouse_move 10 10",
|
||||
"mouse_button 0",
|
||||
"device_del mouse1",
|
||||
"dump-guest-memory /dev/null 0 4096",
|
||||
"gdbserver",
|
||||
"host_net_add user id=net0",
|
||||
"hostfwd_add tcp::43210-:43210",
|
||||
"hostfwd_remove tcp::43210-:43210",
|
||||
"host_net_remove 0 net0",
|
||||
"i /w 0",
|
||||
"log all",
|
||||
"log none",
|
||||
"memsave 0 4096 \"/dev/null\"",
|
||||
"migrate_set_cache_size 1",
|
||||
"migrate_set_downtime 1",
|
||||
"migrate_set_speed 1",
|
||||
"netdev_add user,id=net1",
|
||||
"set_link net1 off",
|
||||
"set_link net1 on",
|
||||
"netdev_del net1",
|
||||
"nmi",
|
||||
"o /w 0 0x1234",
|
||||
"object_add memory-backend-ram,id=mem1,size=256M",
|
||||
"object_del mem1",
|
||||
"pmemsave 0 4096 \"/dev/null\"",
|
||||
"p $pc + 8",
|
||||
"qom-list /",
|
||||
"qom-set /machine initrd test",
|
||||
"screendump /dev/null",
|
||||
"sendkey x",
|
||||
"singlestep on",
|
||||
"wavcapture /dev/null",
|
||||
"stopcapture 0",
|
||||
"sum 0 512",
|
||||
"x /8i 0x100",
|
||||
"xp /16x 0",
|
||||
NULL
|
||||
};
|
||||
|
||||
/* Run through the list of pre-defined commands */
|
||||
static void test_commands(void)
|
||||
{
|
||||
char *response;
|
||||
int i;
|
||||
|
||||
for (i = 0; hmp_cmds[i] != NULL; i++) {
|
||||
if (verbose) {
|
||||
fprintf(stderr, "\t%s\n", hmp_cmds[i]);
|
||||
}
|
||||
response = hmp(hmp_cmds[i]);
|
||||
g_free(response);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Run through all info commands and call them blindly (without arguments) */
|
||||
static void test_info_commands(void)
|
||||
{
|
||||
char *resp, *info, *info_buf, *endp;
|
||||
|
||||
info_buf = info = hmp("help info");
|
||||
|
||||
while (*info) {
|
||||
/* Extract the info command, ignore parameters and description */
|
||||
g_assert(strncmp(info, "info ", 5) == 0);
|
||||
endp = strchr(&info[5], ' ');
|
||||
g_assert(endp != NULL);
|
||||
*endp = '\0';
|
||||
/* Now run the info command */
|
||||
if (verbose) {
|
||||
fprintf(stderr, "\t%s\n", info);
|
||||
}
|
||||
resp = hmp(info);
|
||||
g_free(resp);
|
||||
/* And move forward to the next line */
|
||||
info = strchr(endp + 1, '\n');
|
||||
if (!info) {
|
||||
break;
|
||||
}
|
||||
info += 1;
|
||||
}
|
||||
|
||||
g_free(info_buf);
|
||||
}
|
||||
|
||||
static void test_machine(gconstpointer data)
|
||||
{
|
||||
const char *machine = data;
|
||||
char *args;
|
||||
|
||||
args = g_strdup_printf("-S -M %s", machine);
|
||||
qtest_start(args);
|
||||
|
||||
test_info_commands();
|
||||
test_commands();
|
||||
|
||||
qtest_end();
|
||||
g_free(args);
|
||||
g_free((void *)data);
|
||||
}
|
||||
|
||||
static void add_machine_test_case(const char *mname)
|
||||
{
|
||||
char *path;
|
||||
|
||||
/* Ignore blacklisted machines that have known problems */
|
||||
if (!strcmp("puv3", mname) || !strcmp("tricore_testboard", mname) ||
|
||||
!strcmp("xenfv", mname) || !strcmp("xenpv", mname)) {
|
||||
return;
|
||||
}
|
||||
|
||||
path = g_strdup_printf("hmp/%s", mname);
|
||||
qtest_add_data_func(path, g_strdup(mname), test_machine);
|
||||
g_free(path);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *v_env = getenv("V");
|
||||
|
||||
if (v_env && *v_env >= '2') {
|
||||
verbose = true;
|
||||
}
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
qtest_cb_for_every_machine(add_machine_test_case);
|
||||
|
||||
return g_test_run();
|
||||
}
|
Loading…
Reference in New Issue
Block a user