qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v6 4/7] qom: support arbitrary non-scalar proper


From: Marc-André Lureau
Subject: Re: [Qemu-devel] [PATCH v6 4/7] qom: support arbitrary non-scalar properties with -object
Date: Tue, 28 Jun 2016 18:09:08 +0200

Hi

On Tue, Jun 14, 2016 at 6:07 PM, Daniel P. Berrange <address@hidden> wrote:
> The current -object command line syntax only allows for
> creation of objects with scalar properties, or a list
> with a fixed scalar element type. Objects which have
> properties that are represented as structs in the QAPI
> schema cannot be created using -object.
>
> This is a design limitation of the way the OptsVisitor
> is written. It simply iterates over the QemuOpts values
> as a flat list. The support for lists is enabled by
> allowing the same key to be repeated in the opts string.
>
> It is not practical to extend the OptsVisitor to support
> more complex data structures while also maintaining
> the existing list handling behaviour that is relied upon
> by other areas of QEMU.
>
> Fortunately there is no existing object that implements
> the UserCreatable interface that relies on the list
> handling behaviour, so it is possible to swap out the
> OptsVisitor for a different visitor implementation, so
> -object supports non-scalar properties, thus leaving
> other users of OptsVisitor unaffected.
>
> The previously added qdict_crumple() method is able to
> take a qdict containing a flat set of properties and
> turn that into a arbitrarily nested set of dicts and
> lists. By combining qemu_opts_to_qdict and qdict_crumple()
> together, we can turn the opt string into a data structure
> that is practically identical to that passed over QMP
> when defining an object. The only difference is that all
> the scalar values are represented as strings, rather than
> strings, ints and bools. This is sufficient to let us
> replace the OptsVisitor with the QMPInputVisitor for
> use with -object.
>
> Thus -object can now support non-scalar properties,
> for example the QMP object
>
>   {
>     "execute": "object-add",
>     "arguments": {
>       "qom-type": "demo",
>       "id": "demo0",
>       "parameters": {
>         "foo": [
>           { "bar": "one", "wizz": "1" },
>           { "bar": "two", "wizz": "2" }
>         ]
>       }
>     }
>   }
>
> Would be creatable via the CLI now using
>
>     $QEMU \
>       -object demo,id=demo0,\
>               foo.0.bar=one,foo.0.wizz=1,\
>               foo.1.bar=two,foo.1.wizz=2
>
> Notice that this syntax is intentionally compatible
> with that currently used by block drivers.
>
> This is also wired up to work for the 'object_add' command
> in the HMP monitor with the same syntax.
>
>   (hmp) object_add demo,id=demo0,\
>                    foo.0.bar=one,foo.0.wizz=1,\
>                    foo.1.bar=two,foo.1.wizz=2
>
> NB indentation should not be used with HMP commands, this
> is just for convenient formatting in this commit message.
>
> Signed-off-by: Daniel P. Berrange <address@hidden>

The patch breaks parsing of size arguments:

-object memory-backend-file,id=mem,size=512M,mem-path=/tmp: Parameter
'size' expects a number


Looks like the previous patch needs type_size support

