diff mbox series

[RFC,v2,3/4] libqos: implement sdbus QMP driver

Message ID 20180103214925.16677-4-f4bug@amsat.org
State RFC
Headers show
Series sdbus: testing sdcards | expand

Commit Message

Philippe Mathieu-Daudé Jan. 3, 2018, 9:49 p.m. UTC
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 tests/libqos/sdbus-qmp.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++
 tests/Makefile.include   |   2 +-
 2 files changed, 131 insertions(+), 1 deletion(-)
 create mode 100644 tests/libqos/sdbus-qmp.c

Comments

Stefan Hajnoczi Jan. 5, 2018, 3:25 p.m. UTC | #1
On Wed, Jan 03, 2018 at 06:49:24PM -0300, Philippe Mathieu-Daudé wrote:
> +static const char *qmp_sdbus_getpath(const char *blkname)
> +{
> +    QDict *response, *minfo;
> +    QList *list;
> +    const QListEntry *le;
> +    QString *qstr;
> +    const char *mname;
> +    QObject *qobj;
> +
> +    response = qmp("{ 'execute': 'query-block' }");

This function implicitly uses global_qtest.  If you ever want to do
multi-VM (e.g. migration) tests then this may become a problem because
there's no way to say which QEMU process to talk to.

This can be addressed by adding a QTestState *s argument to these
functions so that global_qtest isn't hardcoded.  Use qtest_qmp()
instead.

> +    g_assert_nonnull(response);
> +    list = qdict_get_qlist(response, "return");
> +    g_assert_nonnull(list);
> +
> +    QLIST_FOREACH_ENTRY(list, le) {
> +        QDict *response2;
> +
> +        minfo = qobject_to_qdict(qlist_entry_obj(le));
> +        g_assert(minfo);
> +        qobj = qdict_get(minfo, "qdev");
> +        if (!qobj) {
> +            continue;
> +        }
> +        qstr = qobject_to_qstring(qobj);
> +        g_assert(qstr);
> +        mname = qstring_get_str(qstr);
> +
> +        response2 = qmp("{ 'execute': 'qom-get',"
> +                        "  'arguments': { 'path': %s,"
> +                        "   'property': \"parent_bus\"}"
> +                        "}", mname);
> +        g_assert(response2);
> +        g_assert(qdict_haskey(response2, "return"));
> +        qobj = qdict_get(response2, "return");
> +        qstr = qobject_to_qstring(qobj);
> +        g_assert(qstr);
> +        mname = qstring_get_str(qstr);
> +
> +        return mname;
> +    }
> +    return NULL;
> +}

response is leaked.  I think something like this is needed:

  char *mname = g_strdup(qstring_get_str(qstr));
  QDECREF(response);
  return mname;

The caller must g_free() the return value too and the type must be char
* instead of const char *.

> +
> +static ssize_t qmp_mmc_do_cmd(SDBusAdapter *adapter, enum NCmd cmd, uint32_t arg,
> +                              uint8_t **response)
> +{
> +    QMPSDBus *s = (QMPSDBus *)adapter;
> +    QDict *response1;
> +    QObject *qobj;
> +
> +    response1 = qmp("{ 'execute': 'x-debug-sdbus-command',"
> +                    "  'arguments': { 'qom-path': %s,"
> +                    "                 'command': %u, 'arg': %u}"
> +                    "}",
> +                    s->qom_path, cmd, arg);
> +    g_assert(qdict_haskey(response1, "return"));
> +    qobj = qdict_get(response1, "return");
> +    //QDECREF(response);
> +
> +    if (!qobj) {
> +        return -1;
> +    }
> +
> +    {
> +        QString *qstr;
> +        const gchar *mname;
> +        guchar *uc;
> +        gsize out_len;
> +        QDict *response2 = qobject_to_qdict(qobj);
> +
> +        if (!qdict_haskey(response2, "base64")) {
> +            return 0;
> +        }
> +        qobj = qdict_get(response2, "base64");
> +        qstr = qobject_to_qstring(qobj);
> +        if (!qstr) {
> +            puts("!qstr");
> +            return 0;
> +        }
> +        mname = qstring_get_str(qstr);
> +
> +        uc = g_base64_decode(mname, &out_len);
> +        if (response) {
> +            *response = uc;
> +        } else {
> +            g_free(uc);
> +        }
> +        return out_len;
> +
> +    }
> +
> +    return 0;
> +}

Please fix memory leaks here, too.  For example, response1 is leaked.
diff mbox series

Patch

