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/cprintf.hh" 36#include "base/refcnt.hh" 37#include "unittest/unittest.hh" 38 39using namespace std; 40using UnitTest::setCase; 41 42namespace { 43 44bool printNewDel = false; 45 46class TestRC; 47typedef list<TestRC *> LiveList; 48LiveList liveList; 49 50int 51live() 52{ 53 return liveList.size(); 54} 55 56int 57liveChange() 58{ 59 static int oldLive = 0; 60 int newLive = live(); 61 int diff = newLive - oldLive; 62 oldLive = newLive; 63 return diff; 64} 65 66class TestRC : public RefCounted 67{ 68 protected: 69 const char *_tag; 70 LiveList::iterator liveIt; 71 72 public: 73 TestRC(const char *newTag) : _tag(newTag) 74 { 75 if (printNewDel) 76 cprintf(" Creating object \"%s\"\n", _tag); 77 liveList.push_front(this); 78 liveIt = liveList.begin(); 79 } 80 81 ~TestRC() 82 { 83 if (printNewDel) 84 cprintf(" Destroying object \"%s\"\n", _tag); 85 liveList.erase(liveIt); 86 } 87 88 const char * 89 tag() 90 { 91 return _tag; 92 } 93 94 int testVal; 95}; 96 97typedef RefCountingPtr<TestRC> Ptr; 98 99} // anonymous namespace 100 101int 102main() 103{ 104 assert(live() == 0); 105 assert(liveChange() == 0); 106 107 // Create an empty Ptr and verify it's data pointer is NULL. 108 setCase("NULL check"); 109 Ptr nullCheck; 110 EXPECT_EQ(nullCheck.get(), NULL); 111 112 EXPECT_EQ(liveChange(), 0); 113 114 // Construct a Ptr from a TestRC pointer. 115 setCase("construction from pointer"); 116 Ptr constFromPointer = new TestRC("construction from pointer"); 117 118 EXPECT_EQ(liveChange(), 1); 119 120 // Construct a Ptr from an existing Ptr. 121 setCase("construction from a Ptr"); 122 Ptr constFromPtr = constFromPointer; 123 124 EXPECT_EQ(liveChange(), 0); 125 126 // Test a Ptr being destroyed. 127 setCase("destroying a Ptr"); 128 Ptr *ptrPtr = new Ptr(new TestRC("destroying a ptr")); 129 EXPECT_EQ(liveChange(), 1); 130 delete ptrPtr; 131 EXPECT_EQ(liveChange(), -1); 132 133 // Test assignment from a pointer and from a Ptr. 134 setCase("assignment operators"); 135 Ptr assignmentTarget; 136 TestRC *assignmentSourcePointer = new TestRC("assignment source 1"); 137 EXPECT_EQ(liveChange(), 1); 138 assignmentTarget = assignmentSourcePointer; 139 EXPECT_EQ(liveChange(), 0); 140 assignmentTarget = NULL; 141 EXPECT_EQ(liveChange(), -1); 142 Ptr assignmentSourcePtr(new TestRC("assignment source 2")); 143 EXPECT_EQ(liveChange(), 1); 144 assignmentTarget = assignmentSourcePtr; 145 EXPECT_EQ(liveChange(), 0); 146 assignmentSourcePtr = NULL; 147 EXPECT_EQ(liveChange(), 0); 148 assignmentTarget = NULL; 149 EXPECT_EQ(liveChange(), -1); 150 151 // Test access to members of the pointed to class and dereferencing. 152 setCase("access to members"); 153 TestRC *accessTest = new TestRC("access test"); 154 Ptr accessTestPtr = accessTest; 155 accessTest->testVal = 1; 156 EXPECT_EQ(accessTestPtr->testVal, 1); 157 EXPECT_EQ((*accessTestPtr).testVal, 1); 158 accessTest->testVal = 2; 159 EXPECT_EQ(accessTestPtr->testVal, 2); 160 EXPECT_EQ((*accessTestPtr).testVal, 2); 161 accessTestPtr->testVal = 3; 162 EXPECT_EQ(accessTest->testVal, 3); 163 (*accessTestPtr).testVal = 4; 164 EXPECT_EQ(accessTest->testVal, 4); 165 accessTestPtr = NULL; 166 accessTest = NULL; 167 EXPECT_EQ(liveChange(), 0); 168 169 // Test bool and ! operator overloads. 170 setCase("conversion to bool and ! overload"); 171 Ptr boolTest = new TestRC("bool test"); 172 EXPECT_EQ(boolTest, true); 173 EXPECT_EQ(!boolTest, false); 174 boolTest = NULL; 175 EXPECT_EQ(boolTest, false); 176 EXPECT_EQ(!boolTest, true); 177 EXPECT_EQ(liveChange(), 0); 178 179 // Test the equality operators. 180 setCase("equality operators"); 181 TestRC *equalTestA = new TestRC("equal test a"); 182 Ptr equalTestAPtr = equalTestA; 183 Ptr equalTestAPtr2 = equalTestA; 184 TestRC *equalTestB = new TestRC("equal test b"); 185 Ptr equalTestBPtr = equalTestB; 186 EXPECT_TRUE(equalTestA == equalTestAPtr); 187 EXPECT_TRUE(equalTestAPtr == equalTestA); 188 EXPECT_TRUE(equalTestAPtr == equalTestAPtr2); 189 EXPECT_TRUE(equalTestA != equalTestBPtr); 190 EXPECT_TRUE(equalTestAPtr != equalTestB); 191 EXPECT_TRUE(equalTestAPtr != equalTestBPtr); 192 193 return UnitTest::printResults(); 194} 195