qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Eric Blake <eblake@redhat.com>
To: qemu-devel@nongnu.org
Cc: armbru@redhat.com, Michael Roth <mdroth@linux.vnet.ibm.com>
Subject: [Qemu-devel] [PATCH v15 15/23] qmp: Support explicit null during visits
Date: Wed, 27 Apr 2016 18:01:47 -0600	[thread overview]
Message-ID: <1461801715-24307-16-git-send-email-eblake@redhat.com> (raw)
In-Reply-To: <1461801715-24307-1-git-send-email-eblake@redhat.com>

Implement the new type_null() callback for the qmp input and
output visitors. While we don't yet have a use for this in QAPI
input (the generator will need some tweaks first), some
potential usages have already been discussed on the list.
Meanwhile, the output visitor could already output explicit null
via type_any, but this gives us finer control.

At any rate, it's easy to test that we can round-trip an explicit
null through manual use of visit_type_null() wrapped by a virtual
visit_start_struct() walk, even if we can't do the visit in a
QAPI type.  Repurpose the test_visitor_out_empty test,
particularly since a future patch will tighten semantics to
forbid use of qmp_output_get_qobject() without at least one
intervening visit_type_*.

Signed-off-by: Eric Blake <eblake@redhat.com>

---
v15: hoist stubs to earlier patch, testsuite improvements
v14: rebase to header inclusion cleanups
v13: no change
v12: retitle and merge in output visitor support, move refcount
tests to separate file
[no v10, v11]
v9: new patch
---
 qapi/qmp-input-visitor.c        |  8 +++++++-
 qapi/qmp-output-visitor.c       |  4 ++--
 tests/check-qnull.c             | 13 +++++++++++--
 tests/test-qmp-input-visitor.c  | 26 ++++++++++++++++++++++++++
 tests/test-qmp-output-visitor.c | 20 +++++++++++++++-----
 5 files changed, 61 insertions(+), 10 deletions(-)

diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c
index 739bbd5..7e94be6 100644
--- a/qapi/qmp-input-visitor.c
+++ b/qapi/qmp-input-visitor.c
@@ -342,7 +342,13 @@ static void qmp_input_type_any(Visitor *v, const char *name, QObject **obj,

 static void qmp_input_type_null(Visitor *v, const char *name, Error **errp)
 {
-    error_setg(errp, "FIXME: Implement");
+    QmpInputVisitor *qiv = to_qiv(v);
+    QObject *qobj = qmp_input_get_object(qiv, name, true);
+
+    if (qobject_type(qobj) != QTYPE_QNULL) {
+        error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+                   "null");
+    }
 }

 static void qmp_input_optional(Visitor *v, const char *name, bool *present)
diff --git a/qapi/qmp-output-visitor.c b/qapi/qmp-output-visitor.c
index a67e3e8..5681ad3 100644
--- a/qapi/qmp-output-visitor.c
+++ b/qapi/qmp-output-visitor.c
@@ -18,7 +18,6 @@
 #include "qemu/queue.h"
 #include "qemu-common.h"
 #include "qapi/qmp/types.h"
