From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:36574) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SgbzV-0003ER-GC for qemu-devel@nongnu.org; Mon, 18 Jun 2012 09:27:43 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SgbzO-0003Pv-LN for qemu-devel@nongnu.org; Mon, 18 Jun 2012 09:27:37 -0400 Received: from e39.co.us.ibm.com ([32.97.110.160]:39471) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SgbzO-0003PS-Bc for qemu-devel@nongnu.org; Mon, 18 Jun 2012 09:27:30 -0400 Received: from /spool/local by e39.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 18 Jun 2012 07:27:25 -0600 Received: from d03relay05.boulder.ibm.com (d03relay05.boulder.ibm.com [9.17.195.107]) by d03dlp02.boulder.ibm.com (Postfix) with ESMTP id 925943E4004F for ; Mon, 18 Jun 2012 13:27:20 +0000 (WET) Received: from d03av05.boulder.ibm.com (d03av05.boulder.ibm.com [9.17.195.85]) by d03relay05.boulder.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q5IDR2Gu115348 for ; Mon, 18 Jun 2012 07:27:04 -0600 Received: from d03av05.boulder.ibm.com (loopback [127.0.0.1]) by d03av05.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q5IDQsbA025933 for ; Mon, 18 Jun 2012 07:26:54 -0600 Message-ID: <4FDF2C6B.2010607@us.ibm.com> Date: Mon, 18 Jun 2012 08:26:03 -0500 From: Anthony Liguori MIME-Version: 1.0 References: <1339620902-4481-1-git-send-email-aliguori@us.ibm.com> <1339620902-4481-4-git-send-email-aliguori@us.ibm.com> In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [PATCH 3/3] qom: add unit test for Interfaces List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Peter Crosthwaite Cc: Paolo Bonzini , Andreas Faerber , qemu-devel@nongnu.org On 06/16/2012 05:31 AM, Peter Crosthwaite wrote: > On Thu, Jun 14, 2012 at 6:55 AM, Anthony Liguori wrote: >> Signed-off-by: Anthony Liguori > > Reviewed-by: Peter A.G. Crosthwaite > >> --- >> 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 >> + * >> + * 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 >> >