[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH for-2.9 v2] qom: Make all interface types abstra
From: |
Markus Armbruster |
Subject: |
Re: [Qemu-devel] [PATCH for-2.9 v2] qom: Make all interface types abstract |
Date: |
Wed, 14 Dec 2016 14:04:50 +0100 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/24.5 (gnu/linux) |
Eduardo Habkost <address@hidden> writes:
> "qom-list-types abstract=false" currently returns all interface
> types, as if they were not abstract. Fix this by making sure all
> interface types are abstract.
>
> All interface types have instance_size == 0, so we can use
> it to set abstract=true on type_initialize().
>
> Signed-off-by: Eduardo Habkost <address@hidden>
> ---
> Changes v1 -> v2:
> * Use old-fashioned if statement instead of "|=" on bool field
> Suggested-by: Andreas Färber <address@hidden>
> * Keep "device/introspect" path prefix on unit test
> * Suggested-by: Andreas Färber <address@hidden>
> ---
> qom/object.c | 6 +++++
> tests/device-introspect-test.c | 60
> +++++++++++++++++++++++++++++++++++++++---
> 2 files changed, 63 insertions(+), 3 deletions(-)
>
> diff --git a/qom/object.c b/qom/object.c
> index 7a05e35..760fafb 100644
> --- a/qom/object.c
> +++ b/qom/object.c
> @@ -272,6 +272,12 @@ static void type_initialize(TypeImpl *ti)
>
> ti->class_size = type_class_get_size(ti);
> ti->instance_size = type_object_get_size(ti);
> + /* Any type with zero instance_size is implicitly abstract.
> + * This means interface types are all abstract.
> + */
> + if (ti->instance_size == 0) {
> + ti->abstract = true;
> + }
>
> ti->class = g_malloc0(ti->class_size);
>
Letting zero instance_size imply abstract works (I guess), but is it
wise to imply? Is requiring explicit .abstract = true really too much
trouble?
Consider:
static const TypeInfo uc_interface_info = {
.name = TYPE_USER_CREATABLE,
.parent = TYPE_INTERFACE,
.class_size = sizeof(UserCreatableClass),
};
Is this abstract? Yes, because there's no .instance_size = ...,
therefore .instance_size remains zero, and .abstract defaults to true.
static const TypeInfo memory_region_info = {
.parent = TYPE_OBJECT,
.name = TYPE_MEMORY_REGION,
.instance_size = sizeof(MemoryRegion),
.instance_init = memory_region_initfn,
.instance_finalize = memory_region_finalize,
};
Is this abstract? No, because with .instance_size =
sizeof(MemoryRegion), which known to be non-zero, .abstract defaults to
false.
Is such a complex default a good idea?
static const TypeInfo rng_backend_info = {
.name = TYPE_RNG_BACKEND,
.parent = TYPE_OBJECT,
.instance_size = sizeof(RngBackend),
.instance_init = rng_backend_init,
.instance_finalize = rng_backend_finalize,
.class_size = sizeof(RngBackendClass),
.class_init = rng_backend_class_init,
.abstract = true,
.interfaces = (InterfaceInfo[]) {
{ TYPE_USER_CREATABLE },
{ }
}
};
Is this abstract? Yes, because with .abstract = true, the default
doesn't matter.
How do you find all abstract TypeInfo in the source? The uninitiated
might grep for .abstract = true, and be misled. The initiated will be
annoyed instead, because grepping for *absence* of .instance_size = is
bothersome.
I suspect life could be easier going forward if we instead required
.abstract = true for interfaces, and enforced it with
assert(ti->instance_size || ti->abstract) here.
> diff --git a/tests/device-introspect-test.c b/tests/device-introspect-test.c
> index 37debc1..c5637cc 100644
> --- a/tests/device-introspect-test.c
> +++ b/tests/device-introspect-test.c
> @@ -20,18 +20,24 @@
> #include "qemu/osdep.h"
> #include "qemu-common.h"
> #include "qapi/qmp/qstring.h"
> +#include "qapi/qmp/qbool.h"
> +#include "qapi/qmp/qdict.h"
> #include "libqtest.h"
>
> const char common_args[] = "-nodefaults -machine none";
>
> -static QList *device_type_list(bool abstract)
> +static QList *qom_list_types(const char *implements, bool abstract)
> {
> QDict *resp;
> QList *ret;
> + QDict *args = qdict_new();
>
> + qdict_put(args, "abstract", qbool_from_bool(abstract));
> + if (implements) {
> + qdict_put(args, "implements", qstring_from_str(implements));
> + }
> resp = qmp("{'execute': 'qom-list-types',"
> - " 'arguments': {'implements': 'device', 'abstract': %i}}",
> - abstract);
> + " 'arguments': %p }", args);
> g_assert(qdict_haskey(resp, "return"));
> ret = qdict_get_qlist(resp, "return");
> QINCREF(ret);
> @@ -39,6 +45,11 @@ static QList *device_type_list(bool abstract)
> return ret;
> }
>
> +static QList *device_type_list(bool abstract)
> +{
> + return qom_list_types("device", abstract);
> +}
> +
> static void test_one_device(const char *type)
> {
> QDict *resp;
> @@ -110,6 +121,48 @@ static void test_device_intro_concrete(void)
> qtest_end();
> }
>
> +static void test_abstract_interfaces(void)
> +{
> + QList *all_types;
> + QList *obj_types;
> + QListEntry *ae;
> +
> + qtest_start(common_args);
> + /* qom-list-types implements=interface would return any type
> + * that implements _any_ interface (not just interface types),
> + * so use a trick to find the interface type names:
> + * - list all object types
> + * - list all types, and look for items that are not
> + * on the first list
> + */
> + all_types = qom_list_types(NULL, false);
> + obj_types = qom_list_types("object", false);
> +
> + QLIST_FOREACH_ENTRY(all_types, ae) {
> + QDict *at = qobject_to_qdict(qlist_entry_obj(ae));
> + const char *aname = qdict_get_str(at, "name");
> + QListEntry *oe;
> + const char *found = NULL;
> +
> + QLIST_FOREACH_ENTRY(obj_types, oe) {
> + QDict *ot = qobject_to_qdict(qlist_entry_obj(oe));
> + const char *oname = qdict_get_str(ot, "name");
> + if (!strcmp(aname, oname)) {
> + found = oname;
> + break;
> + }
> + }
> +
> + /* Using g_assert_cmpstr() will give more useful failure
> + * messages than g_assert(found) */
Sure this comment is worth having?
> + g_assert_cmpstr(aname, ==, found);
I'm having a mental block... what exactly is this loop nest testing?
> + }
> +
> + QDECREF(all_types);
> + QDECREF(obj_types);
> + qtest_end();
> +}
> +
> int main(int argc, char **argv)
> {
> g_test_init(&argc, &argv, NULL);
> @@ -118,6 +171,7 @@ int main(int argc, char **argv)
> qtest_add_func("device/introspect/none", test_device_intro_none);
> qtest_add_func("device/introspect/abstract", test_device_intro_abstract);
> qtest_add_func("device/introspect/concrete", test_device_intro_concrete);
> + qtest_add_func("device/introspect/abstract-interfaces",
> test_abstract_interfaces);
>
> return g_test_run();
> }
- [Qemu-devel] [PATCH for-2.9 v2] qom: Make all interface types abstract, Eduardo Habkost, 2016/12/12
- Re: [Qemu-devel] [PATCH for-2.9 v2] qom: Make all interface types abstract,
Markus Armbruster <=
- Re: [Qemu-devel] [PATCH for-2.9 v2] qom: Make all interface types abstract, Eduardo Habkost, 2016/12/14
- Re: [Qemu-devel] [PATCH for-2.9 v2] qom: Make all interface types abstract, Paolo Bonzini, 2016/12/14
- Re: [Qemu-devel] [PATCH for-2.9 v2] qom: Make all interface types abstract, Eduardo Habkost, 2016/12/14
- Re: [Qemu-devel] [PATCH for-2.9 v2] qom: Make all interface types abstract, Markus Armbruster, 2016/12/14
- Re: [Qemu-devel] [PATCH for-2.9 v2] qom: Make all interface types abstract, Paolo Bonzini, 2016/12/15
- Re: [Qemu-devel] [PATCH for-2.9 v2] qom: Make all interface types abstract, Markus Armbruster, 2016/12/19