From: Markus Armbruster <armbru@redhat.com>
To: Eduardo Habkost <ehabkost@redhat.com>
Cc: "Andreas Färber" <afaerber@suse.de>,
qemu-devel@nongnu.org, "Paolo Bonzini" <pbonzini@redhat.com>,
"Lin Ma" <lma@suse.com>
Subject: Re: [Qemu-devel] [PATCH for-2.9 v2] qom: Make all interface types abstract
Date: Wed, 14 Dec 2016 14:04:50 +0100 [thread overview]
Message-ID: <87zijyfyq5.fsf@dusky.pond.sub.org> (raw)
In-Reply-To: <1481567461-2341-1-git-send-email-ehabkost@redhat.com> (Eduardo Habkost's message of "Mon, 12 Dec 2016 16:31:01 -0200")
Eduardo Habkost <ehabkost@redhat.com> 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 <ehabkost@redhat.com>
> ---
> Changes v1 -> v2:
> * Use old-fashioned if statement instead of "|=" on bool field
> Suggested-by: Andreas Färber <afaerber@suse.de>
> * Keep "device/introspect" path prefix on unit test
> * Suggested-by: Andreas Färber <afaerber@suse.de>
> ---
> 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();
> }
next prev parent reply other threads:[~2016-12-14 13:05 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-12-12 18:31 [Qemu-devel] [PATCH for-2.9 v2] qom: Make all interface types abstract Eduardo Habkost
2016-12-14 13:04 ` Markus Armbruster [this message]
2016-12-14 13:48 ` Eduardo Habkost
2016-12-14 17:07 ` Paolo Bonzini
2016-12-14 17:45 ` Eduardo Habkost
2016-12-14 17:47 ` Markus Armbruster
2016-12-15 13:45 ` Paolo Bonzini
2016-12-19 10:21 ` Markus Armbruster
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87zijyfyq5.fsf@dusky.pond.sub.org \
--to=armbru@redhat.com \
--cc=afaerber@suse.de \
--cc=ehabkost@redhat.com \
--cc=lma@suse.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).