refcnttest.cc revision 7824
1/* 2 * Copyright (c) 2010 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Gabe Black 29 */ 30 31#include <cassert> 32#include <iostream> 33#include <list> 34 35#include "base/refcnt.hh" 36 37using namespace std; 38 39namespace { 40 41class TestRC; 42typedef list<TestRC *> LiveList; 43LiveList liveList; 44 45int 46live() 47{ 48 return liveList.size(); 49} 50 51int 52liveChange() 53{ 54 static int oldLive = 0; 55 int newLive = live(); 56 int diff = newLive - oldLive; 57 oldLive = newLive; 58 return diff; 59} 60 61class TestRC : public RefCounted 62{ 63 protected: 64 const char *_tag; 65 LiveList::iterator liveIt; 66 67 public: 68 TestRC(const char *newTag) : _tag(newTag) 69 { 70 cout << " Creating object \"" << _tag << "\"\n"; 71 liveList.push_front(this); 72 liveIt = liveList.begin(); 73 } 74 75 ~TestRC() 76 { 77 cout << " Destroying object \"" << _tag << "\"\n"; 78 liveList.erase(liveIt); 79 } 80 81 const char * 82 tag() 83 { 84 return _tag; 85 } 86 87 int testVal; 88}; 89 90typedef RefCountingPtr<TestRC> Ptr; 91 92} 93 94int 95main() 96{ 97 assert(live() == 0); 98 assert(liveChange() == 0); 99 100 // Create an empty Ptr and verify it's data pointer is NULL. 101 cout << "NULL check.\n"; 102 Ptr nullCheck; 103 assert(nullCheck.get() == NULL); 104 105 assert(liveChange() == 0); 106 107 // Construct a Ptr from a TestRC pointer. 108 cout << "Construction from pointer.\n"; 109 Ptr constFromPointer = new TestRC("construction from pointer"); 110 111 assert(liveChange() == 1); 112 113 // Construct a Ptr from an existing Ptr. 114 cout << "Construction from a Ptr.\n"; 115 Ptr constFromPtr = constFromPointer; 116 117 assert(liveChange() == 0); 118 119 // Test a Ptr being destroyed. 120 cout << "Destroying a Ptr.\n"; 121 Ptr *ptrPtr = new Ptr(new TestRC("destroying a ptr")); 122 assert(liveChange() == 1); 123 delete ptrPtr; 124 assert(liveChange() == -1); 125 126 // Test assignment from a pointer and from a Ptr. 127 cout << "Assignment operators.\n"; 128 Ptr assignmentTarget; 129 TestRC *assignmentSourcePointer = new TestRC("assignment source 1"); 130 assert(liveChange() == 1); 131 assignmentTarget = assignmentSourcePointer; 132 assert(liveChange() == 0); 133 assignmentTarget = NULL; 134 assert(liveChange() == -1); 135 Ptr assignmentSourcePtr(new TestRC("assignment source 2")); 136 assert(liveChange() == 1); 137 assignmentTarget = assignmentSourcePtr; 138 assert(liveChange() == 0); 139 assignmentSourcePtr = NULL; 140 assert(liveChange() == 0); 141 assignmentTarget = NULL; 142 assert(liveChange() == -1); 143 144 // Test access to members of the pointed to class and dereferencing. 145 cout << "Access to members.\n"; 146 TestRC *accessTest = new TestRC("access test"); 147 Ptr accessTestPtr = accessTest; 148 accessTest->testVal = 1; 149 assert(accessTestPtr->testVal == 1); 150 assert((*accessTestPtr).testVal == 1); 151 accessTest->testVal = 2; 152 assert(accessTestPtr->testVal == 2); 153 assert((*accessTestPtr).testVal == 2); 154 accessTestPtr->testVal = 3; 155 assert(accessTest->testVal == 3); 156 (*accessTestPtr).testVal = 4; 157 assert(accessTest->testVal == 4); 158 accessTestPtr = NULL; 159 accessTest = NULL; 160 assert(liveChange() == 0); 161 162 // Test bool and ! operator overloads. 163 cout << "Conversion to bool and ! overload.\n"; 164 Ptr boolTest = new TestRC("bool test"); 165 assert(boolTest == true); 166 assert(!boolTest == false); 167 boolTest = NULL; 168 assert(boolTest == false); 169 assert(!boolTest == true); 170 assert(liveChange() == 0); 171 172 // Test the equality operators. 173 cout << "Equality operators.\n"; 174 TestRC *equalTestA = new TestRC("equal test a"); 175 Ptr equalTestAPtr = equalTestA; 176 Ptr equalTestAPtr2 = equalTestA; 177 TestRC *equalTestB = new TestRC("equal test b"); 178 Ptr equalTestBPtr = equalTestB; 179 assert(equalTestA == equalTestAPtr); 180 assert(equalTestAPtr == equalTestA); 181 assert(equalTestAPtr == equalTestAPtr2); 182 assert(equalTestA != equalTestBPtr); 183 assert(equalTestAPtr != equalTestB); 184 assert(equalTestAPtr != equalTestBPtr); 185 186 cout << flush; 187} 188