qemu/tests/test-qdev-global-props.c
<<
>>
Prefs
   1/*
   2 *  Test code for qdev global-properties handling
   3 *
   4 *  Copyright (c) 2012 Red Hat Inc.
   5 *
   6 * Permission is hereby granted, free of charge, to any person obtaining a copy
   7 * of this software and associated documentation files (the "Software"), to deal
   8 * in the Software without restriction, including without limitation the rights
   9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 * copies of the Software, and to permit persons to whom the Software is
  11 * furnished to do so, subject to the following conditions:
  12 *
  13 * The above copyright notice and this permission notice shall be included in
  14 * all copies or substantial portions of the Software.
  15 *
  16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 * THE SOFTWARE.
  23 */
  24
  25#include "qemu/osdep.h"
  26
  27#include "hw/qdev-properties.h"
  28#include "qom/object.h"
  29#include "qapi/error.h"
  30#include "qapi/visitor.h"
  31
  32
  33#define TYPE_STATIC_PROPS "static_prop_type"
  34#define STATIC_TYPE(obj) \
  35    OBJECT_CHECK(MyType, (obj), TYPE_STATIC_PROPS)
  36
  37#define TYPE_SUBCLASS "static_prop_subtype"
  38
  39#define PROP_DEFAULT 100
  40
  41typedef struct MyType {
  42    DeviceState parent_obj;
  43
  44    uint32_t prop1;
  45    uint32_t prop2;
  46} MyType;
  47
  48static Property static_props[] = {
  49    DEFINE_PROP_UINT32("prop1", MyType, prop1, PROP_DEFAULT),
  50    DEFINE_PROP_UINT32("prop2", MyType, prop2, PROP_DEFAULT),
  51    DEFINE_PROP_END_OF_LIST()
  52};
  53
  54static void static_prop_class_init(ObjectClass *oc, void *data)
  55{
  56    DeviceClass *dc = DEVICE_CLASS(oc);
  57
  58    dc->realize = NULL;
  59    device_class_set_props(dc, static_props);
  60}
  61
  62static const TypeInfo static_prop_type = {
  63    .name = TYPE_STATIC_PROPS,
  64    .parent = TYPE_DEVICE,
  65    .instance_size = sizeof(MyType),
  66    .class_init = static_prop_class_init,
  67};
  68
  69static const TypeInfo subclass_type = {
  70    .name = TYPE_SUBCLASS,
  71    .parent = TYPE_STATIC_PROPS,
  72};
  73
  74/* Test simple static property setting to default value */
  75static void test_static_prop_subprocess(void)
  76{
  77    MyType *mt;
  78
  79    mt = STATIC_TYPE(object_new(TYPE_STATIC_PROPS));
  80    qdev_realize(DEVICE(mt), NULL, &error_fatal);
  81
  82    g_assert_cmpuint(mt->prop1, ==, PROP_DEFAULT);
  83}
  84
  85static void test_static_prop(void)
  86{
  87    g_test_trap_subprocess("/qdev/properties/static/default/subprocess", 0, 0);
  88    g_test_trap_assert_passed();
  89    g_test_trap_assert_stderr("");
  90    g_test_trap_assert_stdout("");
  91}
  92
  93static void register_global_properties(GlobalProperty *props)
  94{
  95    int i;
  96
  97    for (i = 0; props[i].driver != NULL; i++) {
  98        qdev_prop_register_global(props + i);
  99    }
 100}
 101
 102
 103/* Test setting of static property using global properties */
 104static void test_static_globalprop_subprocess(void)
 105{
 106    MyType *mt;
 107    static GlobalProperty props[] = {
 108        { TYPE_STATIC_PROPS, "prop1", "200" },
 109        {}
 110    };
 111
 112    register_global_properties(props);
 113
 114    mt = STATIC_TYPE(object_new(TYPE_STATIC_PROPS));
 115    qdev_realize(DEVICE(mt), NULL, &error_fatal);
 116
 117    g_assert_cmpuint(mt->prop1, ==, 200);
 118    g_assert_cmpuint(mt->prop2, ==, PROP_DEFAULT);
 119}
 120
 121static void test_static_globalprop(void)
 122{
 123    g_test_trap_subprocess("/qdev/properties/static/global/subprocess", 0, 0);
 124    g_test_trap_assert_passed();
 125    g_test_trap_assert_stderr("");
 126    g_test_trap_assert_stdout("");
 127}
 128
 129#define TYPE_DYNAMIC_PROPS "dynamic-prop-type"
 130#define DYNAMIC_TYPE(obj) \
 131    OBJECT_CHECK(MyType, (obj), TYPE_DYNAMIC_PROPS)
 132
 133#define TYPE_UNUSED_HOTPLUG   "hotplug-type"
 134#define TYPE_UNUSED_NOHOTPLUG "nohotplug-type"
 135
 136static void prop1_accessor(Object *obj, Visitor *v, const char *name,
 137                           void *opaque, Error **errp)
 138{
 139    MyType *mt = DYNAMIC_TYPE(obj);
 140
 141    visit_type_uint32(v, name, &mt->prop1, errp);
 142}
 143
 144static void prop2_accessor(Object *obj, Visitor *v, const char *name,
 145                           void *opaque, Error **errp)
 146{
 147    MyType *mt = DYNAMIC_TYPE(obj);
 148
 149    visit_type_uint32(v, name, &mt->prop2, errp);
 150}
 151
 152static void dynamic_instance_init(Object *obj)
 153{
 154    object_property_add(obj, "prop1", "uint32", prop1_accessor, prop1_accessor,
 155                        NULL, NULL);
 156    object_property_add(obj, "prop2", "uint32", prop2_accessor, prop2_accessor,
 157                        NULL, NULL);
 158}
 159
 160static void dynamic_class_init(ObjectClass *oc, void *data)
 161{
 162    DeviceClass *dc = DEVICE_CLASS(oc);
 163
 164    dc->realize = NULL;
 165}
 166
 167
 168static const TypeInfo dynamic_prop_type = {
 169    .name = TYPE_DYNAMIC_PROPS,
 170    .parent = TYPE_DEVICE,
 171    .instance_size = sizeof(MyType),
 172    .instance_init = dynamic_instance_init,
 173    .class_init = dynamic_class_init,
 174};
 175
 176static void hotplug_class_init(ObjectClass *oc, void *data)
 177{
 178    DeviceClass *dc = DEVICE_CLASS(oc);
 179
 180    dc->realize = NULL;
 181    dc->hotpluggable = true;
 182}
 183
 184static const TypeInfo hotplug_type = {
 185    .name = TYPE_UNUSED_HOTPLUG,
 186    .parent = TYPE_DEVICE,
 187    .instance_size = sizeof(MyType),
 188    .instance_init = dynamic_instance_init,
 189    .class_init = hotplug_class_init,
 190};
 191
 192static void nohotplug_class_init(ObjectClass *oc, void *data)
 193{
 194    DeviceClass *dc = DEVICE_CLASS(oc);
 195
 196    dc->realize = NULL;
 197    dc->hotpluggable = false;
 198}
 199
 200static const TypeInfo nohotplug_type = {
 201    .name = TYPE_UNUSED_NOHOTPLUG,
 202    .parent = TYPE_DEVICE,
 203    .instance_size = sizeof(MyType),
 204    .instance_init = dynamic_instance_init,
 205    .class_init = nohotplug_class_init,
 206};
 207
 208#define TYPE_NONDEVICE "nondevice-type"
 209
 210static const TypeInfo nondevice_type = {
 211    .name = TYPE_NONDEVICE,
 212    .parent = TYPE_OBJECT,
 213};
 214
 215/* Test setting of dynamic properties using global properties */
 216static void test_dynamic_globalprop_subprocess(void)
 217{
 218    MyType *mt;
 219    static GlobalProperty props[] = {
 220        { TYPE_DYNAMIC_PROPS, "prop1", "101", },
 221        { TYPE_DYNAMIC_PROPS, "prop2", "102", },
 222        { TYPE_DYNAMIC_PROPS"-bad", "prop3", "103", },
 223        { TYPE_UNUSED_HOTPLUG, "prop4", "104", },
 224        { TYPE_UNUSED_NOHOTPLUG, "prop5", "105", },
 225        { TYPE_NONDEVICE, "prop6", "106", },
 226        {}
 227    };
 228    int global_error;
 229
 230    register_global_properties(props);
 231
 232    mt = DYNAMIC_TYPE(object_new(TYPE_DYNAMIC_PROPS));
 233    qdev_realize(DEVICE(mt), NULL, &error_fatal);
 234
 235    g_assert_cmpuint(mt->prop1, ==, 101);
 236    g_assert_cmpuint(mt->prop2, ==, 102);
 237    global_error = qdev_prop_check_globals();
 238    g_assert_cmpuint(global_error, ==, 1);
 239    g_assert(props[0].used);
 240    g_assert(props[1].used);
 241    g_assert(!props[2].used);
 242    g_assert(!props[3].used);
 243    g_assert(!props[4].used);
 244    g_assert(!props[5].used);
 245}
 246
 247static void test_dynamic_globalprop(void)
 248{
 249    g_test_trap_subprocess("/qdev/properties/dynamic/global/subprocess", 0, 0);
 250    g_test_trap_assert_passed();
 251    g_test_trap_assert_stderr_unmatched("*prop1*");
 252    g_test_trap_assert_stderr_unmatched("*prop2*");
 253    g_test_trap_assert_stderr("*warning: global dynamic-prop-type-bad.prop3 has invalid class name\n*");
 254    g_test_trap_assert_stderr_unmatched("*prop4*");
 255    g_test_trap_assert_stderr("*warning: global nohotplug-type.prop5=105 not used\n*");
 256    g_test_trap_assert_stderr("*warning: global nondevice-type.prop6 has invalid class name\n*");
 257    g_test_trap_assert_stdout("");
 258}
 259
 260/* Test if global props affecting subclasses are applied in the right order */
 261static void test_subclass_global_props(void)
 262{
 263    MyType *mt;
 264    /* Global properties must be applied in the order they were registered */
 265    static GlobalProperty props[] = {
 266        { TYPE_STATIC_PROPS, "prop1", "101" },
 267        { TYPE_SUBCLASS,     "prop1", "102" },
 268        { TYPE_SUBCLASS,     "prop2", "103" },
 269        { TYPE_STATIC_PROPS, "prop2", "104" },
 270        {}
 271    };
 272
 273    register_global_properties(props);
 274
 275    mt = STATIC_TYPE(object_new(TYPE_SUBCLASS));
 276    qdev_realize(DEVICE(mt), NULL, &error_fatal);
 277
 278    g_assert_cmpuint(mt->prop1, ==, 102);
 279    g_assert_cmpuint(mt->prop2, ==, 104);
 280}
 281
 282int main(int argc, char **argv)
 283{
 284    g_test_init(&argc, &argv, NULL);
 285
 286    module_call_init(MODULE_INIT_QOM);
 287    type_register_static(&static_prop_type);
 288    type_register_static(&subclass_type);
 289    type_register_static(&dynamic_prop_type);
 290    type_register_static(&hotplug_type);
 291    type_register_static(&nohotplug_type);
 292    type_register_static(&nondevice_type);
 293
 294    g_test_add_func("/qdev/properties/static/default/subprocess",
 295                    test_static_prop_subprocess);
 296    g_test_add_func("/qdev/properties/static/default",
 297                    test_static_prop);
 298
 299    g_test_add_func("/qdev/properties/static/global/subprocess",
 300                    test_static_globalprop_subprocess);
 301    g_test_add_func("/qdev/properties/static/global",
 302                    test_static_globalprop);
 303
 304    g_test_add_func("/qdev/properties/dynamic/global/subprocess",
 305                    test_dynamic_globalprop_subprocess);
 306    g_test_add_func("/qdev/properties/dynamic/global",
 307                    test_dynamic_globalprop);
 308
 309    g_test_add_func("/qdev/properties/global/subclass",
 310                    test_subclass_global_props);
 311
 312    g_test_run();
 313
 314    return 0;
 315}
 316