📄 cdl2.cxx
字号:
//==========================================================================//// cdl2.cxx//// Tests for the CdlHandle class.////==========================================================================//####COPYRIGHTBEGIN####// // ----------------------------------------------------------------------------// Copyright (C) 1999, 2000 Red Hat, Inc.//// This file is part of the eCos host tools.//// This program is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 of the License, or (at your option) // any later version.// // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for // more details.// // You should have received a copy of the GNU General Public License along with// this program; if not, write to the Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.//// ----------------------------------------------------------------------------// //####COPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN#### //// Author(s): bartv// Contributors: bartv// Date: 1999-01-12// Description: Large parts of libcdl are implemented using a// CdlHandle template and a CdlRefcountSupport class.// This tests check that these both work as expected.////####DESCRIPTIONEND####//==========================================================================#include <cstdio>#include <cdlconfig.h>#include <cdl.hxx>#include <cyg/infra/cyg_ass.h>#include <cyg/infra/cyg_trac.h>#include <cyg/infra/testcase.h>#include <cstdlib>#ifndef CYGBLD_LIBCDL_USE_SMART_POINTERSintmain(int argc, char** argv){ CYG_TEST_FAIL_FINISH("Smart pointers not yet enabled - waiting for a working version of Visual C++"); return EXIT_FAILURE;}#else // CYGBLD_LIBCDL_USE_SMART_POINTERS// ----------------------------------------------------------------------------// Miscellaneous statics.// This routine controls the return value of a class1_body check_this()// operation, allowing test code to make sure that using check_this()// on a smart pointer works as expected.static bool check_this_ok = true;// ----------------------------------------------------------------------------// This test case makes use of three implementation classes. It is necessary// to have forward declarations of these, and then it is possible to define// handle classes for each one.class class01_body;class class02_body;class derived_body;typedef CdlHandle<class01_body> class01;typedef CdlHandle<class02_body> class02;typedef CdlHandle<derived_body> derived;// ----------------------------------------------------------------------------// This test needs three additional classes which are reference-counted and// which are accessed via CdlHandle smart pointers. It is necessary to start class class01_body : public CdlRefcountSupport { friend class CdlTest; public: static int class01_objects; class01_body() : CdlRefcountSupport() { class01_objects++; object_number = class01_objects; modifiable = 0; class01_body_cookie = class01_body_magic; } ~class01_body() { class01_objects--; class01_body_cookie = class01_body_invalid; } int get_number(void) { return object_number; } void modify(void) { modifiable++; } bool check_this(cyg_assert_class_zeal zeal) const { CYG_UNUSED_PARAM(cyg_assert_class_zeal, zeal); if (class01_body_magic != class01_body_cookie) { return false; } return check_this_ok; } private: // Which object is this? int object_number; int modifiable; class01_body(const class01_body&); class01_body& operator=(const class01_body&); enum { class01_body_invalid = 0, class01_body_magic = 0x015b19d6 } class01_body_cookie;};class class02_body : public CdlRefcountSupport { friend class CdlTest; public: static int class02_objects; class02_body() : CdlRefcountSupport() { class02_objects++; class02_body_cookie = class02_body_magic; } ~class02_body() { class02_objects--; class02_body_cookie = class02_body_invalid; } bool check_this(cyg_assert_class_zeal zeal) const { CYG_UNUSED_PARAM(cyg_assert_class_zeal, zeal); return class02_body_magic == class02_body_cookie; } private: class02_body(const class02_body&); class02_body& operator=(const class02_body&); enum { class02_body_invalid = 0, class02_body_magic = 0x3225c96c } class02_body_cookie;};class derived_body : public class01_body { friend class CdlTest; public: static int derived_objects; derived_body() : class01_body() { derived_objects++; derived_body_cookie = derived_body_magic; } ~derived_body() { derived_objects--; derived_body_cookie = derived_body_invalid; } bool check_this(cyg_assert_class_zeal zeal) const { if (derived_body_magic != derived_body_cookie) { return false; } return class01_body::check_this(zeal); } private: derived_body(const derived_body&); derived_body& operator=(const derived_body&); enum { derived_body_invalid = 0, derived_body_magic = 0x7ed15350 } derived_body_cookie;};int class01_body::class01_objects = 0;int class02_body::class02_objects = 0;int derived_body::derived_objects = 0;// ----------------------------------------------------------------------------// The actual test code.boolcheck_const_arg(const class01 const_ptr){ // Make sure that read-only access is allowed and goes to the right // object if (!const_ptr->check_this(cyg_quick)) { CYG_TEST_FAIL("check_this() on a constant pointer should be fine"); return false; } check_this_ok = false; if (const_ptr->check_this(cyg_quick)) { CYG_TEST_FAIL("check_this() on a constant pointer should be fine"); check_this_ok = true; return false; } check_this_ok = true; return true;}intmain(int argc, char** argv){ bool ok = true; // Make sure that smart pointers do not impose any kind of overhead. if ((sizeof(void *) != sizeof(class01)) || (sizeof(void *) != sizeof(class02)) || (sizeof(void *) != sizeof(derived))) { CYG_TEST_FAIL("smart pointers are not the same size as dumb pointers"); } else { CYG_TEST_PASS("smart pointers are the same size as dumb pointers"); } // Start by creating a number of objects to be manipulated. class01_body * class01_obj1 = new class01_body; class01_body * class01_obj2 = new class01_body; class02_body * class02_obj1 = new class02_body; derived_body * derived_obj1 = new derived_body; // Quick sanity check if ((1 != derived_body::derived_objects) || (1 != class02_body::class02_objects) || (3 != class01_body::class01_objects)) { CYG_TEST_FAIL("Testcase has created an invalid number of objects"); } // Convert the basic objects to smart pointers. If this code compiles // then the test succeeds. class01 class01_ptr1 = class01(class01_obj1); class01 class01_ptr2 = class01(class01_obj2); class02 class02_ptr1 = class02(class02_obj1); derived derived_ptr1 = derived(derived_obj1); CYG_TEST_PASS("conversion to smart pointers works"); // Also create a couple of other smart pointers. These should be // initialised to 0. class01 class01_ptr3; class01 class01_ptr4 = 0; class01 class01_ptr5 = class01(0); CYG_TEST_PASS("smart pointers can have the value zero"); // Try to dereference the smart pointers. if ((1 != class01_ptr1->get_number()) || (2 != class01_ptr2->get_number()) || (3 != derived_ptr1->get_number())) { CYG_TEST_FAIL("-> dereferencing operator broken"); } else { CYG_TEST_PASS("-> dereferencing operator functional"); } if ((1 != (*class01_ptr1).get_number()) || (2 != (*class01_ptr2).get_number()) || (3 != (*derived_ptr1).get_number())) { CYG_TEST_FAIL("* dereferencing operator broken"); } else { CYG_TEST_PASS("* dereferencing operator functional"); } // Also try to access the check_this() member functions if (!class01_ptr1->check_this(cyg_quick)) { } // Do a couple of if's. This checks that the !operator is // functional. Some of the checks are there to make sure that the // compiler does the right thing. ok = true; if (!class01_ptr1) { CYG_TEST_FAIL("!(assigned smart pointer) is true"); ok = false; } if (0 == class01_ptr1) { CYG_TEST_FAIL("0 == assigned smart pointer"); ok = false; } if (0 != class01_ptr3) { CYG_TEST_FAIL("0 != unassigned smart pointer"); ok = false; } if (class01_ptr1 == 0) { CYG_TEST_FAIL("0 == assigned smart pointer"); ok = false; } if (class01_ptr3 != 0) { CYG_TEST_FAIL("0 != unassigned smart pointer"); ok = false; } if (class01_ptr1 == class01_ptr2) { CYG_TEST_FAIL("comparing two different smart pointers succeeds"); ok = false; } if (class01_ptr1 != class01_ptr2) { // Do nothing } else { CYG_TEST_FAIL("comparing two different smart pointers succeeds"); ok = false; }#if 0 // Comparing base and derived smart pointers directly does not work yet. if (class01_ptr1 == derived_ptr1) { CYG_TEST_FAIL("comparing different base and derived pointers succeeds"); }#endif if (ok) { CYG_TEST_PASS("smart pointer comparisons work"); } // Try some assignment operators. class01_ptr3 = class01_ptr1; class01_ptr4 = derived_ptr1; class01_ptr5 = class01_ptr2; // After doing all of these assignments there should be no change in // the number of underlying objects. ok = true; if ((1 != derived_body::derived_objects) || (1 != class02_body::class02_objects) || (3 != class01_body::class01_objects)) { ok = false; CYG_TEST_FAIL("Assignment of smart pointers has changed the underlying number of objects"); } if ((class01_ptr1 != class01_ptr3) || (class01_ptr2 != class01_ptr5)) { ok = false; CYG_TEST_FAIL("Assignment of smart pointers has not worked"); } if (class01_ptr4.get_dumb_pointer() != derived_ptr1.get_dumb_pointer()) { ok = false; CYG_TEST_FAIL("Assignment of derived to base smart pointer has not worked"); } if ((2 != class01_ptr1->get_refcount()) || (2 != class01_ptr2->get_refcount()) || (2 != class01_ptr4->get_refcount()) || (2 != derived_ptr1->get_refcount())) { ok = false; CYG_TEST_FAIL("Reference counts after assignment operators do not match up"); } if (ok) { CYG_TEST_PASS("Assignment of smart pointers"); } // Now try assigning zero. Incidentally this is necessary if the underlying // objects are to be destroyed again at the end. class01_ptr3 = 0; class01_ptr4 = 0; class01_ptr5 = 0; ok = true; if (0 != class01_ptr3) { ok = false; CYG_TEST_FAIL("assigning 0 to a smart pointer does not work"); } if ((1 != class01_ptr1->get_refcount()) || (1 != class01_ptr2->get_refcount()) || (1 != derived_ptr1->get_refcount())) { ok = false; CYG_TEST_FAIL("Reference counts after assignment operators do not match up"); } if (ok) { CYG_TEST_PASS("Assigning zero to smart pointers"); } // Make sure that implicit casts to const work. This is really // a compiler test. if (check_const_arg(class01_ptr1) && check_const_arg(derived_ptr1)) { CYG_TEST_PASS("Implicit cast to const smart pointer"); } #if 0 // All of this code should fail to compile. // Applying delete to a smart pointer does not work. Use destroy() instead. delete class01_ptr1;#endif#if 0 // Attempts to do incompatible assignments should fail. class01_ptr1 = class02_ptr1;#endif#if 0 // Comparing completely different types should fail. if (class01_ptr1 == class02_ptr1) { CYG_TEST_FAIL("it should not be possible to compare objects of different types"); }#endif#if 0 { const class01 const_class01_ptr = class01_ptr1; const_class01_ptr->modify(); }#endif#if 0 { const class01 const_derived_ptr = derived_ptr1; const_derived_ptr->modify(); }#endif // Check that destroy() actually gets rid of the underlying objects. class01_ptr1.destroy(); class01_ptr2.destroy(); class02_ptr1.destroy(); derived_ptr1.destroy(); if ((0 != derived_body::derived_objects) || (0 != class02_body::class02_objects) || (0 != class01_body::class01_objects)) { CYG_TEST_FAIL("There are still objects after the smart pointers have been destroyed"); } else { CYG_TEST_PASS("Using destroy() on the smart pointers cleans up the underlying objects"); } return EXIT_SUCCESS;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -