From: Kevin Wolf <kwolf@redhat.com>
To: qemu-devel@nongnu.org
Cc: kwolf@redhat.com
Subject: [Qemu-devel] [PATCH 1/2] qtest: Add function to send QMP commands
Date: Tue, 8 May 2012 17:51:43 +0200 [thread overview]
Message-ID: <1336492304-26256-2-git-send-email-kwolf@redhat.com> (raw)
In-Reply-To: <1336492304-26256-1-git-send-email-kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
tests/libqtest.c | 123 ++++++++++++++++++++++++++++++++++++++++++------------
tests/libqtest.h | 17 +++++++
2 files changed, 113 insertions(+), 27 deletions(-)
diff --git a/tests/libqtest.c b/tests/libqtest.c
index 295c6d4..6d333ef 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -36,6 +36,7 @@ QTestState *global_qtest;
struct QTestState
{
int fd;
+ int qmp_fd;
bool irq_level[MAX_IRQ];
GString *rx;
gchar *pid_file;
@@ -45,48 +46,76 @@ struct QTestState
g_assert_cmpint(ret, !=, -1); \
} while (0)
+static int init_socket(const char *socket_path)
+{
+ struct sockaddr_un addr;
+ int sock;
+ int ret;
+
+ sock = socket(PF_UNIX, SOCK_STREAM, 0);
+ g_assert_no_errno(sock);
+
+ addr.sun_family = AF_UNIX;
+ snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", socket_path);
+ qemu_set_cloexec(sock);
+
+ do {
+ ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
+ } while (ret == -1 && errno == EINTR);
+ g_assert_no_errno(ret);
+ listen(sock, 1);
+
+ return sock;
+}
+
+static int socket_accept(int sock)
+{
+ struct sockaddr_un addr;
+ socklen_t addrlen;
+ int ret;
+
+ do {
+ ret = accept(sock, (struct sockaddr *)&addr, &addrlen);
+ } while (ret == -1 && errno == EINTR);
+ g_assert_no_errno(ret);
+ close(sock);
+
+ return ret;
+}
+
QTestState *qtest_init(const char *extra_args)
{
QTestState *s;
- struct sockaddr_un addr;
- int sock, ret, i;
+ int sock, qmpsock, ret, i;
gchar *socket_path;
+ gchar *qmp_socket_path;
gchar *pid_file;
gchar *command;
const char *qemu_binary;
pid_t pid;
- socklen_t addrlen;
qemu_binary = getenv("QTEST_QEMU_BINARY");
g_assert(qemu_binary != NULL);
socket_path = g_strdup_printf("/tmp/qtest-%d.sock", getpid());
+ qmp_socket_path = g_strdup_printf("/tmp/qtest-%d.qmp", getpid());
pid_file = g_strdup_printf("/tmp/qtest-%d.pid", getpid());
s = g_malloc(sizeof(*s));
- sock = socket(PF_UNIX, SOCK_STREAM, 0);
- g_assert_no_errno(sock);
-
- addr.sun_family = AF_UNIX;
- snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", socket_path);
- qemu_set_cloexec(sock);
-
- do {
- ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
- } while (ret == -1 && errno == EINTR);
- g_assert_no_errno(ret);
- listen(sock, 1);
+ sock = init_socket(socket_path);
+ qmpsock = init_socket(qmp_socket_path);
pid = fork();
if (pid == 0) {
command = g_strdup_printf("%s "
"-qtest unix:%s,nowait "
"-qtest-log /dev/null "
+ "-qmp unix:%s,nowait "
"-pidfile %s "
"-machine accel=qtest "
"%s", qemu_binary, socket_path,
- pid_file,
+ qmp_socket_path, pid_file,
extra_args ?: "");
ret = system(command);
@@ -94,13 +123,9 @@ QTestState *qtest_init(const char *extra_args)
g_free(command);
}
- do {
- ret = accept(sock, (struct sockaddr *)&addr, &addrlen);
- } while (ret == -1 && errno == EINTR);
- g_assert_no_errno(ret);
- close(sock);
+ s->fd = socket_accept(sock);
+ s->qmp_fd = socket_accept(qmpsock);
- s->fd = ret;
s->rx = g_string_new("");
s->pid_file = pid_file;
for (i = 0; i < MAX_IRQ; i++) {
@@ -108,6 +133,11 @@ QTestState *qtest_init(const char *extra_args)
}
g_free(socket_path);
+ g_free(qmp_socket_path);
+
+ /* Read the QMP greeting and then do the handshake */
+ qtest_qmp(s, "");
+ qtest_qmp(s, "{ 'execute': 'qmp_capabilities' }");
return s;
}
@@ -131,22 +161,19 @@ void qtest_quit(QTestState *s)
}
}
-static void GCC_FMT_ATTR(2, 3) qtest_sendf(QTestState *s, const char *fmt, ...)
+static void socket_sendf(int fd, const char *fmt, va_list ap)
{
- va_list ap;
gchar *str;
size_t size, offset;
- va_start(ap, fmt);
str = g_strdup_vprintf(fmt, ap);
- va_end(ap);
size = strlen(str);
offset = 0;
while (offset < size) {
ssize_t len;
- len = write(s->fd, str + offset, size - offset);
+ len = write(fd, str + offset, size - offset);
if (len == -1 && errno == EINTR) {
continue;
}
@@ -158,6 +185,15 @@ static void GCC_FMT_ATTR(2, 3) qtest_sendf(QTestState *s, const char *fmt, ...)
}
}
+static void GCC_FMT_ATTR(2, 3) qtest_sendf(QTestState *s, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ socket_sendf(s->fd, fmt, ap);
+ va_end(ap);
+}
+
static GString *qtest_recv_line(QTestState *s)
{
GString *line;
@@ -233,6 +269,39 @@ redo:
return words;
}
+void qtest_qmp(QTestState *s, const char *fmt, ...)
+{
+ va_list ap;
+ bool has_reply = false;
+ int nesting = 0;
+
+ /* Send QMP request */
+ va_start(ap, fmt);
+ socket_sendf(s->qmp_fd, fmt, ap);
+ va_end(ap);
+
+ /* Receive reply */
+ while (!has_reply || nesting > 0) {
+ ssize_t len;
+ char c;
+
+ len = read(s->qmp_fd, &c, 1);
+ if (len == -1 && errno == EINTR) {
+ continue;
+ }
+
+ switch (c) {
+ case '{':
+ nesting++;
+ has_reply = true;
+ break;
+ case '}':
+ nesting--;
+ break;
+ }
+ }
+}
+
const char *qtest_get_arch(void)
{
const char *qemu = getenv("QTEST_QEMU_BINARY");
diff --git a/tests/libqtest.h b/tests/libqtest.h
index 2ca85a9..c8ade85 100644
--- a/tests/libqtest.h
+++ b/tests/libqtest.h
@@ -38,6 +38,15 @@ QTestState *qtest_init(const char *extra_args);
void qtest_quit(QTestState *s);
/**
+ * qtest_qmp:
+ * @s: QTestState instance to operate on.
+ * @fmt...: QMP message to send to qemu
+ *
+ * Sends a QMP message to QEMU
+ */
+void qtest_qmp(QTestState *s, const char *fmt, ...);
+
+/**
* qtest_get_irq:
* @s: QTestState instance to operate on.
* @num: Interrupt to observe.
@@ -207,6 +216,14 @@ void qtest_add_func(const char *str, void (*fn));
)
/**
+ * qmp:
+ * @fmt...: QMP message to send to qemu
+ *
+ * Sends a QMP message to QEMU
+ */
+#define qmp(fmt, ...) qtest_qmp(global_qtest, fmt, ## __VA_ARGS__)
+
+/**
* get_irq:
* @num: Interrupt to observe.
*
--
1.7.6.5
next prev parent reply other threads:[~2012-05-08 15:52 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-05-08 15:51 [Qemu-devel] [PATCH 0/2] qtest: Add floppy media change test Kevin Wolf
2012-05-08 15:51 ` Kevin Wolf [this message]
2012-05-08 15:51 ` [Qemu-devel] [PATCH 2/2] qtest: Add floppy test Kevin Wolf
2012-05-09 17:11 ` Andreas Färber
2012-05-10 7:30 ` Kevin Wolf
2012-05-10 7:31 ` Paolo Bonzini
2012-05-10 7:31 ` [Qemu-devel] [PATCH 0/2] qtest: Add floppy media change test Paolo Bonzini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1336492304-26256-2-git-send-email-kwolf@redhat.com \
--to=kwolf@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).