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
>>
>
next prev parent 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.