1 //==========================================================================
5 // Tests for the CdlHandle class.
7 //==========================================================================
8 //####COPYRIGHTBEGIN####
10 // ----------------------------------------------------------------------------
11 // Copyright (C) 1999, 2000 Red Hat, Inc.
13 // This file is part of the eCos host tools.
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)
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
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.
29 // ----------------------------------------------------------------------------
31 //####COPYRIGHTEND####
32 //==========================================================================
33 //#####DESCRIPTIONBEGIN####
36 // Contributors: bartv
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.
42 //####DESCRIPTIONEND####
43 //==========================================================================
46 #include <cdlconfig.h>
48 #include <cyg/infra/cyg_ass.h>
49 #include <cyg/infra/cyg_trac.h>
50 #include <cyg/infra/testcase.h>
53 #ifndef CYGBLD_LIBCDL_USE_SMART_POINTERS
55 main(int argc, char** argv)
57 CYG_TEST_FAIL_FINISH("Smart pointers not yet enabled - waiting for a working version of Visual C++");
60 #else // CYGBLD_LIBCDL_USE_SMART_POINTERS
61 // ----------------------------------------------------------------------------
62 // Miscellaneous statics.
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;
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.
77 typedef CdlHandle<class01_body> class01;
78 typedef CdlHandle<class02_body> class02;
79 typedef CdlHandle<derived_body> derived;
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
85 class class01_body : public CdlRefcountSupport {
91 static int class01_objects;
92 class01_body() : CdlRefcountSupport() {
94 object_number = class01_objects;
96 class01_body_cookie = class01_body_magic;
100 class01_body_cookie = class01_body_invalid;
104 return object_number;
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) {
115 return check_this_ok;
119 // Which object is this?
123 class01_body(const class01_body&);
124 class01_body& operator=(const class01_body&);
126 class01_body_invalid = 0,
127 class01_body_magic = 0x015b19d6
128 } class01_body_cookie;
131 class class02_body : public CdlRefcountSupport {
133 friend class CdlTest;
136 static int class02_objects;
137 class02_body() : CdlRefcountSupport() {
139 class02_body_cookie = class02_body_magic;
143 class02_body_cookie = class02_body_invalid;
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;
152 class02_body(const class02_body&);
153 class02_body& operator=(const class02_body&);
155 class02_body_invalid = 0,
156 class02_body_magic = 0x3225c96c
157 } class02_body_cookie;
160 class derived_body : public class01_body {
162 friend class CdlTest;
165 static int derived_objects;
166 derived_body() : class01_body() {
168 derived_body_cookie = derived_body_magic;
172 derived_body_cookie = derived_body_invalid;
174 bool check_this(cyg_assert_class_zeal zeal) const {
175 if (derived_body_magic != derived_body_cookie) {
178 return class01_body::check_this(zeal);
182 derived_body(const derived_body&);
183 derived_body& operator=(const derived_body&);
185 derived_body_invalid = 0,
186 derived_body_magic = 0x7ed15350
187 } derived_body_cookie;
190 int class01_body::class01_objects = 0;
191 int class02_body::class02_objects = 0;
192 int derived_body::derived_objects = 0;
194 // ----------------------------------------------------------------------------
195 // The actual test code.
198 check_const_arg(const class01 const_ptr)
200 // Make sure that read-only access is allowed and goes to the right
202 if (!const_ptr->check_this(cyg_quick)) {
203 CYG_TEST_FAIL("check_this() on a constant pointer should be fine");
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;
212 check_this_ok = true;
217 main(int argc, char** argv)
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))) {
226 CYG_TEST_FAIL("smart pointers are not the same size as dumb pointers");
228 CYG_TEST_PASS("smart pointers are the same size as dumb pointers");
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;
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");
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");
252 // Also create a couple of other smart pointers. These should be
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");
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");
265 CYG_TEST_PASS("-> dereferencing operator functional");
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");
272 CYG_TEST_PASS("* dereferencing operator functional");
275 // Also try to access the check_this() member functions
276 if (!class01_ptr1->check_this(cyg_quick)) {
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.
284 CYG_TEST_FAIL("!(assigned smart pointer) is true");
287 if (0 == class01_ptr1) {
288 CYG_TEST_FAIL("0 == assigned smart pointer");
291 if (0 != class01_ptr3) {
292 CYG_TEST_FAIL("0 != unassigned smart pointer");
295 if (class01_ptr1 == 0) {
296 CYG_TEST_FAIL("0 == assigned smart pointer");
299 if (class01_ptr3 != 0) {
300 CYG_TEST_FAIL("0 != unassigned smart pointer");
303 if (class01_ptr1 == class01_ptr2) {
304 CYG_TEST_FAIL("comparing two different smart pointers succeeds");
307 if (class01_ptr1 != class01_ptr2) {
310 CYG_TEST_FAIL("comparing two different smart pointers succeeds");
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");
320 CYG_TEST_PASS("smart pointer comparisons work");
323 // Try some assignment operators.
324 class01_ptr3 = class01_ptr1;
325 class01_ptr4 = derived_ptr1;
326 class01_ptr5 = class01_ptr2;
328 // After doing all of these assignments there should be no change in
329 // the number of underlying objects.
331 if ((1 != derived_body::derived_objects) ||
332 (1 != class02_body::class02_objects) ||
333 (3 != class01_body::class01_objects)) {
335 CYG_TEST_FAIL("Assignment of smart pointers has changed the underlying number of objects");
337 if ((class01_ptr1 != class01_ptr3) ||
338 (class01_ptr2 != class01_ptr5)) {
340 CYG_TEST_FAIL("Assignment of smart pointers has not worked");
342 if (class01_ptr4.get_dumb_pointer() != derived_ptr1.get_dumb_pointer()) {
344 CYG_TEST_FAIL("Assignment of derived to base smart pointer has not worked");
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())) {
351 CYG_TEST_FAIL("Reference counts after assignment operators do not match up");
354 CYG_TEST_PASS("Assignment of smart pointers");
357 // Now try assigning zero. Incidentally this is necessary if the underlying
358 // objects are to be destroyed again at the end.
364 if (0 != class01_ptr3) {
366 CYG_TEST_FAIL("assigning 0 to a smart pointer does not work");
368 if ((1 != class01_ptr1->get_refcount()) ||
369 (1 != class01_ptr2->get_refcount()) ||
370 (1 != derived_ptr1->get_refcount())) {
372 CYG_TEST_FAIL("Reference counts after assignment operators do not match up");
375 CYG_TEST_PASS("Assigning zero to smart pointers");
378 // Make sure that implicit casts to const work. This is really
380 if (check_const_arg(class01_ptr1) &&
381 check_const_arg(derived_ptr1)) {
382 CYG_TEST_PASS("Implicit cast to const smart pointer");
386 // All of this code should fail to compile.
387 // Applying delete to a smart pointer does not work. Use destroy() instead.
391 // Attempts to do incompatible assignments should fail.
392 class01_ptr1 = class02_ptr1;
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");
402 const class01 const_class01_ptr = class01_ptr1;
403 const_class01_ptr->modify();
408 const class01 const_derived_ptr = derived_ptr1;
409 const_derived_ptr->modify();
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");
423 CYG_TEST_PASS("Using destroy() on the smart pointers cleans up the underlying objects");