0ec0f5761af00fa62bf155eb9b7f193e46ab0e5f
[synfig.git] / ETL / trunk / test / handle.cpp
1 /*! ========================================================================
2 ** Extended Template and Library Test Suite
3 ** Handle Template Class Test
4 ** $Id$
5 **
6 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
7 **
8 ** This package is free software; you can redistribute it and/or
9 ** modify it under the terms of the GNU General Public License as
10 ** published by the Free Software Foundation; either version 2 of
11 ** the License, or (at your option) any later version.
12 **
13 ** This package is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 ** General Public License for more details.
17 **
18 ** === N O T E S ===========================================================
19 **
20 ** ========================================================================= */
21
22 /* === H E A D E R S ======================================================= */
23
24 #include <ETL/handle>
25 #include <list>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string>
29 #include <map>
30 #include <vector>
31
32 /* === M A C R O S ========================================================= */
33
34 #define NUMBER_OF_OBJECTS       40000
35 using namespace std;
36
37 /* === C L A S S E S ======================================================= */
38
39 struct my_test_obj : public etl::rshared_object
40 {
41         static int instance_count;
42         int my_id;
43         my_test_obj(int my_id=0):my_id(my_id)
44         {
45                 instance_count++;
46         }
47
48         virtual ~my_test_obj()
49         {
50                 if(instance_count==0)
51                         printf("Error, instance count is going past zero!\n");
52                 instance_count--;
53         }
54
55         bool operator<(const my_test_obj &rhs)const
56         {
57                 return my_id<rhs.my_id;
58         }
59 };
60
61 struct my_other_test_obj : public my_test_obj
62 {
63         static int instance_count;
64         my_other_test_obj(int my_id=0):my_test_obj(my_id)
65         {
66                 instance_count++;
67         }
68         virtual ~my_other_test_obj()
69         {
70                 if(instance_count==0)
71                         printf("Error, instance count is going past zero!\n");
72                 instance_count--;
73         }
74 };
75
76 int my_test_obj::instance_count=0;
77 int my_other_test_obj::instance_count=0;
78
79 typedef etl::handle<my_test_obj> obj_handle;
80 typedef etl::rhandle<my_test_obj> robj_handle;
81 typedef etl::handle<my_other_test_obj> other_obj_handle;
82 typedef list< obj_handle > obj_list;
83 typedef list< other_obj_handle > other_obj_list;
84 typedef list< robj_handle > robj_list;
85
86 int handle_basic_test()
87 {
88         printf("handle: Size of a handle: %u\n",(unsigned int)sizeof(etl::handle<int>));
89         printf("handle: Size of a loose_handle: %u\n",(unsigned int)sizeof(etl::loose_handle<int>));
90         printf("handle: Size of a rhandle: %u\n",(unsigned int)sizeof(etl::rhandle<int>));
91         printf("handle: Size of a shared_object: %u\n",(unsigned int)sizeof(etl::shared_object));
92         printf("handle: Size of a rshared_object: %u\n",(unsigned int)sizeof(etl::rshared_object));
93
94         printf("handle: Basic test: ");
95         my_test_obj::instance_count=0;
96
97         {
98                 etl::handle<my_test_obj> obj_handle(new my_test_obj(rand()));
99         }
100
101         if(my_test_obj::instance_count!=0)
102         {
103                 printf("FAILED!\n");
104                 printf(__FILE__":%d: on create/distroy, instance count=%d, should be zero.\n",__LINE__,my_test_obj::instance_count);
105                 return 1;
106         }
107
108         {
109                 map<string,etl::handle<my_test_obj> > my_map;
110                 etl::handle<my_test_obj> obj_handle(new my_test_obj(rand()));
111                 my_map["bleh"]=obj_handle;
112         }
113
114         if(my_test_obj::instance_count!=0)
115         {
116                 printf("FAILED!\n");
117                 printf(__FILE__":%d: on create/distroy, instance count=%d, should be zero.\n",__LINE__,my_test_obj::instance_count);
118                 return 1;
119         }
120
121         etl::handle<my_test_obj> obj_handle(new my_test_obj(rand()));
122
123         if(obj_handle != obj_handle.constant())
124         {
125                 printf("FAILED!\n");
126                 printf(__FILE__":%d: on call to handle<>::constant().\n",__LINE__);
127                 return 1;
128         }
129
130         printf("PASSED\n");
131
132         return 0;
133 }
134
135 int handle_general_use_test(void)
136 {
137         printf("handle: General-use test: ");
138         my_test_obj::instance_count=0;
139
140         obj_list my_list, my_other_list;
141         int i;
142
143         for(i=0;i<NUMBER_OF_OBJECTS;i++)
144                 my_list.push_back( obj_handle(new my_test_obj(rand())) );
145
146         my_other_list=my_list;
147         if(my_test_obj::instance_count!=NUMBER_OF_OBJECTS)
148         {
149                 printf("FAILED!\n");
150                 printf(__FILE__":%d: On copy, instance count=%d, should be %d.\n",__LINE__,my_test_obj::instance_count,NUMBER_OF_OBJECTS);
151                 return 1;
152         }
153
154         my_list.sort();
155         if(my_test_obj::instance_count!=NUMBER_OF_OBJECTS)
156         {
157                 printf("FAILED!\n");
158                 printf(__FILE__":%d: On copy, instance count=%d, should be %d.\n",__LINE__,my_test_obj::instance_count,NUMBER_OF_OBJECTS);
159                 return 1;
160         }
161
162         my_list.clear();
163         if(my_test_obj::instance_count!=NUMBER_OF_OBJECTS)
164         {
165                 printf("FAILED!\n");
166                 printf(__FILE__":%d: On copy's clear, instance count=%d, should be %d.\n",__LINE__,my_test_obj::instance_count,NUMBER_OF_OBJECTS);
167                 return 1;
168         }
169
170         {
171                 obj_handle a(new my_test_obj(27)), b(new my_test_obj(42));
172                 a.swap(b);
173                 if (a->my_id != 42 || b->my_id != 27)
174                 {
175                         printf("FAILED!\n");
176                         printf(__FILE__":%d: On swap (27,42) gave (%d,%d), should be (42,27).\n",__LINE__,a->my_id,b->my_id);
177                         return 1;
178                 }
179         }
180
181         my_other_list.clear();
182         if(my_test_obj::instance_count)
183         {
184                 printf("FAILED!\n");
185                 printf(__FILE__":%d: On clear, instance count=%d, should be zero.\n",__LINE__,my_test_obj::instance_count);
186                 return 1;
187         }
188
189         printf("PASSED\n");
190
191         return 0;
192 }
193
194         struct ListItem
195         {
196                 robj_handle obj;
197                 int bleh;
198                 int blah;
199                 ListItem(robj_handle obj,int bleh=1, int blah=2):
200                         obj(obj),bleh(bleh),blah(blah) { }
201         };
202
203 int rhandle_general_use_test(void)
204 {
205
206
207         printf("rhandle: General-use test: ");
208         my_test_obj::instance_count=0;
209
210         robj_list my_list;
211         int i;
212
213         robj_handle obj=        new my_test_obj(rand());
214         for(i=0;i<NUMBER_OF_OBJECTS;i++)
215                 my_list.push_back(obj);
216
217         obj_list my_other_list(my_list.begin(),my_list.end());
218
219
220
221         if(obj.count()!=NUMBER_OF_OBJECTS*2+1)
222         {
223                 printf("FAILED!\n");
224                 printf(__FILE__":%d: On copy, handle count=%d, should be %d.\n",__LINE__,obj.count(),NUMBER_OF_OBJECTS*2+1);
225                 return 1;
226         }
227
228         if(obj.rcount()!=NUMBER_OF_OBJECTS+1)
229         {
230                 printf("FAILED!\n");
231                 printf(__FILE__":%d: On copy, rhandle count=%d, should be %d.\n",__LINE__,obj.rcount(),NUMBER_OF_OBJECTS+1);
232                 return 1;
233         }
234
235         my_list.sort();
236         if(obj.rcount()!=NUMBER_OF_OBJECTS+1)
237         {
238                 printf("FAILED!\n");
239                 printf(__FILE__":%d: On copy, instance count=%d, should be %d.\n",__LINE__,obj.rcount(),NUMBER_OF_OBJECTS+1);
240                 return 1;
241         }
242
243         {robj_handle bleh(obj);}
244
245         if(obj.rcount()!=NUMBER_OF_OBJECTS+1)
246         {
247                 printf("FAILED!\n");
248                 printf(__FILE__":%d: On copy, instance count=%d, should be %d.\n",__LINE__,obj.rcount(),NUMBER_OF_OBJECTS+1);
249                 return 1;
250         }
251
252         my_other_list.clear();
253
254         if(obj.rcount()!=obj.count())
255         {
256                 printf("FAILED!\n");
257                 printf(__FILE__":%d: On copy's clear, handle count (%d) != rhandle count (%d)\n",__LINE__,obj.count(),obj.rcount());
258                 return 1;
259         }
260
261         if(obj.rcount()!=NUMBER_OF_OBJECTS+1)
262         {
263                 printf("FAILED!\n");
264                 printf(__FILE__":%d: On copy's clear, instance count=%d, should be %d.\n",__LINE__,obj.rcount(),NUMBER_OF_OBJECTS+1);
265                 return 1;
266         }
267
268         robj_handle new_obj=    new my_test_obj(rand());
269
270         int replacements=obj.replace(new_obj);
271
272         if(replacements!=NUMBER_OF_OBJECTS+1)
273         {
274                 printf("FAILED!\n");
275                 printf(__FILE__":%d: Only managed to replace %d, should have replaced %d\n",__LINE__,replacements,NUMBER_OF_OBJECTS+1);
276                 return 1;
277         }
278
279         if(obj!=new_obj)
280         {
281                 printf("FAILED!\n");
282                 printf(__FILE__":%d: On replace, handles should be equal.\n",__LINE__);
283                 return 1;
284         }
285
286         {
287                 robj_handle bleh(obj);
288                 robj_handle blah(obj.get());
289         }
290
291
292         my_list.clear();
293         obj.detach();
294         new_obj.detach();
295
296         if(my_test_obj::instance_count)
297         {
298                 printf("FAILED!\n");
299                 printf(__FILE__":%d: On clear, instance count=%d, should be zero.\n",__LINE__,my_test_obj::instance_count);
300                 return 1;
301         }
302
303
304
305         std::vector<ListItem> my_item_list;
306         for(i=0;i<NUMBER_OF_OBJECTS;i++)
307                 my_item_list.push_back(ListItem(new my_test_obj(rand()),3,4));
308
309
310         for(i=0;i<100;i++)
311         {
312                 int src,dest;
313                 src=rand()%NUMBER_OF_OBJECTS;
314                 dest=rand()%NUMBER_OF_OBJECTS;
315                 ListItem tmp(my_item_list[src]);
316                 assert(tmp.obj.rcount()>=2);
317                 my_item_list.erase(my_item_list.begin()+src);
318                 assert(tmp.obj.rcount()>=1);
319                 my_item_list.insert(my_item_list.begin()+dest,tmp);
320                 assert(tmp.obj.rcount()>=2);
321         }
322
323         my_item_list.clear();
324
325         if(my_test_obj::instance_count)
326         {
327                 printf("FAILED!\n");
328                 printf(__FILE__":%d: On clear, instance count=%d, should be zero.\n",__LINE__,my_test_obj::instance_count);
329                 return 1;
330         }
331
332         printf("PASSED\n");
333
334         return 0;
335 }
336
337 int handle_inheritance_test(void)
338 {
339         printf("handle: Inheritance test: ");
340         my_test_obj::instance_count=0;
341         my_other_test_obj::instance_count=0;
342
343         other_obj_list my_other_list;
344         int i;
345
346         for(i=0;i<NUMBER_OF_OBJECTS;i++)
347                 my_other_list.push_back( other_obj_handle(new my_other_test_obj(rand())) );
348
349         obj_list my_list(my_other_list.begin(),my_other_list.end());
350         if(my_test_obj::instance_count!=NUMBER_OF_OBJECTS)
351         {
352                 printf("FAILED!\n");
353                 printf(__FILE__":%d: On copy, instance count=%d, should be %d.\n",__LINE__,my_test_obj::instance_count,NUMBER_OF_OBJECTS);
354                 return 1;
355         }
356
357         for(i=0;i<NUMBER_OF_OBJECTS;i++)
358                 my_list.push_back( other_obj_handle(new my_other_test_obj(rand())) );
359         if(my_other_test_obj::instance_count!=NUMBER_OF_OBJECTS*2 ||
360            my_test_obj::instance_count!=my_other_test_obj::instance_count)
361         {
362                 printf("FAILED!\n");
363                 printf(__FILE__":%d: On inherited copy, instance count=%d, should be %d.\n",__LINE__,my_test_obj::instance_count,NUMBER_OF_OBJECTS*2);
364                 return 1;
365         }
366
367         my_list.sort();
368         my_other_list.sort();
369         if(my_test_obj::instance_count!=NUMBER_OF_OBJECTS*2)
370         {
371                 printf("FAILED!\n");
372                 printf(__FILE__":%d: On sort, instance count=%d, should be %d.\n",__LINE__,my_test_obj::instance_count,NUMBER_OF_OBJECTS*2);
373                 return 1;
374         }
375
376         my_list.clear();
377         if(my_test_obj::instance_count!=NUMBER_OF_OBJECTS)
378         {
379                 printf("FAILED!\n");
380                 printf(__FILE__":%d: On clear, instance count=%d, should be %d.\n",__LINE__,my_test_obj::instance_count,NUMBER_OF_OBJECTS);
381                 return 1;
382         }
383
384         my_other_list.clear();
385         if(my_test_obj::instance_count)
386         {
387                 printf("FAILED!\n");
388                 printf(__FILE__":%d: On clear, instance count=%d, should be zero.\n",__LINE__,my_test_obj::instance_count);
389                 return 1;
390         }
391
392         printf("PASSED\n");
393
394         return 0;
395 }
396
397 void test_func(etl::handle<my_test_obj> handle)
398 {
399         if(handle) { int i=handle.count(); i++; }
400 }
401
402 int loose_handle_test(void)
403 {
404         printf("handle: loose_handle test: ");
405         my_test_obj::instance_count=0;
406
407         etl::loose_handle<my_test_obj> obj_handle_loose;
408         etl::handle<my_test_obj> obj_handle2;
409
410         {
411                 etl::handle<my_test_obj> obj_handle(new my_test_obj(rand()));
412                 if(my_test_obj::instance_count!=1)
413                 {
414                         printf("FAILED!\n");
415                         printf(__FILE__":%d: on handle assignment from new object, instance count=%d, should be 1.\n",__LINE__,my_test_obj::instance_count);
416                         return 1;
417                 }
418
419                 obj_handle_loose=obj_handle;
420                 if(obj_handle!=obj_handle_loose)
421                 {
422                         printf("FAILED!\n");
423                         printf(__FILE__":%d: on loose_handle assignment\n",__LINE__);
424                         return 1;
425                 }
426
427                 obj_handle2=obj_handle_loose;
428                 if(my_test_obj::instance_count!=1)
429                 {
430                         printf("FAILED!\n");
431                         printf(__FILE__":%d: on handle assignment from loose_handle, instance count=%d, should be 1.\n",__LINE__,my_test_obj::instance_count);
432                         return 1;
433                 }
434
435                 test_func(obj_handle_loose);
436                 if(my_test_obj::instance_count!=1)
437                 {
438                         printf("FAILED!\n");
439                         printf(__FILE__":%d: on handle assignment from loose_handle, instance count=%d, should be 1.\n",__LINE__,my_test_obj::instance_count);
440                         return 1;
441                 }
442         }
443
444         {
445                 etl::loose_handle<my_test_obj> a(new my_test_obj(27)), b(new my_test_obj(42));
446                 a.swap(b);
447                 if (a->my_id != 42 || b->my_id != 27)
448                 {
449                         printf("FAILED!\n");
450                         printf(__FILE__":%d: on loose_handle swap (27,42) gave (%d,%d), should be (42,27).\n",__LINE__,a->my_id,b->my_id);
451                         return 1;
452                 }
453         }
454
455         if(my_test_obj::instance_count!=3)
456         {
457                 printf("FAILED!\n");
458                 printf(__FILE__":%d: on create/destroy, instance count=%d, should be 3.\n",__LINE__,my_test_obj::instance_count);
459                 return 1;
460         }
461
462         printf("PASSED\n");
463         return 0;
464 }
465
466 int handle_cast_test()
467 {
468         printf("handle: casting test: ");
469
470         etl::handle<my_test_obj> obj;
471         etl::handle<my_other_test_obj> other_obj;
472         etl::loose_handle<my_other_test_obj> loose_obj;
473
474         other_obj.spawn();
475         loose_obj=other_obj;
476
477         obj=etl::handle<my_test_obj>::cast_dynamic(loose_obj);
478
479         if(obj!=other_obj)
480         {
481                 printf("FAILED!\n");
482                 printf(__FILE__":%d: on handle assignment from loose_handle.\n",__LINE__);
483                 return 1;
484         }
485
486         printf("PASSED\n");
487         return 0;
488 }
489
490 /* === E N T R Y P O I N T ================================================= */
491
492 int main()
493 {
494         int error=0;
495
496         error+=handle_basic_test();
497         error+=handle_cast_test();
498         error+=handle_general_use_test();
499         error+=handle_inheritance_test();
500         error+=loose_handle_test();
501         error+=rhandle_general_use_test();
502
503         return error;
504 }