]>
Commit | Line | Data |
---|---|---|
747b0cb4 EH |
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 | ||
681c28a3 | 25 | #include "qemu/osdep.h" |
747b0cb4 | 26 | |
a27bd6c7 | 27 | #include "hw/qdev-properties.h" |
99a0b036 | 28 | #include "qom/object.h" |
ce189ab2 | 29 | #include "qapi/error.h" |
99a0b036 | 30 | #include "qapi/visitor.h" |
747b0cb4 EH |
31 | |
32 | ||
33 | #define TYPE_STATIC_PROPS "static_prop_type" | |
db1015e9 | 34 | typedef struct MyType MyType; |
8110fa1d EH |
35 | DECLARE_INSTANCE_CHECKER(MyType, STATIC_TYPE, |
36 | TYPE_STATIC_PROPS) | |
747b0cb4 | 37 | |
3caca555 EH |
38 | #define TYPE_SUBCLASS "static_prop_subtype" |
39 | ||
747b0cb4 EH |
40 | #define PROP_DEFAULT 100 |
41 | ||
db1015e9 | 42 | struct MyType { |
747b0cb4 EH |
43 | DeviceState parent_obj; |
44 | ||
45 | uint32_t prop1; | |
46 | uint32_t prop2; | |
db1015e9 | 47 | }; |
747b0cb4 EH |
48 | |
49 | static Property static_props[] = { | |
50 | DEFINE_PROP_UINT32("prop1", MyType, prop1, PROP_DEFAULT), | |
51 | DEFINE_PROP_UINT32("prop2", MyType, prop2, PROP_DEFAULT), | |
52 | DEFINE_PROP_END_OF_LIST() | |
53 | }; | |
54 | ||
55 | static void static_prop_class_init(ObjectClass *oc, void *data) | |
56 | { | |
57 | DeviceClass *dc = DEVICE_CLASS(oc); | |
58 | ||
59 | dc->realize = NULL; | |
4f67d30b | 60 | device_class_set_props(dc, static_props); |
747b0cb4 EH |
61 | } |
62 | ||
63 | static const TypeInfo static_prop_type = { | |
64 | .name = TYPE_STATIC_PROPS, | |
65 | .parent = TYPE_DEVICE, | |
66 | .instance_size = sizeof(MyType), | |
67 | .class_init = static_prop_class_init, | |
68 | }; | |
69 | ||
3caca555 EH |
70 | static const TypeInfo subclass_type = { |
71 | .name = TYPE_SUBCLASS, | |
72 | .parent = TYPE_STATIC_PROPS, | |
73 | }; | |
74 | ||
747b0cb4 | 75 | /* Test simple static property setting to default value */ |
2177801a | 76 | static void test_static_prop_subprocess(void) |
747b0cb4 EH |
77 | { |
78 | MyType *mt; | |
79 | ||
80 | mt = STATIC_TYPE(object_new(TYPE_STATIC_PROPS)); | |
ce189ab2 | 81 | qdev_realize(DEVICE(mt), NULL, &error_fatal); |
747b0cb4 EH |
82 | |
83 | g_assert_cmpuint(mt->prop1, ==, PROP_DEFAULT); | |
84 | } | |
85 | ||
2177801a EH |
86 | static void test_static_prop(void) |
87 | { | |
88 | g_test_trap_subprocess("/qdev/properties/static/default/subprocess", 0, 0); | |
89 | g_test_trap_assert_passed(); | |
90 | g_test_trap_assert_stderr(""); | |
91 | g_test_trap_assert_stdout(""); | |
92 | } | |
93 | ||
e6add65b MAL |
94 | static void register_global_properties(GlobalProperty *props) |
95 | { | |
96 | int i; | |
97 | ||
98 | for (i = 0; props[i].driver != NULL; i++) { | |
99 | qdev_prop_register_global(props + i); | |
100 | } | |
101 | } | |
102 | ||
103 | ||
747b0cb4 | 104 | /* Test setting of static property using global properties */ |
2177801a | 105 | static void test_static_globalprop_subprocess(void) |
747b0cb4 EH |
106 | { |
107 | MyType *mt; | |
108 | static GlobalProperty props[] = { | |
109 | { TYPE_STATIC_PROPS, "prop1", "200" }, | |
110 | {} | |
111 | }; | |
112 | ||
e6add65b | 113 | register_global_properties(props); |
747b0cb4 EH |
114 | |
115 | mt = STATIC_TYPE(object_new(TYPE_STATIC_PROPS)); | |
ce189ab2 | 116 | qdev_realize(DEVICE(mt), NULL, &error_fatal); |
747b0cb4 EH |
117 | |
118 | g_assert_cmpuint(mt->prop1, ==, 200); | |
119 | g_assert_cmpuint(mt->prop2, ==, PROP_DEFAULT); | |
120 | } | |
121 | ||
2177801a EH |
122 | static void test_static_globalprop(void) |
123 | { | |
124 | g_test_trap_subprocess("/qdev/properties/static/global/subprocess", 0, 0); | |
125 | g_test_trap_assert_passed(); | |
126 | g_test_trap_assert_stderr(""); | |
127 | g_test_trap_assert_stdout(""); | |
128 | } | |
129 | ||
99a0b036 | 130 | #define TYPE_DYNAMIC_PROPS "dynamic-prop-type" |
8110fa1d EH |
131 | DECLARE_INSTANCE_CHECKER(MyType, DYNAMIC_TYPE, |
132 | TYPE_DYNAMIC_PROPS) | |
99a0b036 | 133 | |
08ac80cd EH |
134 | #define TYPE_UNUSED_HOTPLUG "hotplug-type" |
135 | #define TYPE_UNUSED_NOHOTPLUG "nohotplug-type" | |
136 | ||
d7bce999 EB |
137 | static void prop1_accessor(Object *obj, Visitor *v, const char *name, |
138 | void *opaque, Error **errp) | |
99a0b036 EH |
139 | { |
140 | MyType *mt = DYNAMIC_TYPE(obj); | |
141 | ||
51e72bc1 | 142 | visit_type_uint32(v, name, &mt->prop1, errp); |
99a0b036 EH |
143 | } |
144 | ||
d7bce999 EB |
145 | static void prop2_accessor(Object *obj, Visitor *v, const char *name, |
146 | void *opaque, Error **errp) | |
99a0b036 EH |
147 | { |
148 | MyType *mt = DYNAMIC_TYPE(obj); | |
149 | ||
51e72bc1 | 150 | visit_type_uint32(v, name, &mt->prop2, errp); |
99a0b036 EH |
151 | } |
152 | ||
153 | static void dynamic_instance_init(Object *obj) | |
154 | { | |
155 | object_property_add(obj, "prop1", "uint32", prop1_accessor, prop1_accessor, | |
d2623129 | 156 | NULL, NULL); |
99a0b036 | 157 | object_property_add(obj, "prop2", "uint32", prop2_accessor, prop2_accessor, |
d2623129 | 158 | NULL, NULL); |
99a0b036 EH |
159 | } |
160 | ||
161 | static void dynamic_class_init(ObjectClass *oc, void *data) | |
162 | { | |
163 | DeviceClass *dc = DEVICE_CLASS(oc); | |
164 | ||
165 | dc->realize = NULL; | |
166 | } | |
167 | ||
168 | ||
169 | static const TypeInfo dynamic_prop_type = { | |
170 | .name = TYPE_DYNAMIC_PROPS, | |
171 | .parent = TYPE_DEVICE, | |
172 | .instance_size = sizeof(MyType), | |
173 | .instance_init = dynamic_instance_init, | |
174 | .class_init = dynamic_class_init, | |
175 | }; | |
176 | ||
08ac80cd EH |
177 | static void hotplug_class_init(ObjectClass *oc, void *data) |
178 | { | |
179 | DeviceClass *dc = DEVICE_CLASS(oc); | |
180 | ||
181 | dc->realize = NULL; | |
182 | dc->hotpluggable = true; | |
183 | } | |
184 | ||
185 | static const TypeInfo hotplug_type = { | |
186 | .name = TYPE_UNUSED_HOTPLUG, | |
187 | .parent = TYPE_DEVICE, | |
188 | .instance_size = sizeof(MyType), | |
189 | .instance_init = dynamic_instance_init, | |
190 | .class_init = hotplug_class_init, | |
191 | }; | |
192 | ||
193 | static void nohotplug_class_init(ObjectClass *oc, void *data) | |
194 | { | |
195 | DeviceClass *dc = DEVICE_CLASS(oc); | |
196 | ||
197 | dc->realize = NULL; | |
198 | dc->hotpluggable = false; | |
199 | } | |
200 | ||
201 | static const TypeInfo nohotplug_type = { | |
202 | .name = TYPE_UNUSED_NOHOTPLUG, | |
203 | .parent = TYPE_DEVICE, | |
204 | .instance_size = sizeof(MyType), | |
205 | .instance_init = dynamic_instance_init, | |
206 | .class_init = nohotplug_class_init, | |
207 | }; | |
208 | ||
209 | #define TYPE_NONDEVICE "nondevice-type" | |
210 | ||
211 | static const TypeInfo nondevice_type = { | |
212 | .name = TYPE_NONDEVICE, | |
213 | .parent = TYPE_OBJECT, | |
214 | }; | |
215 | ||
70e98b23 | 216 | /* Test setting of dynamic properties using global properties */ |
2177801a | 217 | static void test_dynamic_globalprop_subprocess(void) |
99a0b036 EH |
218 | { |
219 | MyType *mt; | |
220 | static GlobalProperty props[] = { | |
55df8e1a MAL |
221 | { TYPE_DYNAMIC_PROPS, "prop1", "101", }, |
222 | { TYPE_DYNAMIC_PROPS, "prop2", "102", }, | |
223 | { TYPE_DYNAMIC_PROPS"-bad", "prop3", "103", }, | |
224 | { TYPE_UNUSED_HOTPLUG, "prop4", "104", }, | |
225 | { TYPE_UNUSED_NOHOTPLUG, "prop5", "105", }, | |
226 | { TYPE_NONDEVICE, "prop6", "106", }, | |
99a0b036 EH |
227 | {} |
228 | }; | |
ef240523 | 229 | int global_error; |
99a0b036 | 230 | |
e6add65b | 231 | register_global_properties(props); |
99a0b036 EH |
232 | |
233 | mt = DYNAMIC_TYPE(object_new(TYPE_DYNAMIC_PROPS)); | |
ce189ab2 | 234 | qdev_realize(DEVICE(mt), NULL, &error_fatal); |
99a0b036 EH |
235 | |
236 | g_assert_cmpuint(mt->prop1, ==, 101); | |
237 | g_assert_cmpuint(mt->prop2, ==, 102); | |
ef240523 MAL |
238 | global_error = qdev_prop_check_globals(); |
239 | g_assert_cmpuint(global_error, ==, 1); | |
b3ce84fe EH |
240 | g_assert(props[0].used); |
241 | g_assert(props[1].used); | |
242 | g_assert(!props[2].used); | |
243 | g_assert(!props[3].used); | |
244 | g_assert(!props[4].used); | |
245 | g_assert(!props[5].used); | |
99a0b036 EH |
246 | } |
247 | ||
2177801a EH |
248 | static void test_dynamic_globalprop(void) |
249 | { | |
250 | g_test_trap_subprocess("/qdev/properties/dynamic/global/subprocess", 0, 0); | |
251 | g_test_trap_assert_passed(); | |
252 | g_test_trap_assert_stderr_unmatched("*prop1*"); | |
253 | g_test_trap_assert_stderr_unmatched("*prop2*"); | |
61d9282c YL |
254 | g_test_trap_assert_stderr( |
255 | "*warning: global dynamic-prop-type-bad.prop3 has invalid class name*"); | |
08ac80cd | 256 | g_test_trap_assert_stderr_unmatched("*prop4*"); |
61d9282c YL |
257 | g_test_trap_assert_stderr( |
258 | "*warning: global nohotplug-type.prop5=105 not used*"); | |
259 | g_test_trap_assert_stderr( | |
260 | "*warning: global nondevice-type.prop6 has invalid class name*"); | |
b3ce84fe EH |
261 | g_test_trap_assert_stdout(""); |
262 | } | |
263 | ||
3caca555 EH |
264 | /* Test if global props affecting subclasses are applied in the right order */ |
265 | static void test_subclass_global_props(void) | |
266 | { | |
267 | MyType *mt; | |
268 | /* Global properties must be applied in the order they were registered */ | |
269 | static GlobalProperty props[] = { | |
270 | { TYPE_STATIC_PROPS, "prop1", "101" }, | |
271 | { TYPE_SUBCLASS, "prop1", "102" }, | |
272 | { TYPE_SUBCLASS, "prop2", "103" }, | |
273 | { TYPE_STATIC_PROPS, "prop2", "104" }, | |
274 | {} | |
275 | }; | |
276 | ||
e6add65b | 277 | register_global_properties(props); |
3caca555 EH |
278 | |
279 | mt = STATIC_TYPE(object_new(TYPE_SUBCLASS)); | |
ce189ab2 | 280 | qdev_realize(DEVICE(mt), NULL, &error_fatal); |
3caca555 EH |
281 | |
282 | g_assert_cmpuint(mt->prop1, ==, 102); | |
283 | g_assert_cmpuint(mt->prop2, ==, 104); | |
284 | } | |
285 | ||
747b0cb4 EH |
286 | int main(int argc, char **argv) |
287 | { | |
288 | g_test_init(&argc, &argv, NULL); | |
289 | ||
290 | module_call_init(MODULE_INIT_QOM); | |
291 | type_register_static(&static_prop_type); | |
3caca555 | 292 | type_register_static(&subclass_type); |
99a0b036 | 293 | type_register_static(&dynamic_prop_type); |
08ac80cd EH |
294 | type_register_static(&hotplug_type); |
295 | type_register_static(&nohotplug_type); | |
296 | type_register_static(&nondevice_type); | |
747b0cb4 | 297 | |
2177801a EH |
298 | g_test_add_func("/qdev/properties/static/default/subprocess", |
299 | test_static_prop_subprocess); | |
300 | g_test_add_func("/qdev/properties/static/default", | |
301 | test_static_prop); | |
302 | ||
303 | g_test_add_func("/qdev/properties/static/global/subprocess", | |
304 | test_static_globalprop_subprocess); | |
305 | g_test_add_func("/qdev/properties/static/global", | |
306 | test_static_globalprop); | |
307 | ||
308 | g_test_add_func("/qdev/properties/dynamic/global/subprocess", | |
309 | test_dynamic_globalprop_subprocess); | |
310 | g_test_add_func("/qdev/properties/dynamic/global", | |
311 | test_dynamic_globalprop); | |
747b0cb4 | 312 | |
3caca555 EH |
313 | g_test_add_func("/qdev/properties/global/subclass", |
314 | test_subclass_global_props); | |
315 | ||
747b0cb4 EH |
316 | g_test_run(); |
317 | ||
318 | return 0; | |
319 | } |