Signed-off-by: Anthony Liguori <aligu...@us.ibm.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 <aligu...@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; + +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