9ae3a8
From 5f073207f144613806bc0b004a01ef66da9ad5e0 Mon Sep 17 00:00:00 2001
9ae3a8
Message-Id: <5f073207f144613806bc0b004a01ef66da9ad5e0.1387288155.git.minovotn@redhat.com>
9ae3a8
In-Reply-To: <527da6c2ce2c09d0183aa8595fc95f136f61b6df.1387288155.git.minovotn@redhat.com>
9ae3a8
References: <527da6c2ce2c09d0183aa8595fc95f136f61b6df.1387288155.git.minovotn@redhat.com>
9ae3a8
From: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
Date: Thu, 12 Dec 2013 16:21:25 +0100
9ae3a8
Subject: [PATCH 5/8] libqtest: add qmp(fmt, ...) -> QDict* function
9ae3a8
MIME-Version: 1.0
9ae3a8
Content-Type: text/plain; charset=UTF-8
9ae3a8
Content-Transfer-Encoding: 8bit
9ae3a8
9ae3a8
RH-Author: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
Message-id: <1386865288-1575-6-git-send-email-stefanha@redhat.com>
9ae3a8
Patchwork-id: 56259
9ae3a8
O-Subject: [RHEL7 qemu-kvm PATCH 5/8] libqtest: add qmp(fmt, ...) -> QDict* function
9ae3a8
Bugzilla: 1003773
9ae3a8
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
RH-Acked-by: Jeffrey Cody <jcody@redhat.com>
9ae3a8
RH-Acked-by: Markus Armbruster <armbru@redhat.com>
9ae3a8
9ae3a8
Add a qtest qmp() function that returns the response object.  This
9ae3a8
allows test cases to verify the result or to check for error responses.
9ae3a8
It also allows waiting for QMP events.
9ae3a8
9ae3a8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
Reviewed-by: Eric Blake <eblake@redhat.com>
9ae3a8
Reviewed-by: Andreas Färber <afaerber@suse.de>
9ae3a8
(cherry picked from commit 0c460dac03e7919079525d8e24ef2c4c607c219d)
9ae3a8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
---
9ae3a8
 tests/libqtest.c | 66 ++++++++++++++++++++++++++++++++++++++++++++------------
9ae3a8
 tests/libqtest.h | 37 +++++++++++++++++++++++++++++++
9ae3a8
 2 files changed, 89 insertions(+), 14 deletions(-)
9ae3a8
9ae3a8
Signed-off-by: Michal Novotny <minovotn@redhat.com>
9ae3a8
---
9ae3a8
 tests/libqtest.c | 66 ++++++++++++++++++++++++++++++++++++++++++++------------
9ae3a8
 tests/libqtest.h | 37 +++++++++++++++++++++++++++++++
9ae3a8
 2 files changed, 89 insertions(+), 14 deletions(-)
9ae3a8
9ae3a8
diff --git a/tests/libqtest.c b/tests/libqtest.c
9ae3a8
index dc4c983..83424c3 100644
9ae3a8
--- a/tests/libqtest.c
9ae3a8
+++ b/tests/libqtest.c
9ae3a8
@@ -30,6 +30,8 @@
9ae3a8
 
9ae3a8
 #include "qemu/compiler.h"
9ae3a8
 #include "qemu/osdep.h"
9ae3a8
+#include "qapi/qmp/json-streamer.h"
9ae3a8
+#include "qapi/qmp/json-parser.h"
9ae3a8
 
9ae3a8
 #define MAX_IRQ 256
9ae3a8
 
9ae3a8
@@ -291,16 +293,38 @@ redo:
9ae3a8
     return words;
9ae3a8
 }
9ae3a8
 
9ae3a8
-void qtest_qmpv_discard_response(QTestState *s, const char *fmt, va_list ap)
9ae3a8
+typedef struct {
9ae3a8
+    JSONMessageParser parser;
9ae3a8
+    QDict *response;
9ae3a8
+} QMPResponseParser;
9ae3a8
+
9ae3a8
+static void qmp_response(JSONMessageParser *parser, QList *tokens)
9ae3a8
 {
9ae3a8
-    bool has_reply = false;
9ae3a8
-    int nesting = 0;
9ae3a8
+    QMPResponseParser *qmp = container_of(parser, QMPResponseParser, parser);
9ae3a8
+    QObject *obj;
9ae3a8
+
9ae3a8
+    obj = json_parser_parse(tokens, NULL);
9ae3a8
+    if (!obj) {
9ae3a8
+        fprintf(stderr, "QMP JSON response parsing failed\n");
9ae3a8
+        exit(1);
9ae3a8
+    }
9ae3a8
+
9ae3a8
+    g_assert(qobject_type(obj) == QTYPE_QDICT);
9ae3a8
+    g_assert(!qmp->response);
9ae3a8
+    qmp->response = (QDict *)obj;
9ae3a8
+}
9ae3a8
+
9ae3a8
+QDict *qtest_qmpv(QTestState *s, const char *fmt, va_list ap)
9ae3a8
+{
9ae3a8
+    QMPResponseParser qmp;
9ae3a8
 
9ae3a8
     /* Send QMP request */
9ae3a8
     socket_sendf(s->qmp_fd, fmt, ap);
9ae3a8
 
9ae3a8
     /* Receive reply */
9ae3a8
-    while (!has_reply || nesting > 0) {
9ae3a8
+    qmp.response = NULL;
9ae3a8
+    json_message_parser_init(&qmp.parser, qmp_response);
9ae3a8
+    while (!qmp.response) {
9ae3a8
         ssize_t len;
9ae3a8
         char c;
9ae3a8
 
9ae3a8
@@ -314,25 +338,39 @@ void qtest_qmpv_discard_response(QTestState *s, const char *fmt, va_list ap)
9ae3a8
             exit(1);
9ae3a8
         }
9ae3a8
 
9ae3a8
-        switch (c) {
9ae3a8
-        case '{':
9ae3a8
-            nesting++;
9ae3a8
-            has_reply = true;
9ae3a8
-            break;
9ae3a8
-        case '}':
9ae3a8
-            nesting--;
9ae3a8
-            break;
9ae3a8
-        }
9ae3a8
+        json_message_parser_feed(&qmp.parser, &c, 1);
9ae3a8
     }
9ae3a8
+    json_message_parser_destroy(&qmp.parser);
9ae3a8
+
9ae3a8
+    return qmp.response;
9ae3a8
+}
9ae3a8
+
9ae3a8
+QDict *qtest_qmp(QTestState *s, const char *fmt, ...)
9ae3a8
+{
9ae3a8
+    va_list ap;
9ae3a8
+    QDict *response;
9ae3a8
+
9ae3a8
+    va_start(ap, fmt);
9ae3a8
+    response = qtest_qmpv(s, fmt, ap);
9ae3a8
+    va_end(ap);
9ae3a8
+    return response;
9ae3a8
+}
9ae3a8
+
9ae3a8
+void qtest_qmpv_discard_response(QTestState *s, const char *fmt, va_list ap)
9ae3a8
+{
9ae3a8
+    QDict *response = qtest_qmpv(s, fmt, ap);
9ae3a8
+    QDECREF(response);
9ae3a8
 }
