diff mbox

[19/24] qapi: Improve how keyval input visitor reports unexpected dicts

Message ID 1488194450-28056-20-git-send-email-armbru@redhat.com
State New
Headers show

Commit Message

Markus Armbruster Feb. 27, 2017, 11:20 a.m. UTC
Incorrect option

    -blockdev node-name=foo,driver=file,filename=foo.img,aio.unmap

is rejected with "Invalid parameter type for 'aio', expected: string".
To make sense of this, you almost have to translate it into the
equivalent QMP command

    { "execute": "blockdev-add", "arguments": { "node-name": "foo", "driver": "file", "filename": "foo.img", "aio": { "unmap": true } } }

Improve the error message to "Parameters 'aio.*' are unexpected".
Take care not to confuse the case "unexpected nested parameters"
(i.e. the object is a QDict or QList) with the case "non-string scalar
parameter".  The latter is a misuse of the visitor, and should perhaps
be an assertion.  Note that test-qobject-input-visitor exercises this
misuse in test_visitor_in_int_keyval(), test_visitor_in_bool_keyval()
and test_visitor_in_number_keyval().

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 qapi/qobject-input-visitor.c | 26 ++++++++++++++++++++++----
 1 file changed, 22 insertions(+), 4 deletions(-)

Comments

Kevin Wolf Feb. 28, 2017, 5:51 p.m. UTC | #1
Am 27.02.2017 um 12:20 hat Markus Armbruster geschrieben:
> Incorrect option
> 
>     -blockdev node-name=foo,driver=file,filename=foo.img,aio.unmap
> 
> is rejected with "Invalid parameter type for 'aio', expected: string".
> To make sense of this, you almost have to translate it into the
> equivalent QMP command
> 
>     { "execute": "blockdev-add", "arguments": { "node-name": "foo", "driver": "file", "filename": "foo.img", "aio": { "unmap": true } } }
> 
> Improve the error message to "Parameters 'aio.*' are unexpected".

In fact, what I get (after fixing the previous review comments that
would make it crash) is "Expected '=' after parameter 'aio.unmap'". Only
if I add a value, I get the newly added message.

Doesn't make the patch less correct, though.

> Take care not to confuse the case "unexpected nested parameters"
> (i.e. the object is a QDict or QList) with the case "non-string scalar
> parameter".  The latter is a misuse of the visitor, and should perhaps
> be an assertion.  Note that test-qobject-input-visitor exercises this
> misuse in test_visitor_in_int_keyval(), test_visitor_in_bool_keyval()
> and test_visitor_in_number_keyval().
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Markus Armbruster Feb. 28, 2017, 6:52 p.m. UTC | #2
Kevin Wolf <kwolf@redhat.com> writes:

> Am 27.02.2017 um 12:20 hat Markus Armbruster geschrieben:
>> Incorrect option
>> 
>>     -blockdev node-name=foo,driver=file,filename=foo.img,aio.unmap
>> 
>> is rejected with "Invalid parameter type for 'aio', expected: string".
>> To make sense of this, you almost have to translate it into the
>> equivalent QMP command
>> 
>>     { "execute": "blockdev-add", "arguments": { "node-name": "foo", "driver": "file", "filename": "foo.img", "aio": { "unmap": true } } }
>> 
>> Improve the error message to "Parameters 'aio.*' are unexpected".
>
> In fact, what I get (after fixing the previous review comments that
> would make it crash) is "Expected '=' after parameter 'aio.unmap'". Only
> if I add a value, I get the newly added message.

Fallout from ditching implied value sugar some time after this commit
message was written.  Will fix.

> Doesn't make the patch less correct, though.
>
>> Take care not to confuse the case "unexpected nested parameters"
>> (i.e. the object is a QDict or QList) with the case "non-string scalar
>> parameter".  The latter is a misuse of the visitor, and should perhaps
>> be an assertion.  Note that test-qobject-input-visitor exercises this
>> misuse in test_visitor_in_int_keyval(), test_visitor_in_bool_keyval()
>> and test_visitor_in_number_keyval().
>> 
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>
> Reviewed-by: Kevin Wolf <kwolf@redhat.com>

Thanks!
diff mbox

Patch

diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
index 64a08d3..1d7b420 100644
--- a/qapi/qobject-input-visitor.c
+++ b/qapi/qobject-input-visitor.c
@@ -167,9 +167,18 @@  static const char *qobject_input_get_keyval(QObjectInputVisitor *qiv,
 
     qstr = qobject_to_qstring(qobj);
     if (!qstr) {
-        error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
-                   full_name(qiv, name), "string");
-        return NULL;
+        switch (qobject_type(qobj)) {
+        case QTYPE_QDICT:
+        case QTYPE_QLIST:
+            error_setg(errp, "Parameters '%s.*' are unexpected",
+                       full_name(qiv, name));
+            return NULL;
+        default:
+            /* Non-string scalar (should this be an assertion?) */
+            error_setg(errp, "Internal error: parameter %s invalid",
+                       full_name(qiv, name));
+            return NULL;
+        }
     }
 
     return qstring_get_str(qstr);
@@ -478,6 +487,15 @@  static void qobject_input_type_str(Visitor *v, const char *name, char **obj,
     *obj = g_strdup(qstring_get_str(qstr));
 }
 
+static void qobject_input_type_str_keyval(Visitor *v, const char *name,
+                                          char **obj, Error **errp)
+{
+    QObjectInputVisitor *qiv = to_qiv(v);
+    const char *str = qobject_input_get_keyval(qiv, name, errp);
+
+    *obj = g_strdup(str);
+}
+
 static void qobject_input_type_number(Visitor *v, const char *name, double *obj,
                                       Error **errp)
 {
@@ -649,7 +667,7 @@  Visitor *qobject_input_visitor_new_keyval(QObject *obj)
     v->visitor.type_int64 = qobject_input_type_int64_keyval;
     v->visitor.type_uint64 = qobject_input_type_uint64_keyval;
     v->visitor.type_bool = qobject_input_type_bool_keyval;
-    v->visitor.type_str = qobject_input_type_str;
+    v->visitor.type_str = qobject_input_type_str_keyval;
     v->visitor.type_number = qobject_input_type_number_keyval;
     v->visitor.type_any = qobject_input_type_any;
     v->visitor.type_null = qobject_input_type_null;