refcnttest.cc revision 7824:b36af60dcb91
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