9ae3a8
 
9ae3a8
 void qtest_qmp_discard_response(QTestState *s, const char *fmt, ...)
9ae3a8
 {
9ae3a8
     va_list ap;
9ae3a8
+    QDict *response;
9ae3a8
 
9ae3a8
     va_start(ap, fmt);
9ae3a8
-    qtest_qmpv_discard_response(s, fmt, ap);
9ae3a8
+    response = qtest_qmpv(s, fmt, ap);
9ae3a8
     va_end(ap);
9ae3a8
+    QDECREF(response);
9ae3a8
 }
9ae3a8
 
9ae3a8
 const char *qtest_get_arch(void)
9ae3a8
diff --git a/tests/libqtest.h b/tests/libqtest.h
9ae3a8
index 3faa49b..0d914f6 100644
9ae3a8
--- a/tests/libqtest.h
9ae3a8
+++ b/tests/libqtest.h
9ae3a8
@@ -22,6 +22,7 @@
9ae3a8
 #include <stdbool.h>
9ae3a8
 #include <stdarg.h>
9ae3a8
 #include <sys/types.h>
9ae3a8
+#include "qapi/qmp/qdict.h"
9ae3a8
 
9ae3a8
 typedef struct QTestState QTestState;
9ae3a8
 
9ae3a8
@@ -53,6 +54,15 @@ void qtest_quit(QTestState *s);
9ae3a8
 void qtest_qmp_discard_response(QTestState *s, const char *fmt, ...);
9ae3a8
 
9ae3a8
 /**
9ae3a8
+ * qtest_qmp:
9ae3a8
+ * @s: #QTestState instance to operate on.
9ae3a8
+ * @fmt...: QMP message to send to qemu
9ae3a8
+ *
9ae3a8
+ * Sends a QMP message to QEMU and returns the response.
9ae3a8
+ */
9ae3a8
+QDict *qtest_qmp(QTestState *s, const char *fmt, ...);
9ae3a8
+
9ae3a8
+/**
9ae3a8
  * qtest_qmpv_discard_response:
9ae3a8
  * @s: #QTestState instance to operate on.
9ae3a8
  * @fmt: QMP message to send to QEMU
9ae3a8
@@ -63,6 +73,16 @@ void qtest_qmp_discard_response(QTestState *s, const char *fmt, ...);
9ae3a8
 void qtest_qmpv_discard_response(QTestState *s, const char *fmt, va_list ap);
9ae3a8
 
9ae3a8
 /**
9ae3a8
+ * qtest_qmpv:
9ae3a8
+ * @s: #QTestState instance to operate on.
9ae3a8
+ * @fmt: QMP message to send to QEMU
9ae3a8
+ * @ap: QMP message arguments
9ae3a8
+ *
9ae3a8
+ * Sends a QMP message to QEMU and returns the response.
9ae3a8
+ */
9ae3a8
+QDict *qtest_qmpv(QTestState *s, const char *fmt, va_list ap);
9ae3a8
+
9ae3a8
+/**
9ae3a8
  * qtest_get_irq:
9ae3a8
  * @s: #QTestState instance to operate on.
9ae3a8
  * @num: Interrupt to observe.
9ae3a8
@@ -331,6 +351,23 @@ static inline void qtest_end(void)
9ae3a8
 }
9ae3a8
 
9ae3a8
 /**
9ae3a8
+ * qmp:
9ae3a8
+ * @fmt...: QMP message to send to qemu
9ae3a8
+ *
9ae3a8
+ * Sends a QMP message to QEMU and returns the response.
9ae3a8
+ */
9ae3a8
+static inline QDict *qmp(const char *fmt, ...)
9ae3a8
+{
9ae3a8
+    va_list ap;
9ae3a8
+    QDict *response;
9ae3a8
+
9ae3a8
+    va_start(ap, fmt);
9ae3a8
+    response = qtest_qmpv(global_qtest, fmt, ap);
9ae3a8
+    va_end(ap);
9ae3a8
+    return response;
9ae3a8
+}
9ae3a8
+
9ae3a8
+/**
9ae3a8
  * qmp_discard_response:
9ae3a8
  * @fmt...: QMP message to send to qemu
9ae3a8
  *
9ae3a8
-- 
9ae3a8
1.7.11.7
9ae3a8