]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - tools/src/libcdl/testsuite/libcdl/cdl2.cxx
Initial revision
[karo-tx-redboot.git] / tools / src / libcdl / testsuite / libcdl / cdl2.cxx
1 //==========================================================================
2 //
3 //      cdl2.cxx
4 //
5 //      Tests for the CdlHandle class.
6 //
7 //==========================================================================
8 //####COPYRIGHTBEGIN####
9 //                                                                          
10 // ----------------------------------------------------------------------------
11 // Copyright (C) 1999, 2000 Red Hat, Inc.
12 //
13 // This file is part of the eCos host tools.
14 //
15 // This program is free software; you can redistribute it and/or modify it 
16 // under the terms of the GNU General Public License as published by the Free 
17 // Software Foundation; either version 2 of the License, or (at your option) 
18 // any later version.
19 // 
20 // This program is distributed in the hope that it will be useful, but WITHOUT 
21 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
22 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
23 // more details.
24 // 
25 // You should have received a copy of the GNU General Public License along with
26 // this program; if not, write to the Free Software Foundation, Inc., 
27 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
28 //
29 // ----------------------------------------------------------------------------
30 //                                                                          
31 //####COPYRIGHTEND####
32 //==========================================================================
33 //#####DESCRIPTIONBEGIN####                                             
34 //
35 // Author(s):           bartv
36 // Contributors:        bartv
37 // Date:                1999-01-12
38 // Description:         Large parts of libcdl are implemented using a
39 //                      CdlHandle template and a CdlRefcountSupport class.
40 //                      This tests check that these both work as expected.
41 //
42 //####DESCRIPTIONEND####
43 //==========================================================================
44
45 #include <cstdio>
46 #include <cdlconfig.h>
47 #include <cdl.hxx>
48 #include <cyg/infra/cyg_ass.h>
49 #include <cyg/infra/cyg_trac.h>
50 #include <cyg/infra/testcase.h>
51 #include <cstdlib>
52
53 #ifndef CYGBLD_LIBCDL_USE_SMART_POINTERS
54 int
55 main(int argc, char** argv)
56 {
57     CYG_TEST_FAIL_FINISH("Smart pointers not yet enabled - waiting for a working version of Visual C++");
58     return EXIT_FAILURE;
59 }
60 #else // CYGBLD_LIBCDL_USE_SMART_POINTERS
61 // ----------------------------------------------------------------------------
62 // Miscellaneous statics.
63
64 // This routine controls the return value of a class1_body check_this()
65 // operation, allowing test code to make sure that using check_this()
66 // on a smart pointer works as expected.
67 static bool check_this_ok = true;
68
69 // ----------------------------------------------------------------------------
70 // This test case makes use of three implementation classes. It is necessary
71 // to have forward declarations of these, and then it is possible to define
72 // handle classes for each one.
73 class class01_body;
74 class class02_body;
75 class derived_body;
76
77 typedef CdlHandle<class01_body> class01;
78 typedef CdlHandle<class02_body> class02;
79 typedef CdlHandle<derived_body> derived;
80
81 // ----------------------------------------------------------------------------
82 // This test needs three additional classes which are reference-counted and
83 // which are accessed via CdlHandle smart pointers. It is necessary to start 
84
85 class class01_body : public CdlRefcountSupport {
86
87     friend class CdlTest;
88     
89   public:
90
91     static int class01_objects;
92     class01_body() : CdlRefcountSupport() {
93         class01_objects++;
94         object_number = class01_objects;
95         modifiable    = 0;
96         class01_body_cookie = class01_body_magic;
97     }
98     ~class01_body() {
99         class01_objects--;
100         class01_body_cookie = class01_body_invalid;
101     }
102     int
103     get_number(void) {
104         return object_number;
105     }
106     void
107     modify(void) {
108         modifiable++;
109     }
110     bool check_this(cyg_assert_class_zeal zeal) const {
111         CYG_UNUSED_PARAM(cyg_assert_class_zeal, zeal);
112         if (class01_body_magic != class01_body_cookie) {
113             return false;
114         }
115         return check_this_ok;
116     }
117     
118   private:
119     // Which object is this?
120     int object_number;
121     int modifiable;
122     
123     class01_body(const class01_body&);
124     class01_body& operator=(const class01_body&);
125     enum {
126         class01_body_invalid     = 0,
127         class01_body_magic       = 0x015b19d6
128     } class01_body_cookie;
129 };
130
131 class class02_body : public CdlRefcountSupport {
132
133     friend class CdlTest;
134     
135   public:
136     static int class02_objects;
137     class02_body() : CdlRefcountSupport() {
138         class02_objects++;
139         class02_body_cookie = class02_body_magic;
140     }
141     ~class02_body() {
142         class02_objects--;
143         class02_body_cookie = class02_body_invalid;
144     }
145
146     bool check_this(cyg_assert_class_zeal zeal) const {
147         CYG_UNUSED_PARAM(cyg_assert_class_zeal, zeal);
148         return class02_body_magic == class02_body_cookie;
149     }
150
151   private:
152     class02_body(const class02_body&);
153     class02_body& operator=(const class02_body&);
154     enum {
155         class02_body_invalid     = 0,
156         class02_body_magic       = 0x3225c96c
157     } class02_body_cookie;
158 };
159
160 class derived_body : public class01_body {
161
162     friend class CdlTest;
163     
164   public:
165     static int derived_objects;
166     derived_body() : class01_body() {
167         derived_objects++;
168         derived_body_cookie = derived_body_magic;
169     }
170     ~derived_body() {
171         derived_objects--;
172         derived_body_cookie = derived_body_invalid;
173     }
174     bool check_this(cyg_assert_class_zeal zeal) const {
175         if (derived_body_magic != derived_body_cookie) {
176             return false;
177         }
178         return class01_body::check_this(zeal);
179     }
180
181   private:
182     derived_body(const derived_body&);
183     derived_body& operator=(const derived_body&);
184     enum {
185         derived_body_invalid    = 0,
186         derived_body_magic      = 0x7ed15350
187     } derived_body_cookie;
188 };
189
190 int class01_body::class01_objects   = 0;
191 int class02_body::class02_objects   = 0;
192 int derived_body::derived_objects   = 0;
193
194 // ----------------------------------------------------------------------------
195 // The actual test code.
196
197 bool
198 check_const_arg(const class01 const_ptr)
199 {
200     // Make sure that read-only access is allowed and goes to the right
201     // object
202     if (!const_ptr->check_this(cyg_quick)) {
203         CYG_TEST_FAIL("check_this() on a constant pointer should be fine");
204         return false;
205     }
206     check_this_ok = false;
207     if (const_ptr->check_this(cyg_quick)) {
208         CYG_TEST_FAIL("check_this() on a constant pointer should be fine");
209         check_this_ok = true;
210         return false;
211     }
212     check_this_ok = true;
213     return true;
214 }
215
216 int
217 main(int argc, char** argv)
218 {
219     bool ok = true;
220
221     // Make sure that smart pointers do not impose any kind of overhead.
222     if ((sizeof(void *) != sizeof(class01)) ||
223         (sizeof(void *) != sizeof(class02)) ||
224         (sizeof(void *) != sizeof(derived))) {
225
226         CYG_TEST_FAIL("smart pointers are not the same size as dumb pointers");
227     } else {
228         CYG_TEST_PASS("smart pointers are the same size as dumb pointers");
229     }
230     
231     // Start by creating a number of objects to be manipulated.
232     class01_body *      class01_obj1    = new class01_body;
233     class01_body *      class01_obj2    = new class01_body;
234     class02_body *      class02_obj1    = new class02_body;
235     derived_body *      derived_obj1    = new derived_body;
236
237     // Quick sanity check
238     if ((1 != derived_body::derived_objects) ||
239         (1 != class02_body::class02_objects) ||
240         (3 != class01_body::class01_objects)) {
241         CYG_TEST_FAIL("Testcase has created an invalid number of objects");
242     }
243
244     // Convert the basic objects to smart pointers. If this code compiles
245     // then the test succeeds.
246     class01     class01_ptr1    = class01(class01_obj1);
247     class01     class01_ptr2    = class01(class01_obj2);
248     class02     class02_ptr1    = class02(class02_obj1);
249     derived     derived_ptr1    = derived(derived_obj1);
250     CYG_TEST_PASS("conversion to smart pointers works");
251
252     // Also create a couple of other smart pointers. These should be
253     // initialised to 0.
254     class01      class01_ptr3;
255     class01      class01_ptr4     = 0;
256     class01      class01_ptr5     = class01(0);
257     CYG_TEST_PASS("smart pointers can have the value zero");
258
259     // Try to dereference the smart pointers.
260     if ((1 != class01_ptr1->get_number()) ||
261         (2 != class01_ptr2->get_number()) ||
262         (3 != derived_ptr1->get_number())) {
263         CYG_TEST_FAIL("-> dereferencing operator broken");
264     } else {
265         CYG_TEST_PASS("-> dereferencing operator functional");
266     }
267     if ((1 != (*class01_ptr1).get_number()) ||
268         (2 != (*class01_ptr2).get_number()) ||
269         (3 != (*derived_ptr1).get_number())) {
270         CYG_TEST_FAIL("* dereferencing operator broken");
271     } else {
272         CYG_TEST_PASS("* dereferencing operator functional");
273     }
274
275     // Also try to access the check_this() member functions
276     if (!class01_ptr1->check_this(cyg_quick)) {
277     }
278     
279     // Do a couple of if's. This checks that the !operator is
280     // functional. Some of the checks are there to make sure that the
281     // compiler does the right thing.
282     ok = true;
283     if (!class01_ptr1) {
284         CYG_TEST_FAIL("!(assigned smart pointer) is true");
285         ok = false;
286     }
287     if (0 == class01_ptr1) {
288         CYG_TEST_FAIL("0 == assigned smart pointer");
289         ok = false;
290     }
291     if (0 != class01_ptr3) {
292         CYG_TEST_FAIL("0 != unassigned smart pointer");
293         ok = false;
294     }
295     if (class01_ptr1 == 0) {
296         CYG_TEST_FAIL("0 == assigned smart pointer");
297         ok = false;
298     }
299     if (class01_ptr3 != 0) {
300         CYG_TEST_FAIL("0 != unassigned smart pointer");
301         ok = false;
302     }
303     if (class01_ptr1 == class01_ptr2) {
304         CYG_TEST_FAIL("comparing two different smart pointers succeeds");
305         ok = false;
306     }
307     if (class01_ptr1 != class01_ptr2) {
308         // Do nothing
309     } else {
310         CYG_TEST_FAIL("comparing two different smart pointers succeeds");
311         ok = false;
312     }
313 #if 0
314     // Comparing base and derived smart pointers directly does not work yet.
315     if (class01_ptr1 == derived_ptr1) {
316         CYG_TEST_FAIL("comparing different base and derived pointers succeeds");
317     }
318 #endif
319     if (ok) {
320         CYG_TEST_PASS("smart pointer comparisons work");
321     }
322     
323     // Try some  assignment operators.
324     class01_ptr3 = class01_ptr1;
325     class01_ptr4 = derived_ptr1;
326     class01_ptr5 = class01_ptr2;
327
328     // After doing all of these assignments there should be no change in
329     // the number of underlying objects.
330     ok = true;
331     if ((1 != derived_body::derived_objects) ||
332         (1 != class02_body::class02_objects)   ||
333         (3 != class01_body::class01_objects)) {
334         ok = false;
335         CYG_TEST_FAIL("Assignment of smart pointers has changed the underlying number of objects");
336     }
337     if ((class01_ptr1 != class01_ptr3) ||
338         (class01_ptr2 != class01_ptr5)) {
339         ok = false;
340         CYG_TEST_FAIL("Assignment of smart pointers has not worked");
341     }
342     if (class01_ptr4.get_dumb_pointer() != derived_ptr1.get_dumb_pointer()) {
343         ok = false;
344         CYG_TEST_FAIL("Assignment of derived to base smart pointer has not worked");
345     }
346     if ((2 != class01_ptr1->get_refcount()) ||
347         (2 != class01_ptr2->get_refcount()) ||
348         (2 != class01_ptr4->get_refcount()) ||
349         (2 != derived_ptr1->get_refcount())) {
350         ok = false;
351         CYG_TEST_FAIL("Reference counts after assignment operators do not match up");
352     }
353     if (ok) {
354         CYG_TEST_PASS("Assignment of smart pointers");
355     }
356
357     // Now try assigning zero. Incidentally this is necessary if the underlying
358     // objects are to be destroyed again at the end.
359     class01_ptr3 = 0;
360     class01_ptr4 = 0;
361     class01_ptr5 = 0;
362
363     ok = true;
364     if (0 != class01_ptr3) {
365         ok = false;
366         CYG_TEST_FAIL("assigning 0 to a smart pointer does not work");
367     }
368     if ((1 != class01_ptr1->get_refcount()) ||
369         (1 != class01_ptr2->get_refcount()) ||
370         (1 != derived_ptr1->get_refcount())) {
371         ok = false;
372         CYG_TEST_FAIL("Reference counts after assignment operators do not match up");
373     }
374     if (ok) {
375         CYG_TEST_PASS("Assigning zero to smart pointers");
376     }
377
378     // Make sure that implicit casts to const work. This is really
379     // a compiler test.
380     if (check_const_arg(class01_ptr1) &&
381         check_const_arg(derived_ptr1)) {
382         CYG_TEST_PASS("Implicit cast to const smart pointer");
383     }
384     
385 #if 0
386     // All of this code should fail to compile.
387     // Applying delete to a smart pointer does not work. Use destroy() instead.
388     delete class01_ptr1;
389 #endif
390 #if 0
391     // Attempts to do incompatible assignments should fail.
392     class01_ptr1 = class02_ptr1;
393 #endif
394 #if 0    
395     // Comparing completely different types should fail.
396     if (class01_ptr1 == class02_ptr1) {
397         CYG_TEST_FAIL("it should not be possible to compare objects of different types");
398     }
399 #endif
400 #if 0
401     {
402         const class01 const_class01_ptr = class01_ptr1;
403         const_class01_ptr->modify();
404     }
405 #endif
406 #if 0
407     {
408         const class01 const_derived_ptr = derived_ptr1;
409         const_derived_ptr->modify();
410     }
411 #endif
412     
413     // Check that destroy() actually gets rid of the underlying objects.
414     class01_ptr1.destroy();
415     class01_ptr2.destroy();
416     class02_ptr1.destroy();
417     derived_ptr1.destroy();
418     if ((0 != derived_body::derived_objects) ||
419         (0 != class02_body::class02_objects)    ||
420         (0 != class01_body::class01_objects)) {
421         CYG_TEST_FAIL("There are still objects after the smart pointers have been destroyed");
422     } else {
423         CYG_TEST_PASS("Using destroy() on the smart pointers cleans up the underlying objects");
424     }
425
426     return EXIT_SUCCESS;
427 }
428 #endif