diff --git a/tests/libqos/sdbus-qmp.c b/tests/libqos/sdbus-qmp.c
new file mode 100644
index 0000000000..565e2481db
--- /dev/null
+++ b/tests/libqos/sdbus-qmp.c
@@ -0,0 +1,130 @@ 
+/*
+ * QTest SD/MMC Bus QMP driver
+ *
+ * Copyright (c) 2017 Philippe Mathieu-Daudé
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include "qemu/osdep.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qstring.h"
+
+#include "libqos/sdbus.h"
+#include "libqtest.h"
+
+typedef struct QMPSDBus {
+    SDBusAdapter parent;
+
+    const char *qom_path;
+} QMPSDBus;
+
+
+static const char *qmp_sdbus_getpath(const char *blkname)
+{
+    QDict *response, *minfo;
+    QList *list;
+    const QListEntry *le;
+    QString *qstr;
+    const char *mname;
+    QObject *qobj;
+
+    response = qmp("{ 'execute': 'query-block' }");
+    g_assert_nonnull(response);
+    list = qdict_get_qlist(response, "return");
+    g_assert_nonnull(list);
+
+    QLIST_FOREACH_ENTRY(list, le) {
+        QDict *response2;
+
+        minfo = qobject_to_qdict(qlist_entry_obj(le));
+        g_assert(minfo);
+        qobj = qdict_get(minfo, "qdev");
+        if (!qobj) {
+            continue;
+        }
+        qstr = qobject_to_qstring(qobj);
+        g_assert(qstr);
+        mname = qstring_get_str(qstr);
+
+        response2 = qmp("{ 'execute': 'qom-get',"
+                        "  'arguments': { 'path': %s,"
+                        "   'property': \"parent_bus\"}"
+                        "}", mname);
+        g_assert(response2);
+        g_assert(qdict_haskey(response2, "return"));
+        qobj = qdict_get(response2, "return");
+        qstr = qobject_to_qstring(qobj);
+        g_assert(qstr);
+        mname = qstring_get_str(qstr);
+
+        return mname;
+    }
+    return NULL;
+}
+
+static ssize_t qmp_mmc_do_cmd(SDBusAdapter *adapter, enum NCmd cmd, uint32_t arg,
+                              uint8_t **response)
+{
+    QMPSDBus *s = (QMPSDBus *)adapter;
+    QDict *response1;
+    QObject *qobj;
+
+    response1 = qmp("{ 'execute': 'x-debug-sdbus-command',"
+                    "  'arguments': { 'qom-path': %s,"
+                    "                 'command': %u, 'arg': %u}"
+                    "}",
+                    s->qom_path, cmd, arg);
+    g_assert(qdict_haskey(response1, "return"));
+    qobj = qdict_get(response1, "return");
+    //QDECREF(response);
+
+    if (!qobj) {
+        return -1;
+    }
+
+    {
+        QString *qstr;
+        const gchar *mname;
+        guchar *uc;
+        gsize out_len;
+        QDict *response2 = qobject_to_qdict(qobj);
+
+        if (!qdict_haskey(response2, "base64")) {
+            return 0;
+        }
+        qobj = qdict_get(response2, "base64");
+        qstr = qobject_to_qstring(qobj);
+        if (!qstr) {
+            puts("!qstr");
+            return 0;
+        }
+        mname = qstring_get_str(qstr);
+
+        uc = g_base64_decode(mname, &out_len);
+        if (response) {
+            *response = uc;
+        } else {
+            g_free(uc);
+        }
+        return out_len;
+
+    }
+
+    return 0;
+}
+
+SDBusAdapter *qmp_sdbus_create(const char *bus_name)
+{
+    QMPSDBus *s;
+    SDBusAdapter *mmc;
+
+    s = g_new(QMPSDBus, 1);
+    s->qom_path = qmp_sdbus_getpath(bus_name);
+    g_assert_nonnull(s->qom_path);
+
+    mmc = (SDBusAdapter *)s;
+    mmc->do_command = qmp_mmc_do_cmd;
+
+    return mmc;
+}
diff --git a/tests/Makefile.include b/tests/Makefile.include
index c22925d4db..409784a189 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -715,7 +715,7 @@  tests/test-crypto-block$(EXESUF): tests/test-crypto-block.o $(test-crypto-obj-y)
 
 libqos-obj-y = tests/libqos/pci.o tests/libqos/fw_cfg.o tests/libqos/malloc.o
 libqos-obj-y += tests/libqos/i2c.o tests/libqos/libqos.o
-libqos-obj-y += tests/libqos/sdbus.o
+libqos-obj-y += tests/libqos/sdbus.o tests/libqos/sdbus-qmp.o
 libqos-spapr-obj-y = $(libqos-obj-y) tests/libqos/malloc-spapr.o
 libqos-spapr-obj-y += tests/libqos/libqos-spapr.o
 libqos-spapr-obj-y += tests/libqos/rtas.o