-#include "qapi/error.h"

 typedef struct QStackEntry
 {
@@ -199,7 +198,8 @@ static void qmp_output_type_any(Visitor *v, const char *name, QObject **obj,

 static void qmp_output_type_null(Visitor *v, const char *name, Error **errp)
 {
-    error_setg(errp, "FIXME: Implement");
+    QmpOutputVisitor *qov = to_qov(v);
+    qmp_output_add_obj(qov, name, qnull());
 }

 /* Finish building, and return the root object. Will not be NULL. */
diff --git a/tests/check-qnull.c b/tests/check-qnull.c
index 4a1c3d8..fd9c68f 100644
--- a/tests/check-qnull.c
+++ b/tests/check-qnull.c
@@ -11,7 +11,9 @@

 #include "qapi/qmp/qobject.h"
 #include "qemu-common.h"
+#include "qapi/qmp-input-visitor.h"
 #include "qapi/qmp-output-visitor.h"
+#include "qapi/error.h"

 /*
  * Public Interface test-cases
@@ -37,6 +39,7 @@ static void qnull_visit_test(void)
 {
     QObject *obj;
     QmpOutputVisitor *qov;
+    QmpInputVisitor *qiv;

     /*
      * Most tests of interactions between QObject and visitors are in
@@ -45,13 +48,19 @@ static void qnull_visit_test(void)
      */

     g_assert(qnull_.refcnt == 1);
+    obj = qnull();
+    qiv = qmp_input_visitor_new(obj, true);
+    qobject_decref(obj);
+    visit_type_null(qmp_input_get_visitor(qiv), NULL, &error_abort);
+    qmp_input_visitor_cleanup(qiv);
+
     qov = qmp_output_visitor_new();
-    /* FIXME: Empty visits are ugly, we should have a visit_type_null(). */
+    visit_type_null(qmp_output_get_visitor(qov), NULL, &error_abort);
     obj = qmp_output_get_qobject(qov);
     g_assert(obj == &qnull_);
     qobject_decref(obj);
-
     qmp_output_visitor_cleanup(qov);
+
     g_assert(qnull_.refcnt == 1);
 }

diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c
index c039806..3b6ae92 100644
--- a/tests/test-qmp-input-visitor.c
+++ b/tests/test-qmp-input-visitor.c
@@ -279,6 +279,30 @@ static void test_visitor_in_any(TestInputVisitorData *data,
     qobject_decref(res);
 }

+static void test_visitor_in_null(TestInputVisitorData *data,
+                                 const void *unused)
+{
+    Visitor *v;
+    Error *err = NULL;
+    char *tmp;
+
+    /*
+     * FIXME: Since QAPI doesn't know the 'null' type yet, we can't
+     * test visit_type_null() by reading into a QAPI struct then
+     * checking that it was populated correctly.  The best we can do
+     * for now is ensure that we consumed null from the input, proven
+     * by the fact that we can't re-read the key.
+     */
+
+    v = visitor_input_test_init(data, "{ 'a': null }");
+    visit_start_struct(v, NULL, NULL, 0, &error_abort);
+    visit_type_null(v, "a", &error_abort);
+    visit_type_str(v, "a", &tmp, &err);
+    g_assert(err);
+    g_assert(!tmp);
+    visit_end_struct(v, &error_abort);
+}
+
 static void test_visitor_in_union_flat(TestInputVisitorData *data,
                                        const void *unused)
 {
@@ -829,6 +853,8 @@ int main(int argc, char **argv)
                            &in_visitor_data, test_visitor_in_list);
     input_visitor_test_add("/visitor/input/any",
                            &in_visitor_data, test_visitor_in_any);
+    input_visitor_test_add("/visitor/input/null",
+                           &in_visitor_data, test_visitor_in_null);
     input_visitor_test_add("/visitor/input/union-flat",
                            &in_visitor_data, test_visitor_in_union_flat);
     input_visitor_test_add("/visitor/input/alternate",
diff --git a/tests/test-qmp-output-visitor.c b/tests/test-qmp-output-visitor.c
index fddb5a6..8acc229 100644
--- a/tests/test-qmp-output-visitor.c
+++ b/tests/test-qmp-output-visitor.c
@@ -477,13 +477,23 @@ static void test_visitor_out_alternate(TestOutputVisitorData *data,
     qobject_decref(arg);
 }

-static void test_visitor_out_empty(TestOutputVisitorData *data,
-                                   const void *unused)
+static void test_visitor_out_null(TestOutputVisitorData *data,
+                                  const void *unused)
 {
     QObject *arg;
+    QDict *qdict;
+    QObject *nil;

+    visit_start_struct(data->ov, NULL, NULL, 0, &error_abort);
+    visit_type_null(data->ov, "a", &error_abort);
+    visit_end_struct(data->ov, &error_abort);
     arg = qmp_output_get_qobject(data->qov);
-    g_assert(qobject_type(arg) == QTYPE_QNULL);
+    g_assert(qobject_type(arg) == QTYPE_QDICT);
+    qdict = qobject_to_qdict(arg);
+    g_assert_cmpint(qdict_size(qdict), ==, 1);
+    nil = qdict_get(qdict, "a");
+    g_assert(nil);
+    g_assert(qobject_type(nil) == QTYPE_QNULL);
     qobject_decref(arg);
 }

@@ -837,8 +847,8 @@ int main(int argc, char **argv)
                             &out_visitor_data, test_visitor_out_union_flat);
     output_visitor_test_add("/visitor/output/alternate",
                             &out_visitor_data, test_visitor_out_alternate);
-    output_visitor_test_add("/visitor/output/empty",
-                            &out_visitor_data, test_visitor_out_empty);
+    output_visitor_test_add("/visitor/output/null",
+                            &out_visitor_data, test_visitor_out_null);
     output_visitor_test_add("/visitor/output/native_list/int",
                             &out_visitor_data,
                             test_visitor_out_native_list_int);
-- 
2.5.5

  parent reply	other threads:[~2016-04-28  0:02 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-28  0:01 [Qemu-devel] [PATCH v15 00/23] qapi visitor cleanups (post-introspection cleanups subset E) Eric Blake
2016-04-28  0:01 ` [Qemu-devel] [PATCH v15 01/23] qapi-visit: Add visitor.type classification Eric Blake
2016-04-28  0:01 ` [Qemu-devel] [PATCH v15 02/23] qapi: Guarantee NULL obj on input visitor callback error Eric Blake
2016-04-28 12:24   ` Markus Armbruster
2016-04-28 13:00     ` Eric Blake
2016-04-28 15:41       ` Eric Blake
2016-04-28 16:02   ` [Qemu-devel] [PATCH v15 02A/23] fixup! " Eric Blake
2016-04-28  0:01 ` [Qemu-devel] [PATCH v15 03/23] qmp: Drop dead command->type Eric Blake
2016-04-28  0:01 ` [Qemu-devel] [PATCH v15 04/23] qmp-input: Clean up stack handling Eric Blake
2016-04-28  0:01 ` [Qemu-devel] [PATCH v15 05/23] qapi: Use strict QMP input visitor in more places Eric Blake
2016-04-28 13:06   ` Markus Armbruster
2016-04-28 14:28     ` Eric Blake
2016-04-28  0:01 ` [Qemu-devel] [PATCH v15 06/23] qmp-input: Don't consume input when checking has_member Eric Blake
2016-04-28  0:01 ` [Qemu-devel] [PATCH v15 07/23] qapi-commands: Wrap argument visit in visit_start_struct Eric Blake
2016-04-28  0:01 ` [Qemu-devel] [PATCH v15 08/23] monitor: Let generated code validate arguments Eric Blake
2016-04-28 14:09   ` Markus Armbruster
2016-04-28 14:39     ` Marc-André Lureau
2016-04-28 18:00       ` Markus Armbruster
2016-04-28 18:58         ` Eric Blake
2016-04-28 14:47     ` Eric Blake
2016-04-28  0:01 ` [Qemu-devel] [PATCH v15 09/23] qom: Wrap prop visit in visit_start_struct Eric Blake
2016-04-28 14:46   ` Markus Armbruster
2016-04-28 15:14     ` Eric Blake
2016-04-28  0:01 ` [Qemu-devel] [PATCH v15 10/23] qmp-input: Require struct push to visit members of top dict Eric Blake
2016-04-28 15:00   ` Markus Armbruster
2016-04-28 15:04     ` Eric Blake
2016-04-28  0:01 ` [Qemu-devel] [PATCH v15 11/23] qmp-input: Refactor when list is advanced Eric Blake
2016-04-28 15:19   ` Markus Armbruster
2016-04-28  0:01 ` [Qemu-devel] [PATCH v15 12/23] qapi: Document visitor interfaces, add assertions Eric Blake
2016-04-28 16:34   ` Markus Armbruster
2016-04-28 19:02     ` Eric Blake
2016-04-28  0:01 ` [Qemu-devel] [PATCH v15 13/23] tests: Add check-qnull Eric Blake
2016-04-28  0:01 ` [Qemu-devel] [PATCH v15 14/23] qapi: Add visit_type_null() visitor Eric Blake
2016-04-28 16:40   ` Markus Armbruster
2016-04-28  0:01 ` Eric Blake [this message]
2016-04-28 16:50   ` [Qemu-devel] [PATCH v15 15/23] qmp: Support explicit null during visits Markus Armbruster
2016-04-28 19:07     ` Eric Blake
2016-04-28  0:01 ` [Qemu-devel] [PATCH v15 16/23] spapr_drc: Expose 'null' in qom-get when there is no fdt Eric Blake
2016-04-28  0:01 ` [Qemu-devel] [PATCH v15 17/23] qmp: Add qmp_output_visitor_reset() Eric Blake
2016-04-28  0:01 ` [Qemu-devel] [PATCH v15 18/23] qmp: Tighten output visitor rules Eric Blake
2016-04-28  0:01 ` [Qemu-devel] [PATCH v15 19/23] qapi: Split visit_end_struct() into pieces Eric Blake
2016-04-28  0:01 ` [Qemu-devel] [PATCH v15 20/23] tests/string-input-visitor: Add negative integer tests Eric Blake
2016-04-28  0:01 ` [Qemu-devel] [PATCH v15 21/23] qapi: Fix string input visitor handling of invalid list Eric Blake
2016-04-28 17:18   ` Markus Armbruster
2016-04-28  0:01 ` [Qemu-devel] [PATCH v15 22/23] qapi: Simplify semantics of visit_next_list() Eric Blake
2016-04-28 15:44   ` Eric Blake
2016-04-28  0:01 ` [Qemu-devel] [PATCH v15 23/23] qapi: Change visit_type_FOO() to no longer return partial objects Eric Blake
2016-04-28 17:42   ` Markus Armbruster
2016-04-28 18:03 ` [Qemu-devel] [PATCH v15 00/23] qapi visitor cleanups (post-introspection cleanups subset E) Markus Armbruster

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=1461801715-24307-16-git-send-email-eblake@redhat.com \
    --to=eblake@redhat.com \
    --cc=armbru@redhat.com \
    --cc=mdroth@linux.vnet.ibm.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).