aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--qapi/qmp-input-visitor.c8
-rw-r--r--qapi/qmp-output-visitor.c3
-rw-r--r--tests/check-qnull.c13
-rw-r--r--tests/test-qmp-input-visitor.c29
-rw-r--r--tests/test-qmp-output-visitor.c20
5 files changed, 64 insertions, 9 deletions
diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c
index fa460a3c37..30e7cb38f2 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)
{
- abort();
+ 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 adf7731e3f..5681ad3471 100644
--- a/qapi/qmp-output-visitor.c
+++ b/qapi/qmp-output-visitor.c
@@ -198,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)
{
- abort();
+ 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 4a1c3d830e..fd9c68f7e1 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 c039806e82..10e00ecbc7 100644
--- a/tests/test-qmp-input-visitor.c
+++ b/tests/test-qmp-input-visitor.c
@@ -279,6 +279,33 @@ 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; and that we detect
+ * when input is not null.
+ */
+
+ v = visitor_input_test_init(data, "{ 'a': null, 'b': '' }");
+ 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(!tmp);
+ error_free_or_abort(&err);
+ visit_type_null(v, "b", &err);
+ error_free_or_abort(&err);
+ visit_end_struct(v, &error_abort);
+}
+
static void test_visitor_in_union_flat(TestInputVisitorData *data,
const void *unused)
{
@@ -829,6 +856,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 fddb5a6e90..8acc22961b 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);