qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Anthony Liguori <aliguori@us.ibm.com>
To: Peter Crosthwaite <peter.crosthwaite@petalogix.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>,
	Andreas Faerber <andreas.faerber@web.de>,
	qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH 3/3] qom: add unit test for Interfaces
Date: Mon, 18 Jun 2012 08:26:03 -0500	[thread overview]
Message-ID: <4FDF2C6B.2010607@us.ibm.com> (raw)
In-Reply-To: <CAEgOgz4FOHcmdZObMe2C1pVoMYfXZX5xLaaXxf7xbi8On_DVew@mail.gmail.com>

On 06/16/2012 05:31 AM, Peter Crosthwaite wrote:
> On Thu, Jun 14, 2012 at 6:55 AM, Anthony Liguori<aliguori@us.ibm.com>  wrote:
>> Signed-off-by: Anthony Liguori<aliguori@us.ibm.com>
>
> Reviewed-by: Peter A.G. Crosthwaite<peter.crosthwaite@petalogix.com>
>
>> ---
>>   tests/Makefile      |    5 +-
>>   tests/test-object.c |  222 +++++++++++++++++++++++++++++++++++++++++++++++++++
>>   2 files changed, 226 insertions(+), 1 deletions(-)
>>   create mode 100644 tests/test-object.c
>>
>> diff --git a/tests/Makefile b/tests/Makefile
>> index d66ab19..d1f979d 100644
>> --- a/tests/Makefile
>> +++ b/tests/Makefile
>> @@ -14,6 +14,7 @@ check-unit-y += tests/test-string-input-visitor$(EXESUF)
>>   check-unit-y += tests/test-string-output-visitor$(EXESUF)
>>   check-unit-y += tests/test-coroutine$(EXESUF)
>>   check-unit-y += tests/test-visitor-serialization$(EXESUF)
>> +check-unit-y += tests/test-object$(EXESUF)
>>
>>   check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
>>
>> @@ -32,7 +33,8 @@ test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \
>>         tests/test-coroutine.o tests/test-string-output-visitor.o \
>>         tests/test-string-input-visitor.o tests/test-qmp-output-visitor.o \
>>         tests/test-qmp-input-visitor.o tests/test-qmp-input-strict.o \
>> -       tests/test-qmp-commands.o tests/test-visitor-serialization.o
>> +       tests/test-qmp-commands.o tests/test-visitor-serialization.o \
>> +       tests/test-object.o
>>
>>   test-qapi-obj-y =  $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y)
>>   test-qapi-obj-y += tests/test-qapi-visit.o tests/test-qapi-types.o
>> @@ -66,6 +68,7 @@ tests/test-qmp-input-visitor$(EXESUF): tests/test-qmp-input-visitor.o $(test-qap
>>   tests/test-qmp-input-strict$(EXESUF): tests/test-qmp-input-strict.o $(test-qapi-obj-y)
>>   tests/test-qmp-commands$(EXESUF): tests/test-qmp-commands.o tests/test-qmp-marshal.o $(test-qapi-obj-y)
>>   tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serialization.o $(test-qapi-obj-y)
>> +tests/test-object$(EXESUF): tests/test-object.o $(qom-obj-y) $(test-qapi-obj-y)
>>
>>   tests/rtc-test$(EXESUF): tests/rtc-test.o $(trace-obj-y)
>>   tests/m48t59-test$(EXESUF): tests/m48t59-test.o $(trace-obj-y)
>> diff --git a/tests/test-object.c b/tests/test-object.c
>> new file mode 100644
>> index 0000000..9f41da0
>> --- /dev/null
>> +++ b/tests/test-object.c
>> @@ -0,0 +1,222 @@
>> +/*
>> + * QEMU Object Model unit test
>> + *
>> + * Copyright IBM, Corp. 2012
>> + *
>> + * Authors:
>> + *  Anthony Liguori<aliguori@us.ibm.com>
>> + *
>> + * 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/object.h"
>> +#include "module.h"
>> +
>> +#define TYPE_HERBIVORE "herbivore"
>> +
>> +#define HERBIVORE_CLASS(klass) \
>> +    OBJECT_CLASS_CHECK(HerbivoreClass, (klass), TYPE_HERBIVORE)
>> +#define HERBIVORE_GET_CLASS(obj) \
>> +    OBJECT_GET_CLASS(HerbivoreClass, (obj), TYPE_HERBIVORE)
>> +#define HERBIVORE(obj) \
>> +    INTERFACE_CHECK(Herbivore, (obj), TYPE_HERBIVORE)
>> +
>> +typedef struct Herbivore
>> +{
>> +    Object obj;
>> +} Herbivore;
>
> All this is doing is saying Herbivores are Objects right? A user cant
> add anything to this struct given that interfaces are stateless so
> could this be simplified to
>
> typedef Object Herbivore;

This is admittedly a little wierd...

Interfaces don't exist as Objects in QOM.  They are just classes.  But it's very 
handy to be able to have a Herbivore type that you can cast objects to.

I probably need to respin this though.  INTERFACE_CHECK() asserts that an object 
implements the interface class and then just returns the obj and casts it to the 
dummy Interface object type.

A better approach would be to just teach object_dynamic_cast to do this for 
anythign that's an interface type.  That would fix the link problem you pointed 
out too.  I'll spin a v2.

Regards,

Anthony Liguori

>
> ?
>
>> +
>> +typedef struct HerbivoreClass
>> +{
>> +    InterfaceClass parent;
>> +
>> +    void (*feed_greens)(Herbivore *obj);
>> +} HerbivoreClass;
>> +
>> +static void herbivore_feed_greens(Herbivore *herbie)
>> +{
>> +    HerbivoreClass *k = HERBIVORE_GET_CLASS(herbie);
>> +
>> +    k->feed_greens(herbie);
>> +}
>> +
>> +static TypeInfo herbivore_info = {
>> +    .name = TYPE_HERBIVORE,
>> +    .parent = TYPE_INTERFACE,
>> +    .class_size = sizeof(HerbivoreClass),
>> +};
>> +
>> +#define TYPE_CARNIVORE "carnivore"
>> +#define CARNIVORE_CLASS(klass) \
>> +    OBJECT_CLASS_CHECK(CarnivoreClass, (klass), TYPE_CARNIVORE)
>> +#define CARNIVORE_GET_CLASS(obj) \
>> +    OBJECT_GET_CLASS(CarnivoreClass, (obj), TYPE_CARNIVORE)
>> +#define CARNIVORE(obj) \
>> +    INTERFACE_CHECK(Carnivore, (obj), TYPE_CARNIVORE)
>> +
>> +typedef struct Carnivore
>> +{
>> +    Object parent;
>> +} Carnivore;
>> +
>> +typedef struct CarnivoreClass
>> +{
>> +    InterfaceClass parent;
>> +
>> +    void (*feed_bugs)(Carnivore *obj);
>> +} CarnivoreClass;
>> +
>> +static void carnivore_feed_bugs(Carnivore *carnie)
>> +{
>> +    CarnivoreClass *k = CARNIVORE_GET_CLASS(carnie);
>> +
>> +    k->feed_bugs(carnie);
>> +}
>> +
>> +static TypeInfo carnivore_info = {
>> +    .name = TYPE_CARNIVORE,
>> +    .parent = TYPE_INTERFACE,
>> +    .class_size = sizeof(CarnivoreClass),
>> +};
>> +
>> +#define TYPE_REPTILE "reptile"
>> +#define REPTILE(obj) OBJECT_CHECK(Reptile, (obj), TYPE_REPTILE)
>> +
>> +typedef struct Reptile
>> +{
>> +    Object parent;
>> +} Reptile;
>> +
>> +static TypeInfo reptile_info = {
>> +    .name = TYPE_REPTILE,
>> +    .instance_size = sizeof(Reptile),
>> +    .abstract = true,
>> +    .class_size = sizeof(ObjectClass),
>> +};
>> +
>> +#define TYPE_LIZARD "lizard"
>> +#define LIZARD(obj) OBJECT_CHECK(Lizard, (obj), TYPE_LIZARD)
>> +
>> +typedef struct Lizard
>> +{
>> +    Reptile parent;
>> +} Lizard;
>> +
>> +static TypeInfo lizard_info = {
>> +    .name = TYPE_LIZARD,
>> +    .parent = TYPE_REPTILE,
>> +    .instance_size = sizeof(Lizard),
>> +    .abstract = true,
>> +};
>> +
>> +#define TYPE_IGUANA "iguana"
>> +#define IGUANA(obj) OBJECT_CHECK(Iguana, (obj), TYPE_IGUANA)
>> +
>> +typedef struct Iguana
>> +{
>> +    Lizard parent;
>> +    int greens;
>> +} Iguana;
>> +
>> +static void iguana_feed(Herbivore *herbie)
>> +{
>> +    Iguana *iggie = IGUANA(herbie);
>> +
>> +    iggie->greens++;
>> +}
>> +
>> +static void iguana_class_initfn(ObjectClass *klass, void *data)
>> +{
>> +    HerbivoreClass *iface = HERBIVORE_CLASS(klass);
>> +
>> +    iface->feed_greens = iguana_feed;
>> +}
>> +
>> +static TypeInfo iguana_info = {
>> +    .name = TYPE_IGUANA,
>> +    .parent = TYPE_LIZARD,
>> +    .instance_size = sizeof(Iguana),
>> +    .class_init = iguana_class_initfn,
>> +    .interfaces = (InterfaceInfo[]) {
>> +        { TYPE_HERBIVORE },
>> +        { }
>> +    },
>> +};
>> +
>> +#define TYPE_BEARDED_DRAGON "bearded-dragon"
>> +#define BEARDED_DRAGON(obj) OBJECT_CHECK(BeardedDragon, (obj), TYPE_BEARDED_DRAGON)
>> +
>> +typedef struct BeardedDragon
>> +{
>> +    Lizard parent;
>> +    int bugs;
>> +} BeardedDragon;
>> +
>> +static void bearded_dragon_feed(Carnivore *carnie)
>> +{
>> +    BeardedDragon *dragon = BEARDED_DRAGON(carnie);
>> +
>> +    dragon->bugs++;
>> +}
>> +
>> +static void bearded_dragon_class_initfn(ObjectClass *klass, void *data)
>> +{
>> +    CarnivoreClass *iface = CARNIVORE_CLASS(klass);
>> +
>> +    iface->feed_bugs = bearded_dragon_feed;
>> +}
>> +
>> +static TypeInfo bearded_dragon_info = {
>> +    .name = TYPE_BEARDED_DRAGON,
>> +    .parent = TYPE_LIZARD,
>> +    .instance_size = sizeof(BeardedDragon),
>> +    .class_init = bearded_dragon_class_initfn,
>> +    .interfaces = (InterfaceInfo[]) {
>> +        { TYPE_CARNIVORE },
>> +        { }
>> +    },
>> +};
>> +
>> +static void basic_init(void)
>> +{
>> +    BeardedDragon dragon;
>> +    Iguana iguana;
>> +
>> +    object_initialize(&dragon, TYPE_BEARDED_DRAGON);
>> +
>> +    g_assert_cmpint(dragon.bugs, ==, 0);
>> +    carnivore_feed_bugs(CARNIVORE(&dragon));
>> +    g_assert_cmpint(dragon.bugs, ==, 1);
>> +
>> +    object_finalize(&dragon);
>> +
>> +    object_initialize(&iguana, TYPE_IGUANA);
>> +
>> +    g_assert_cmpint(iguana.greens, ==, 0);
>> +    herbivore_feed_greens(HERBIVORE(&iguana));
>> +    g_assert_cmpint(iguana.greens, ==, 1);
>> +
>> +    object_finalize(&iguana);
>> +}
>> +
>> +int main(int argc, char **argv)
>> +{
>> +    g_test_init(&argc,&argv, NULL);
>> +
>> +    module_call_init(MODULE_INIT_QOM);
>> +
>> +    type_register_static(&carnivore_info);
>> +    type_register_static(&herbivore_info);
>> +
>> +    type_register_static(&reptile_info);
>> +    type_register_static(&lizard_info);
>> +    type_register_static(&iguana_info);
>> +    type_register_static(&bearded_dragon_info);
>> +
>> +    g_test_add_func("/basic/init", basic_init);
>> +
>> +    g_test_run();
>> +
>> +    return 0;
>> +}
>> --
>> 1.7.5.4
>>
>

  reply	other threads:[~2012-06-18 13:27 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-06-13 20:54 [Qemu-devel] [PATCH 0/3] qom: refactor Interfaces Anthony Liguori
2012-06-13 20:55 ` [Qemu-devel] [PATCH 1/3] tests: fix dependency inclusion Anthony Liguori
2012-06-14 13:08   ` Andreas Färber
2012-06-14 13:12     ` Paolo Bonzini
2012-06-13 20:55 ` [Qemu-devel] [PATCH 2/3] qom: reimplement Interfaces Anthony Liguori
2012-06-16 10:47   ` Peter Crosthwaite
2012-06-22 11:29     ` Peter Crosthwaite
2012-06-13 20:55 ` [Qemu-devel] [PATCH 3/3] qom: add unit test for Interfaces Anthony Liguori
2012-06-16 10:31   ` Peter Crosthwaite
2012-06-18 13:26     ` Anthony Liguori [this message]
2012-06-18 13:46       ` Peter Crosthwaite
2012-06-18 13:51         ` Andreas Färber
2012-06-18 14:54           ` Anthony Liguori
2012-06-14  9:10 ` [Qemu-devel] [PATCH 0/3] qom: refactor Interfaces Paolo Bonzini
2012-06-15  4:58 ` Peter Crosthwaite

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=4FDF2C6B.2010607@us.ibm.com \
    --to=aliguori@us.ibm.com \
    --cc=andreas.faerber@web.de \
    --cc=pbonzini@redhat.com \
    --cc=peter.crosthwaite@petalogix.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).