> ---
>  hmp.c                           |  18 +--
>  include/qom/object_interfaces.h |  10 +-
>  qmp.c                           |   2 +-
>  qom/object_interfaces.c         |  49 ++++--
>  tests/check-qom-proplist.c      | 319 
> +++++++++++++++++++++++++++++++++++++++-
>  5 files changed, 365 insertions(+), 33 deletions(-)
>
> diff --git a/hmp.c b/hmp.c
> index a4b1d3d..e7778e7 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -25,7 +25,7 @@
>  #include "qemu/sockets.h"
>  #include "monitor/monitor.h"
>  #include "monitor/qdev.h"
> -#include "qapi/opts-visitor.h"
> +#include "qapi/qmp-input-visitor.h"
>  #include "qapi/qmp/qerror.h"
>  #include "qapi/string-output-visitor.h"
>  #include "qapi/util.h"
> @@ -1717,20 +1717,12 @@ void hmp_netdev_del(Monitor *mon, const QDict *qdict)
>  void hmp_object_add(Monitor *mon, const QDict *qdict)
>  {
>      Error *err = NULL;
> -    QemuOpts *opts;
> -    OptsVisitor *ov;
> +    QmpInputVisitor *qiv;
>      Object *obj = NULL;
>
> -    opts = qemu_opts_from_qdict(qemu_find_opts("object"), qdict, &err);
> -    if (err) {
> -        hmp_handle_error(mon, &err);
> -        return;
> -    }
> -
> -    ov = opts_visitor_new(opts);
> -    obj = user_creatable_add(qdict, opts_get_visitor(ov), &err);
> -    opts_visitor_cleanup(ov);
> -    qemu_opts_del(opts);
> +    qiv = qmp_string_input_visitor_new((QObject *)qdict, true);
> +    obj = user_creatable_add(qdict, qmp_input_get_visitor(qiv), &err);
> +    qmp_input_visitor_cleanup(qiv);
>
>      if (err) {
>          hmp_handle_error(mon, &err);
> diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
> index 8b17f4d..997563a 100644
> --- a/include/qom/object_interfaces.h
> +++ b/include/qom/object_interfaces.h
> @@ -96,18 +96,24 @@ Object *user_creatable_add(const QDict *qdict,
>   * user_creatable_add_type:
>   * @type: the object type name
>   * @id: the unique ID for the object
> + * @nested: whether to recurse into the visitor for properties
>   * @qdict: the object properties
>   * @v: the visitor
>   * @errp: if an error occurs, a pointer to an area to store the error
>   *
>   * Create an instance of the user creatable object @type, placing
>   * it in the object composition tree with name @id, initializing
> - * it with properties from @qdict
> + * it with properties from @qdict.
> + *
> + * If the visitor is already positioned to read the properties
> + * in @qdict, @nested should be false. Conversely, if it is
> + * neccessary to open/close a struct to read the properties in
> + * @qdict, @nested should be true.
>   *
>   * Returns: the newly created object or NULL on error
>   */
>  Object *user_creatable_add_type(const char *type, const char *id,
> -                                const QDict *qdict,
> +                                bool nested, const QDict *qdict,
>                                  Visitor *v, Error **errp);
>
>  /**
> diff --git a/qmp.c b/qmp.c
> index 7df6543..fc33661 100644
> --- a/qmp.c
> +++ b/qmp.c
> @@ -667,7 +667,7 @@ void qmp_object_add(const char *type, const char *id,
>      }
>
>      qiv = qmp_input_visitor_new(props, true);
> -    obj = user_creatable_add_type(type, id, pdict,
> +    obj = user_creatable_add_type(type, id, true, pdict,
>                                    qmp_input_get_visitor(qiv), errp);
>      qmp_input_visitor_cleanup(qiv);
>      if (obj) {
> diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
> index 51e62e2..174a5f8 100644
> --- a/qom/object_interfaces.c
> +++ b/qom/object_interfaces.c
> @@ -3,6 +3,7 @@
>  #include "qom/object_interfaces.h"
>  #include "qemu/module.h"
>  #include "qapi-visit.h"
> +#include "qapi/qmp-input-visitor.h"
>  #include "qapi/qmp-output-visitor.h"
>  #include "qapi/opts-visitor.h"
>
> @@ -63,12 +64,16 @@ Object *user_creatable_add(const QDict *qdict,
>      if (local_err) {
>          goto out_visit;
>      }
> -    visit_check_struct(v, &local_err);
> +
> +    obj = user_creatable_add_type(type, id, false, pdict, v, &local_err);
>      if (local_err) {
>          goto out_visit;
>      }
>
> -    obj = user_creatable_add_type(type, id, pdict, v, &local_err);
> +    visit_check_struct(v, &local_err);
> +    if (local_err) {
> +        goto out_visit;
> +    }
>
>  out_visit:
>      visit_end_struct(v);
> @@ -87,7 +92,7 @@ out:
>
>
>  Object *user_creatable_add_type(const char *type, const char *id,
> -                                const QDict *qdict,
> +                                bool nested, const QDict *qdict,
>                                  Visitor *v, Error **errp)
>  {
>      Object *obj;
> @@ -114,9 +119,11 @@ Object *user_creatable_add_type(const char *type, const 
> char *id,
>
>      assert(qdict);
>      obj = object_new(type);
> -    visit_start_struct(v, NULL, NULL, 0, &local_err);
> -    if (local_err) {
> -        goto out;
> +    if (nested) {
> +        visit_start_struct(v, NULL, NULL, 0, &local_err);
> +        if (local_err) {
> +            goto out;
> +        }
>      }
>      for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) {
>          object_property_set(obj, v, e->key, &local_err);
> @@ -124,12 +131,14 @@ Object *user_creatable_add_type(const char *type, const 
> char *id,
>              break;
>          }
>      }
> -    if (!local_err) {
> -        visit_check_struct(v, &local_err);
> -    }
> -    visit_end_struct(v);
> -    if (local_err) {
> -        goto out;
> +    if (nested) {
> +        if (!local_err) {
> +            visit_check_struct(v, &local_err);
> +        }
> +        visit_end_struct(v);
> +        if (local_err) {
> +            goto out;
> +        }
>      }
>
>      object_property_add_child(object_get_objects_root(),
> @@ -156,15 +165,23 @@ out:
>
>  Object *user_creatable_add_opts(QemuOpts *opts, Error **errp)
>  {
> -    OptsVisitor *ov;
> +    QmpInputVisitor *qiv;
>      QDict *pdict;
> +    QObject *pobj;
>      Object *obj = NULL;
>
> -    ov = opts_visitor_new(opts);
>      pdict = qemu_opts_to_qdict(opts, NULL);
>
> -    obj = user_creatable_add(pdict, opts_get_visitor(ov), errp);
> -    opts_visitor_cleanup(ov);
> +    pobj = qdict_crumple(pdict, true, errp);
> +    if (!pobj) {
> +        goto cleanup;
> +    }
> +    qiv = qmp_string_input_visitor_new(pobj, true);
> +
> +    obj = user_creatable_add((QDict *)pobj, qmp_input_get_visitor(qiv), 
> errp);
> +    qmp_input_visitor_cleanup(qiv);
> +    qobject_decref(pobj);
> + cleanup:
>      QDECREF(pdict);
>      return obj;
>  }
> diff --git a/tests/check-qom-proplist.c b/tests/check-qom-proplist.c
> index 42defe7..0fd104b 100644
> --- a/tests/check-qom-proplist.c
> +++ b/tests/check-qom-proplist.c
> @@ -23,6 +23,14 @@
>  #include "qapi/error.h"
>  #include "qom/object.h"
>  #include "qemu/module.h"
> +#include "qapi/visitor.h"
> +#include "qom/object_interfaces.h"
> +#include "qemu/option.h"
> +#include "qemu/config-file.h"
> +#include "qapi/qmp/qjson.h"
> +#include "qapi/qmp-input-visitor.h"
> +#include "qapi-visit.h"
> +#include "qapi/dealloc-visitor.h"
>
>
>  #define TYPE_DUMMY "qemu-dummy"
> @@ -30,6 +38,11 @@
>  typedef struct DummyObject DummyObject;
>  typedef struct DummyObjectClass DummyObjectClass;
>
> +typedef struct DummyPerson DummyPerson;
> +typedef struct DummyAddr DummyAddr;
> +typedef struct DummyAddrList DummyAddrList;
> +typedef struct DummySizeList DummySizeList;
> +
>  #define DUMMY_OBJECT(obj)                               \
>      OBJECT_CHECK(DummyObject, (obj), TYPE_DUMMY)
>
> @@ -50,12 +63,35 @@ static const char *const dummy_animal_map[DUMMY_LAST + 1] 
> = {
>      [DUMMY_LAST] = NULL,
>  };
>
> +
> +struct DummyAddr {
> +    char *ip;
> +    int64_t prefix;
> +    bool ipv6only;
> +};
> +
> +struct DummyAddrList {
> +    DummyAddrList *next;
> +    struct DummyAddr *value;
> +};
> +
> +struct DummyPerson {
> +    char *name;
> +    int64_t age;
> +};
> +
>  struct DummyObject {
>      Object parent_obj;
>
>      bool bv;
>      DummyAnimal av;
>      char *sv;
> +
> +    intList *sizes;
> +
> +    DummyPerson *person;
> +
> +    DummyAddrList *addrs;
>  };
>
>  struct DummyObjectClass {
> @@ -117,6 +153,159 @@ static char *dummy_get_sv(Object *obj,
>      return g_strdup(dobj->sv);
>  }
>
> +static void visit_type_DummyPerson_fields(Visitor *v, DummyPerson **obj,
> +                                          Error **errp)
> +{
> +    Error *err = NULL;
> +
> +    visit_type_str(v, "name", &(*obj)->name, &err);
> +    if (err) {
> +        goto out;
> +    }
> +    visit_type_int(v, "age", &(*obj)->age, &err);
> +    if (err) {
> +        goto out;
> +    }
> +
> +out:
> +    error_propagate(errp, err);
> +}
> +
> +static void visit_type_DummyPerson(Visitor *v, const char *name,
> +                                   DummyPerson **obj, Error **errp)
> +{
> +    Error *err = NULL;
> +
> +    visit_start_struct(v, name, (void **)obj, sizeof(DummyPerson), &err);
> +    if (err) {
> +        goto out;
> +    }
> +    if (!*obj) {
> +        goto out_obj;
> +    }
> +    visit_type_DummyPerson_fields(v, obj, &err);
> +    error_propagate(errp, err);
> +    err = NULL;
> +out_obj:
> +    visit_end_struct(v);
> +out:
> +    error_propagate(errp, err);
> +}
> +
> +static void visit_type_DummyAddr_members(Visitor *v, DummyAddr **obj,
> +                                         Error **errp)
> +{
> +    Error *err = NULL;
> +
> +    visit_type_str(v, "ip", &(*obj)->ip, &err);
> +    if (err) {
> +        goto out;
> +    }
> +    visit_type_int(v, "prefix", &(*obj)->prefix, &err);
> +    if (err) {
> +        goto out;
> +    }
> +    visit_type_bool(v, "ipv6only", &(*obj)->ipv6only, &err);
> +    if (err) {
> +        goto out;
> +    }
> +
> +out:
> +    error_propagate(errp, err);
> +}
> +
> +static void visit_type_DummyAddr(Visitor *v, const char *name,
> +                                 DummyAddr **obj, Error **errp)
> +{
> +    Error *err = NULL;
> +
> +    visit_start_struct(v, name, (void **)obj, sizeof(DummyAddr), &err);
> +    if (err) {
> +        goto out;
> +    }
> +    if (!*obj) {
> +        goto out_obj;
> +    }
> +    visit_type_DummyAddr_members(v, obj, &err);
> +    error_propagate(errp, err);
> +    err = NULL;
> +out_obj:
> +    visit_end_struct(v);
> +out:
> +    error_propagate(errp, err);
> +}
> +
> +static void qapi_free_DummyAddrList(DummyAddrList *obj);
> +
> +static void visit_type_DummyAddrList(Visitor *v, const char *name,
> +                                     DummyAddrList **obj, Error **errp)
> +{
> +    Error *err = NULL;
> +    DummyAddrList *tail;
> +    size_t size = sizeof(**obj);
> +
> +    visit_start_list(v, name, (GenericList **)obj, size, &err);
> +    if (err) {
> +        goto out;
> +    }
> +
> +    for (tail = *obj; tail;
> +         tail = (DummyAddrList *)visit_next_list(v,
> +                                                 (GenericList *)tail,
> +                                                 size)) {
> +        visit_type_DummyAddr(v, NULL, &tail->value, &err);
> +        if (err) {
> +            break;
> +        }
> +    }
> +
> +    visit_end_list(v);
> +    if (err && visit_is_input(v)) {
> +        qapi_free_DummyAddrList(*obj);
> +        *obj = NULL;
> +    }
> +out:
> +    error_propagate(errp, err);
> +}
> +
> +static void qapi_free_DummyAddrList(DummyAddrList *obj)
> +{
> +    QapiDeallocVisitor *qdv;
> +    Visitor *v;
> +
> +    if (!obj) {
> +        return;
> +    }
> +
> +    qdv = qapi_dealloc_visitor_new();
> +    v = qapi_dealloc_get_visitor(qdv);
> +    visit_type_DummyAddrList(v, NULL, &obj, NULL);
> +    qapi_dealloc_visitor_cleanup(qdv);
> +}
> +
> +static void dummy_set_sizes(Object *obj, Visitor *v, const char *name,
> +                            void *opaque, Error **errp)
> +{
> +    DummyObject *dobj = DUMMY_OBJECT(obj);
> +
> +    visit_type_intList(v, name, &dobj->sizes, errp);
> +}
> +
> +static void dummy_set_person(Object *obj, Visitor *v, const char *name,
> +                            void *opaque, Error **errp)
> +{
> +    DummyObject *dobj = DUMMY_OBJECT(obj);
> +
> +    visit_type_DummyPerson(v, name, &dobj->person, errp);
> +}
> +
> +static void dummy_set_addrs(Object *obj, Visitor *v, const char *name,
> +                            void *opaque, Error **errp)
> +{
> +    DummyObject *dobj = DUMMY_OBJECT(obj);
> +
> +    visit_type_DummyAddrList(v, name, &dobj->addrs, errp);
> +}
>
>  static void dummy_init(Object *obj)
>  {
> @@ -126,9 +315,16 @@ static void dummy_init(Object *obj)
>                               NULL);
>  }
>
> +static void
> +dummy_complete(UserCreatable *uc, Error **errp)
> +{
> +}
>
>  static void dummy_class_init(ObjectClass *cls, void *data)
>  {
> +    UserCreatableClass *ucc = USER_CREATABLE_CLASS(cls);
> +    ucc->complete = dummy_complete;
> +
>      object_class_property_add_bool(cls, "bv",
>                                     dummy_get_bv,
>                                     dummy_set_bv,
> @@ -143,12 +339,36 @@ static void dummy_class_init(ObjectClass *cls, void 
> *data)
>                                     dummy_get_av,
>                                     dummy_set_av,
>                                     NULL);
> +    object_class_property_add(cls, "sizes",
> +                              "int[]",
> +                              NULL,
> +                              dummy_set_sizes,
> +                              NULL, NULL, NULL);
> +    object_class_property_add(cls, "person",
> +                              "DummyPerson",
> +                              NULL,
> +                              dummy_set_person,
> +                              NULL, NULL, NULL);
> +    object_class_property_add(cls, "addrs",
> +                              "DummyAddrList",
> +                              NULL,
> +                              dummy_set_addrs,
> +                              NULL, NULL, NULL);
>  }
>
>
>  static void dummy_finalize(Object *obj)
>  {
>      DummyObject *dobj = DUMMY_OBJECT(obj);
> +    QapiDeallocVisitor *qdv;
> +    Visitor *v;
> +
> +    qdv = qapi_dealloc_visitor_new();
> +    v = qapi_dealloc_get_visitor(qdv);
> +    visit_type_intList(v, NULL, &dobj->sizes, NULL);
> +    visit_type_DummyAddrList(v, NULL, &dobj->addrs, NULL);
> +    visit_type_DummyPerson(v, NULL, &dobj->person, NULL);
> +    qapi_dealloc_visitor_cleanup(qdv);
>
>      g_free(dobj->sv);
>  }
> @@ -162,6 +382,10 @@ static const TypeInfo dummy_info = {
>      .instance_finalize = dummy_finalize,
>      .class_size = sizeof(DummyObjectClass),
>      .class_init = dummy_class_init,
> +    .interfaces = (InterfaceInfo[]) {
> +        { TYPE_USER_CREATABLE },
> +        { }
> +    }
>  };
>
>
> @@ -457,7 +681,9 @@ static void test_dummy_iterator(void)
>
>      ObjectProperty *prop;
>      ObjectPropertyIterator iter;
> -    bool seenbv = false, seensv = false, seenav = false, seentype;
> +    bool seenbv = false, seensv = false, seenav = false,
> +        seentype = false, seenaddrs = false, seenperson = false,
> +        seensizes = false;
>
>      object_property_iter_init(&iter, OBJECT(dobj));
>      while ((prop = object_property_iter_next(&iter))) {
> @@ -470,6 +696,12 @@ static void test_dummy_iterator(void)
>          } else if (g_str_equal(prop->name, "type")) {
>              /* This prop comes from the base Object class */
>              seentype = true;
> +        } else if (g_str_equal(prop->name, "addrs")) {
> +            seenaddrs = true;
> +        } else if (g_str_equal(prop->name, "person")) {
> +            seenperson = true;
> +        } else if (g_str_equal(prop->name, "sizes")) {
> +            seensizes = true;
>          } else {
>              g_printerr("Found prop '%s'\n", prop->name);
>              g_assert_not_reached();
> @@ -479,6 +711,9 @@ static void test_dummy_iterator(void)
>      g_assert(seenav);
>      g_assert(seensv);
>      g_assert(seentype);
> +    g_assert(seenaddrs);
> +    g_assert(seenperson);
> +    g_assert(seensizes);
>
>      object_unparent(OBJECT(dobj));
>  }
> @@ -497,11 +732,91 @@ static void test_dummy_delchild(void)
>      object_unparent(OBJECT(dev));
>  }
>
> +
> +static QemuOptsList dummy_opts = {
> +    .name = "object",
> +    .implied_opt_name = "qom-type",
> +    .head = QTAILQ_HEAD_INITIALIZER(dummy_opts.head),
> +    .desc = {
> +        { }
> +    },
> +};
> +
> +static void test_dummy_create_complex(DummyObject *dummy)
> +{
> +    g_assert(dummy->person != NULL);
> +    g_assert_cmpstr(dummy->person->name, ==, "fred");
> +    g_assert_cmpint(dummy->person->age, ==, 52);
> +
> +    g_assert(dummy->sizes != NULL);
> +    g_assert_cmpint(dummy->sizes->value, ==, 12);
> +    g_assert_cmpint(dummy->sizes->next->value, ==, 65);
> +    g_assert_cmpint(dummy->sizes->next->next->value, ==, 8139);
> +
> +    g_assert(dummy->addrs != NULL);
> +    g_assert_cmpstr(dummy->addrs->value->ip, ==, "127.0.0.1");
> +    g_assert_cmpint(dummy->addrs->value->prefix, ==, 24);
> +    g_assert(dummy->addrs->value->ipv6only);
> +    g_assert_cmpstr(dummy->addrs->next->value->ip, ==, "0.0.0.0");
> +    g_assert_cmpint(dummy->addrs->next->value->prefix, ==, 16);
> +    g_assert(!dummy->addrs->next->value->ipv6only);
> +}
> +
> +
> +static void test_dummy_createopts(void)
> +{
> +    const char *optstr = "qemu-dummy,id=dummy0,bv=yes,av=alligator,sv=hiss,"
> +        "person.name=fred,person.age=52,sizes.0=12,sizes.1=65,sizes.2=8139,"
> +        "addrs.0.ip=127.0.0.1,addrs.0.prefix=24,addrs.0.ipv6only=yes,"
> +        "addrs.1.ip=0.0.0.0,addrs.1.prefix=16,addrs.1.ipv6only=no";
> +    QemuOpts *opts;
> +    DummyObject *dummy;
> +
> +    opts = qemu_opts_parse_noisily(&dummy_opts,
> +                                   optstr, true);
> +    g_assert(opts != NULL);
> +
> +    dummy = DUMMY_OBJECT(user_creatable_add_opts(opts, &error_abort));
> +
> +    test_dummy_create_complex(dummy);
> +
> +    object_unparent(OBJECT(dummy));
> +    object_unref(OBJECT(dummy));
> +}
> +
> +
> +static void test_dummy_createqmp(void)
> +{
> +    const char *jsonstr =
> +        "{ 'qom-type': 'qemu-dummy', 'id': 'dummy0', "
> +        "  'bv': true, 'av': 'alligator', 'sv': 'hiss', "
> +        "  'person': { 'name': 'fred', 'age': 52 }, "
> +        "  'sizes': [12, 65, 8139], "
> +        "  'addrs': [ { 'ip': '127.0.0.1', 'prefix': 24, 'ipv6only': true }, 
> "
> +        "             { 'ip': '0.0.0.0', 'prefix': 16, 'ipv6only': false } ] 
> }";
> +    QObject *obj = qobject_from_json(jsonstr);
> +    QmpInputVisitor *qiv = qmp_input_visitor_new(obj, true);
> +    DummyObject *dummy;
> +    g_assert(obj);
> +    dummy = DUMMY_OBJECT(user_creatable_add(qobject_to_qdict(obj),
> +                                            qmp_input_get_visitor(qiv),
> +                                            &error_abort));
> +
> +    test_dummy_create_complex(dummy);
> +    qmp_input_visitor_cleanup(qiv);
> +    object_unparent(OBJECT(dummy));
> +    object_unref(OBJECT(dummy));
> +    qobject_decref(obj);
> +}
> +
>  int main(int argc, char **argv)
>  {
>      g_test_init(&argc, &argv, NULL);
>
>      module_call_init(MODULE_INIT_QOM);
> +
> +    qemu_add_opts(&dummy_opts);
> +
>      type_register_static(&dummy_info);
>      type_register_static(&dummy_dev_info);
>      type_register_static(&dummy_bus_info);
> @@ -513,6 +828,8 @@ int main(int argc, char **argv)
>      g_test_add_func("/qom/proplist/getenum", test_dummy_getenum);
>      g_test_add_func("/qom/proplist/iterator", test_dummy_iterator);
>      g_test_add_func("/qom/proplist/delchild", test_dummy_delchild);
> +    g_test_add_func("/qom/proplist/createopts", test_dummy_createopts);
> +    g_test_add_func("/qom/proplist/createqmp", test_dummy_createqmp);
>
>      return g_test_run();
>  }
> --
> 2.5.5
>
>



-- 
Marc-André Lureau



reply via email to

[Prev in Thread] Current Thread [Next in Thread]