Eo: Improved error reporting with failed constructors.
[profile/ivi/eobj.git] / tests / eo_test_general.c
1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4
5 #include <stdio.h>
6
7 #include "eo_suite.h"
8 #include "Eo.h"
9
10 #include "class_simple.h"
11
12 START_TEST(eo_simple)
13 {
14    eo_init();
15    Eo *obj = eo_add(EO_BASE_CLASS, NULL);
16    fail_if(obj);
17
18    eo_shutdown();
19 }
20 END_TEST
21
22 START_TEST(eo_data_fetch)
23 {
24    eo_init();
25
26    /* Usually should be const, not const only for the test... */
27    static Eo_Class_Description class_desc = {
28         "Simple2",
29         EO_CLASS_TYPE_REGULAR,
30         EO_CLASS_DESCRIPTION_OPS(NULL, NULL, 0),
31         NULL,
32         10,
33         NULL,
34         NULL,
35         NULL,
36         NULL
37    };
38
39    const Eo_Class *klass = eo_class_new(&class_desc, 0, EO_BASE_CLASS, NULL);
40    fail_if(!klass);
41
42    Eo *obj = eo_add(klass, NULL);
43    fail_if(!obj);
44 #ifndef NDEBUG
45    fail_if(eo_data_get(obj, SIMPLE_CLASS));
46 #endif
47    eo_unref(obj);
48
49    class_desc.data_size = 0;
50    klass = eo_class_new(&class_desc, 0, EO_BASE_CLASS, NULL);
51    fail_if(!klass);
52
53    obj = eo_add(klass, NULL);
54    fail_if(!obj);
55    fail_if(eo_data_get(obj, klass));
56    eo_unref(obj);
57
58    eo_shutdown();
59 }
60 END_TEST
61
62 START_TEST(eo_composite_tests)
63 {
64    eo_init();
65
66    Eo *obj = eo_add(SIMPLE_CLASS, NULL);
67    fail_if(!obj);
68    Eo *obj2 = eo_add(SIMPLE_CLASS, NULL);
69    fail_if(!obj2);
70
71    eo_composite_object_attach(obj, obj2);
72    eo_parent_set(obj2, NULL);
73    fail_if(eo_composite_is(obj2));
74
75    eo_unref(obj2);
76    eo_unref(obj);
77
78    eo_shutdown();
79 }
80 END_TEST
81
82 START_TEST(eo_static_classes)
83 {
84    eo_init();
85
86    static const Eo_Op_Description op_desc[] = {
87         EO_OP_DESCRIPTION(SIMPLE_SUB_ID_A_SET, "i", "Set property A"),
88         EO_OP_DESCRIPTION_SENTINEL
89    };
90
91    /* Usually should be const, not const only for the test... */
92    static Eo_Class_Description class_desc = {
93         "Simple2",
94         EO_CLASS_TYPE_REGULAR,
95         EO_CLASS_DESCRIPTION_OPS(NULL, op_desc, 1),
96         NULL,
97         0,
98         NULL,
99         NULL,
100         NULL,
101         NULL
102    };
103
104    const Eo_Class *klass = eo_class_new(&class_desc, 1, EO_BASE_CLASS, NULL);
105    fail_if(klass);
106
107    klass = eo_class_new(&class_desc, 1000, EO_BASE_CLASS, NULL);
108    fail_if(klass);
109
110    klass = eo_class_new(&class_desc, 2, EO_BASE_CLASS, NULL);
111    fail_if(!klass);
112
113    eo_shutdown();
114 }
115 END_TEST
116
117 static void
118 _man_con(Eo *obj, void *data EINA_UNUSED)
119 {
120    eo_manual_free_set(obj, EINA_TRUE);
121    eo_constructor_super(obj);
122 }
123
124 static void
125 _man_des(Eo *obj, void *data EINA_UNUSED)
126 {
127    eo_destructor_super(obj);
128    eo_manual_free_set(obj, EINA_FALSE);
129 }
130
131 START_TEST(eo_man_free)
132 {
133    eo_init();
134
135    /* Usually should be const, not const only for the test... */
136    static Eo_Class_Description class_desc = {
137         "Simple2",
138         EO_CLASS_TYPE_REGULAR,
139         EO_CLASS_DESCRIPTION_OPS(NULL, NULL, 0),
140         NULL,
141         10,
142         _man_con,
143         _man_des,
144         NULL,
145         NULL
146    };
147
148    const Eo_Class *klass = eo_class_new(&class_desc, 0, EO_BASE_CLASS, NULL);
149    fail_if(!klass);
150
151    Eo *obj = eo_add(klass, NULL);
152    fail_if(!obj);
153    eo_unref(obj);
154
155    obj = eo_add(klass, NULL);
156    fail_if(!obj);
157    eo_manual_free(obj);
158    eo_unref(obj);
159
160    class_desc.destructor = NULL;
161    klass = eo_class_new(&class_desc, 0, EO_BASE_CLASS, NULL);
162    fail_if(!klass);
163
164    obj = eo_add(klass, NULL);
165    fail_if(!obj);
166    eo_manual_free(obj);
167    eo_unref(obj);
168    eo_manual_free(obj);
169
170    obj = eo_add(klass, NULL);
171    fail_if(!obj);
172    eo_unref(obj);
173    eo_manual_free(obj);
174
175    class_desc.constructor = NULL;
176    klass = eo_class_new(&class_desc, 0, EO_BASE_CLASS, NULL);
177    fail_if(!klass);
178
179    obj = eo_add(klass, NULL);
180    fail_if(!obj);
181    eo_manual_free(obj);
182    eo_unref(obj);
183
184    obj = eo_add(klass, NULL);
185    fail_if(!obj);
186    eo_manual_free_set(obj, EINA_TRUE);
187    eo_unref(obj);
188    eo_ref(obj);
189    eo_unref(obj);
190    eo_unref(obj);
191    eo_manual_free(obj);
192
193    eo_shutdown();
194 }
195 END_TEST
196
197 START_TEST(eo_refs)
198 {
199    eo_init();
200    Eo *obj = eo_add(SIMPLE_CLASS, NULL);
201    Eo *obj2 = eo_add(SIMPLE_CLASS, NULL);
202    Eo *obj3 = eo_add(SIMPLE_CLASS, NULL);
203
204    eo_xref(obj, obj2);
205    fail_if(eo_ref_get(obj) != 2);
206    eo_xref(obj, obj3);
207    fail_if(eo_ref_get(obj) != 3);
208
209    eo_xunref(obj, obj2);
210    fail_if(eo_ref_get(obj) != 2);
211    eo_xunref(obj, obj3);
212    fail_if(eo_ref_get(obj) != 1);
213
214 #ifndef NDEBUG
215    eo_xunref(obj, obj3);
216    fail_if(eo_ref_get(obj) != 1);
217
218    eo_xref(obj, obj2);
219    fail_if(eo_ref_get(obj) != 2);
220
221    eo_xunref(obj, obj3);
222    fail_if(eo_ref_get(obj) != 2);
223
224    eo_xunref(obj, obj2);
225    fail_if(eo_ref_get(obj) != 1);
226 #endif
227
228    /* Check we don't seg if there's an extra xref. */
229    eo_xref(obj, obj2);
230    eo_unref(obj);
231
232    eo_unref(obj);
233    eo_unref(obj2);
234    eo_unref(obj3);
235
236    /* Check hierarchy */
237    obj = eo_add(SIMPLE_CLASS, NULL);
238    obj2 = eo_add(SIMPLE_CLASS, obj);
239
240    Eo *wref;
241    eo_do(obj2, eo_wref_add(&wref));
242    fail_if(!wref);
243
244    eo_unref(obj2);
245
246    fail_if(!wref); /* Parent is still holding a reference. */
247
248    eo_unref(obj);
249
250    fail_if(wref);
251
252    /* Just check it doesn't seg atm. */
253    obj = eo_add(SIMPLE_CLASS, NULL);
254    eo_ref(obj);
255    eo_unref(obj);
256    eo_unref(obj);
257
258    obj = eo_add(SIMPLE_CLASS, NULL);
259    obj2 = eo_add(SIMPLE_CLASS, obj);
260    eo_unref(obj2);
261    eo_ref(obj2);
262    eo_del(obj2);
263    eo_unref(obj);
264
265    eo_shutdown();
266 }
267 END_TEST
268
269 START_TEST(eo_weak_reference)
270 {
271    eo_init();
272
273    Eo *obj = eo_add(SIMPLE_CLASS, NULL);
274    Eo *obj2 = eo_add(SIMPLE_CLASS, NULL);
275    Eo *wref, *wref2, *wref3;
276    eo_do(obj, eo_wref_add(&wref));
277    fail_if(!wref);
278
279    eo_unref(obj);
280    fail_if(wref);
281
282    obj = eo_add(SIMPLE_CLASS, NULL);
283    eo_do(obj, eo_wref_add(&wref));
284
285    eo_ref(obj);
286    fail_if(!wref);
287
288    eo_unref(obj);
289    fail_if(!wref);
290
291    eo_unref(obj);
292    fail_if(wref);
293
294    obj = eo_add(SIMPLE_CLASS, NULL);
295
296    eo_do(obj, eo_wref_add(&wref));
297    eo_do(obj, eo_wref_del(&wref));
298    fail_if(wref);
299
300    eo_do(obj, eo_wref_add(&wref));
301    eo_do(obj2, eo_wref_del(&wref));
302    fail_if(!wref);
303    eo_wref_del_safe(&wref);
304    fail_if(wref);
305
306    wref = obj;
307    eo_do(obj, eo_wref_del(&wref));
308    fail_if(wref);
309
310    wref = wref2 = wref3 = NULL;
311    eo_do(obj, eo_wref_add(&wref), eo_wref_add(&wref2), eo_wref_add(&wref3));
312    fail_if(!wref);
313    fail_if(!wref2);
314    fail_if(!wref3);
315    eo_do(obj, eo_wref_del(&wref), eo_wref_del(&wref2), eo_wref_del(&wref3));
316    fail_if(wref);
317    fail_if(wref2);
318    fail_if(wref3);
319
320    eo_do(obj, eo_wref_add(&wref2), eo_wref_add(&wref3));
321    wref = obj;
322    eo_do(obj, eo_wref_del(&wref));
323    fail_if(wref);
324    eo_do(obj, eo_wref_del(&wref2), eo_wref_del(&wref3));
325
326    eo_unref(obj);
327    eo_unref(obj2);
328
329
330    eo_shutdown();
331 }
332 END_TEST
333
334 static void
335 _a_set(Eo *obj EINA_UNUSED, void *class_data EINA_UNUSED, va_list *list EINA_UNUSED)
336 {
337    fail_if(EINA_TRUE);
338 }
339
340 static void
341 _op_errors_class_constructor(Eo_Class *klass)
342 {
343    const Eo_Op_Func_Description func_desc[] = {
344         EO_OP_FUNC(SIMPLE_ID(SIMPLE_SUB_ID_LAST), _a_set),
345         EO_OP_FUNC(SIMPLE_ID(SIMPLE_SUB_ID_LAST + 1), _a_set),
346         EO_OP_FUNC(0x0F010111, _a_set),
347         EO_OP_FUNC_SENTINEL
348    };
349
350    eo_class_funcs_set(klass, func_desc);
351 }
352
353 START_TEST(eo_op_errors)
354 {
355    eo_init();
356
357    static const Eo_Class_Description class_desc = {
358         "Simple",
359         EO_CLASS_TYPE_REGULAR,
360         EO_CLASS_DESCRIPTION_OPS(NULL, NULL, 0),
361         NULL,
362         0,
363         NULL,
364         NULL,
365         _op_errors_class_constructor,
366         NULL
367    };
368
369    const Eo_Class *klass = eo_class_new(&class_desc, 0, SIMPLE_CLASS, NULL);
370    fail_if(!klass);
371
372    Eo *obj = eo_add(klass, NULL);
373
374    /* Out of bounds op for a legal class. */
375    fail_if(eo_do(obj, EO_BASE_ID(0x0111)));
376
377    /* Ilegal class. */
378    fail_if(eo_do(obj, 0x0F010111));
379
380    fail_if(eo_ref_get(obj) != 1);
381
382    eo_ref(obj);
383    fail_if(eo_ref_get(obj) != 2);
384
385    eo_ref(obj);
386    fail_if(eo_ref_get(obj) != 3);
387
388    eo_unref(obj);
389    fail_if(eo_ref_get(obj) != 2);
390
391    eo_unref(obj);
392    fail_if(eo_ref_get(obj) != 1);
393
394    eo_unref(obj);
395
396    obj = eo_add(SIMPLE_CLASS, NULL);
397    fail_if(!eo_do(obj, simple_a_print()));
398    fail_if(!eo_query(obj, simple_a_print()));
399    fail_if(eo_query(obj, simple_a_set(1)));
400    eo_unref(obj);
401
402    eo_shutdown();
403 }
404 END_TEST
405
406 static void
407 _fake_free_func(void *data)
408 {
409    if (!data)
410       return;
411
412    int *a = data;
413    ++*a;
414 }
415
416 START_TEST(eo_generic_data)
417 {
418    eo_init();
419    Eo *obj = eo_add(SIMPLE_CLASS, NULL);
420    void *data;
421
422    eo_do(obj, eo_base_data_set("test1", (void *) 1, NULL));
423    eo_do(obj, eo_base_data_get("test1", &data));
424    fail_if(1 != (int) data);
425    eo_do(obj, eo_base_data_del("test1"));
426    eo_do(obj, eo_base_data_get("test1", &data));
427    fail_if(data);
428
429    eo_do(obj, eo_base_data_set("test1", (void *) 1, NULL));
430    eo_do(obj, eo_base_data_set("test2", (void *) 2, NULL));
431    eo_do(obj, eo_base_data_get("test1", &data));
432    fail_if(1 != (int) data);
433    eo_do(obj, eo_base_data_get("test2", &data));
434    fail_if(2 != (int) data);
435
436    eo_do(obj, eo_base_data_get("test2", &data));
437    fail_if(2 != (int) data);
438    eo_do(obj, eo_base_data_del("test2"));
439    eo_do(obj, eo_base_data_get("test2", &data));
440    fail_if(data);
441
442    eo_do(obj, eo_base_data_get("test1", &data));
443    fail_if(1 != (int) data);
444    eo_do(obj, eo_base_data_del("test1"));
445    eo_do(obj, eo_base_data_get("test1", &data));
446    fail_if(data);
447
448    int a = 0;
449    eo_do(obj, eo_base_data_set("test3", &a, _fake_free_func));
450    eo_do(obj, eo_base_data_get("test3", &data));
451    fail_if(&a != data);
452    eo_do(obj, eo_base_data_get("test3", NULL));
453    eo_do(obj, eo_base_data_del("test3"));
454    fail_if(a != 1);
455
456    a = 0;
457    eo_do(obj, eo_base_data_set("test3", &a, _fake_free_func));
458    eo_do(obj, eo_base_data_set("test3", NULL, _fake_free_func));
459    fail_if(a != 1);
460    a = 0;
461    data = (void *) 123;
462    eo_do(obj, eo_base_data_set(NULL, &a, _fake_free_func));
463    eo_do(obj, eo_base_data_get(NULL, &data));
464    fail_if(data);
465    eo_do(obj, eo_base_data_del(NULL));
466
467    a = 0;
468    eo_do(obj, eo_base_data_set("test3", &a, _fake_free_func));
469    eo_do(obj, eo_base_data_set("test3", NULL, NULL));
470    fail_if(a != 1);
471    eo_do(obj, eo_base_data_set("test3", &a, _fake_free_func));
472
473    eo_unref(obj);
474    fail_if(a != 2);
475
476    eo_shutdown();
477 }
478 END_TEST
479
480 START_TEST(eo_magic_checks)
481 {
482    char _buf[sizeof(long)]; /* Just enough to hold eina magic + a bit more. */
483    char *buf = _buf;
484    eo_init();
485
486    memset(_buf, 1, sizeof(_buf));
487
488    Eo *obj = eo_add(SIMPLE_CLASS, (Eo *) buf);
489    fail_if(obj);
490
491    while (1)
492      {
493         obj = eo_add((Eo_Class *) buf, NULL);
494         fail_if(obj);
495
496         obj = eo_add(SIMPLE_CLASS, NULL);
497         fail_if(!obj);
498
499         fail_if(eo_do((Eo *) buf, EO_NOOP));
500         fail_if(eo_do_super((Eo *) buf, EO_NOOP));
501         fail_if(eo_class_get((Eo *) buf));
502         fail_if(eo_class_name_get((Eo_Class*) buf));
503         eo_class_funcs_set((Eo_Class *) buf, NULL);
504         eo_class_do((Eo_Class *) buf, NULL);
505         eo_class_do_super((Eo_Class *) buf, EO_NOOP);
506
507         fail_if(eo_class_new(NULL, 0, (Eo_Class *) buf), NULL);
508
509         eo_xref(obj, (Eo *) buf);
510         eo_xunref(obj, (Eo *) buf);
511         eo_xref((Eo *) buf, obj);
512         eo_xunref((Eo *) buf, obj);
513
514         eo_ref((Eo *) buf);
515         eo_unref((Eo *) buf);
516         eo_del((Eo *) buf);
517
518         fail_if(0 != eo_ref_get((Eo *) buf));
519
520         Eo *wref = NULL;
521         eo_do((Eo *) buf, eo_wref_add(&wref));
522         fail_if(wref);
523
524         fail_if(eo_parent_get((Eo *) buf));
525
526         eo_error_set((Eo *) buf);
527
528         eo_constructor_super((Eo *) buf);
529         eo_destructor_super((Eo *) buf);
530
531         fail_if(eo_data_get((Eo *) buf, SIMPLE_CLASS));
532
533         eo_composite_object_attach((Eo *) buf, obj);
534         eo_composite_object_attach(obj, (Eo *) buf);
535         eo_composite_object_detach((Eo *) buf, obj);
536         eo_composite_object_detach(obj, (Eo *) buf);
537         eo_composite_is((Eo *) buf);
538
539         eo_do(obj, eo_event_callback_forwarder_add(NULL, (Eo *) buf));
540         eo_do(obj, eo_event_callback_forwarder_del(NULL, (Eo *) buf));
541
542         eo_manual_free_set((Eo *) buf, EINA_TRUE);
543         eo_manual_free((Eo *) buf);
544
545         eo_unref(obj);
546
547         if (!buf)
548            break;
549         else
550            buf = NULL;
551      }
552
553    eo_shutdown();
554 }
555 END_TEST
556
557 void eo_test_general(TCase *tc)
558 {
559    tcase_add_test(tc, eo_generic_data);
560    tcase_add_test(tc, eo_op_errors);
561    tcase_add_test(tc, eo_simple);
562    tcase_add_test(tc, eo_weak_reference);
563    tcase_add_test(tc, eo_refs);
564    tcase_add_test(tc, eo_magic_checks);
565    tcase_add_test(tc, eo_data_fetch);
566    tcase_add_test(tc, eo_man_free);
567    tcase_add_test(tc, eo_static_classes);
568    tcase_add_test(tc, eo_composite_tests);
569 }