RefCount: Add a unit test for reference counting pointers.
[gem5.git] / src / unittest / refcnttest.cc
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
37 using namespace std;
38
39 namespace {
40
41 class TestRC;
42 typedef list<TestRC *> LiveList;
43 LiveList liveList;
44
45 int
46 live()
47 {
48 return liveList.size();
49 }
50
51 int
52 liveChange()
53 {
54 static int oldLive = 0;
55 int newLive = live();
56 int diff = newLive - oldLive;
57 oldLive = newLive;
58 return diff;
59 }
60
61 class 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
90 typedef RefCountingPtr<TestRC> Ptr;
91
92 }
93
94 int
95 main()
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 }