17824Sgblack@eecs.umich.edu/*
27824Sgblack@eecs.umich.edu * Copyright (c) 2010 The Regents of The University of Michigan
37824Sgblack@eecs.umich.edu * All rights reserved.
47824Sgblack@eecs.umich.edu *
57824Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
67824Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
77824Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
87824Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
97824Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
107824Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
117824Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
127824Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
137824Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
147824Sgblack@eecs.umich.edu * this software without specific prior written permission.
157824Sgblack@eecs.umich.edu *
167824Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
177824Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
187824Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
197824Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
207824Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
217824Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
227824Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
237824Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
247824Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
257824Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
267824Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
277824Sgblack@eecs.umich.edu *
287824Sgblack@eecs.umich.edu * Authors: Gabe Black
297824Sgblack@eecs.umich.edu */
307824Sgblack@eecs.umich.edu
317824Sgblack@eecs.umich.edu#include <cassert>
327824Sgblack@eecs.umich.edu#include <iostream>
337824Sgblack@eecs.umich.edu#include <list>
347824Sgblack@eecs.umich.edu
357842Sgblack@eecs.umich.edu#include "base/cprintf.hh"
367824Sgblack@eecs.umich.edu#include "base/refcnt.hh"
377842Sgblack@eecs.umich.edu#include "unittest/unittest.hh"
387824Sgblack@eecs.umich.edu
397824Sgblack@eecs.umich.eduusing namespace std;
407842Sgblack@eecs.umich.eduusing UnitTest::setCase;
417824Sgblack@eecs.umich.edu
427824Sgblack@eecs.umich.edunamespace {
437824Sgblack@eecs.umich.edu
447842Sgblack@eecs.umich.edubool printNewDel = false;
457842Sgblack@eecs.umich.edu
467824Sgblack@eecs.umich.educlass TestRC;
477824Sgblack@eecs.umich.edutypedef list<TestRC *> LiveList;
487824Sgblack@eecs.umich.eduLiveList liveList;
497824Sgblack@eecs.umich.edu
507824Sgblack@eecs.umich.eduint
517824Sgblack@eecs.umich.edulive()
527824Sgblack@eecs.umich.edu{
537824Sgblack@eecs.umich.edu    return liveList.size();
547824Sgblack@eecs.umich.edu}
557824Sgblack@eecs.umich.edu
567824Sgblack@eecs.umich.eduint
577824Sgblack@eecs.umich.eduliveChange()
587824Sgblack@eecs.umich.edu{
597824Sgblack@eecs.umich.edu    static int oldLive = 0;
607824Sgblack@eecs.umich.edu    int newLive = live();
617824Sgblack@eecs.umich.edu    int diff =  newLive - oldLive;
627824Sgblack@eecs.umich.edu    oldLive = newLive;
637824Sgblack@eecs.umich.edu    return diff;
647824Sgblack@eecs.umich.edu}
657824Sgblack@eecs.umich.edu
667824Sgblack@eecs.umich.educlass TestRC : public RefCounted
677824Sgblack@eecs.umich.edu{
687824Sgblack@eecs.umich.edu  protected:
697824Sgblack@eecs.umich.edu    const char *_tag;
707824Sgblack@eecs.umich.edu    LiveList::iterator liveIt;
717824Sgblack@eecs.umich.edu
727824Sgblack@eecs.umich.edu  public:
737824Sgblack@eecs.umich.edu    TestRC(const char *newTag) : _tag(newTag)
747824Sgblack@eecs.umich.edu    {
757842Sgblack@eecs.umich.edu        if (printNewDel)
767842Sgblack@eecs.umich.edu            cprintf("  Creating object \"%s\"\n", _tag);
777824Sgblack@eecs.umich.edu        liveList.push_front(this);
787824Sgblack@eecs.umich.edu        liveIt = liveList.begin();
797824Sgblack@eecs.umich.edu    }
807824Sgblack@eecs.umich.edu
817824Sgblack@eecs.umich.edu    ~TestRC()
827824Sgblack@eecs.umich.edu    {
837842Sgblack@eecs.umich.edu        if (printNewDel)
847842Sgblack@eecs.umich.edu            cprintf("  Destroying object \"%s\"\n", _tag);
857824Sgblack@eecs.umich.edu        liveList.erase(liveIt);
867824Sgblack@eecs.umich.edu    }
877824Sgblack@eecs.umich.edu
887824Sgblack@eecs.umich.edu    const char *
897824Sgblack@eecs.umich.edu    tag()
907824Sgblack@eecs.umich.edu    {
917824Sgblack@eecs.umich.edu        return _tag;
927824Sgblack@eecs.umich.edu    }
937824Sgblack@eecs.umich.edu
947824Sgblack@eecs.umich.edu    int testVal;
957824Sgblack@eecs.umich.edu};
967824Sgblack@eecs.umich.edu
977824Sgblack@eecs.umich.edutypedef RefCountingPtr<TestRC> Ptr;
987824Sgblack@eecs.umich.edu
997842Sgblack@eecs.umich.edu} // anonymous namespace
1007824Sgblack@eecs.umich.edu
1017824Sgblack@eecs.umich.eduint
1027824Sgblack@eecs.umich.edumain()
1037824Sgblack@eecs.umich.edu{
1047824Sgblack@eecs.umich.edu    assert(live() == 0);
1057824Sgblack@eecs.umich.edu    assert(liveChange() == 0);
1067824Sgblack@eecs.umich.edu
1077824Sgblack@eecs.umich.edu    // Create an empty Ptr and verify it's data pointer is NULL.
1087842Sgblack@eecs.umich.edu    setCase("NULL check");
1097824Sgblack@eecs.umich.edu    Ptr nullCheck;
1107842Sgblack@eecs.umich.edu    EXPECT_EQ(nullCheck.get(), NULL);
1117824Sgblack@eecs.umich.edu
1127842Sgblack@eecs.umich.edu    EXPECT_EQ(liveChange(), 0);
1137824Sgblack@eecs.umich.edu
1147824Sgblack@eecs.umich.edu    // Construct a Ptr from a TestRC pointer.
1157842Sgblack@eecs.umich.edu    setCase("construction from pointer");
1167824Sgblack@eecs.umich.edu    Ptr constFromPointer = new TestRC("construction from pointer");
1177824Sgblack@eecs.umich.edu
1187842Sgblack@eecs.umich.edu    EXPECT_EQ(liveChange(), 1);
1197824Sgblack@eecs.umich.edu
1207824Sgblack@eecs.umich.edu    // Construct a Ptr from an existing Ptr.
1217842Sgblack@eecs.umich.edu    setCase("construction from a Ptr");
1227824Sgblack@eecs.umich.edu    Ptr constFromPtr = constFromPointer;
1237824Sgblack@eecs.umich.edu
1247842Sgblack@eecs.umich.edu    EXPECT_EQ(liveChange(), 0);
1257824Sgblack@eecs.umich.edu
1267824Sgblack@eecs.umich.edu    // Test a Ptr being destroyed.
1277842Sgblack@eecs.umich.edu    setCase("destroying a Ptr");
1287824Sgblack@eecs.umich.edu    Ptr *ptrPtr = new Ptr(new TestRC("destroying a ptr"));
1297842Sgblack@eecs.umich.edu    EXPECT_EQ(liveChange(), 1);
1307824Sgblack@eecs.umich.edu    delete ptrPtr;
1317842Sgblack@eecs.umich.edu    EXPECT_EQ(liveChange(), -1);
1327824Sgblack@eecs.umich.edu
1337824Sgblack@eecs.umich.edu    // Test assignment from a pointer and from a Ptr.
1347842Sgblack@eecs.umich.edu    setCase("assignment operators");
1357824Sgblack@eecs.umich.edu    Ptr assignmentTarget;
1367824Sgblack@eecs.umich.edu    TestRC *assignmentSourcePointer = new TestRC("assignment source 1");
1377842Sgblack@eecs.umich.edu    EXPECT_EQ(liveChange(), 1);
1387824Sgblack@eecs.umich.edu    assignmentTarget = assignmentSourcePointer;
1397842Sgblack@eecs.umich.edu    EXPECT_EQ(liveChange(), 0);
1407824Sgblack@eecs.umich.edu    assignmentTarget = NULL;
1417842Sgblack@eecs.umich.edu    EXPECT_EQ(liveChange(), -1);
1427824Sgblack@eecs.umich.edu    Ptr assignmentSourcePtr(new TestRC("assignment source 2"));
1437842Sgblack@eecs.umich.edu    EXPECT_EQ(liveChange(), 1);
1447824Sgblack@eecs.umich.edu    assignmentTarget = assignmentSourcePtr;
1457842Sgblack@eecs.umich.edu    EXPECT_EQ(liveChange(), 0);
1467824Sgblack@eecs.umich.edu    assignmentSourcePtr = NULL;
1477842Sgblack@eecs.umich.edu    EXPECT_EQ(liveChange(), 0);
1487824Sgblack@eecs.umich.edu    assignmentTarget = NULL;
1497842Sgblack@eecs.umich.edu    EXPECT_EQ(liveChange(), -1);
1507824Sgblack@eecs.umich.edu
1517824Sgblack@eecs.umich.edu    // Test access to members of the pointed to class and dereferencing.
1527842Sgblack@eecs.umich.edu    setCase("access to members");
1537824Sgblack@eecs.umich.edu    TestRC *accessTest = new TestRC("access test");
1547824Sgblack@eecs.umich.edu    Ptr accessTestPtr = accessTest;
1557824Sgblack@eecs.umich.edu    accessTest->testVal = 1;
1567842Sgblack@eecs.umich.edu    EXPECT_EQ(accessTestPtr->testVal, 1);
1577842Sgblack@eecs.umich.edu    EXPECT_EQ((*accessTestPtr).testVal, 1);
1587824Sgblack@eecs.umich.edu    accessTest->testVal = 2;
1597842Sgblack@eecs.umich.edu    EXPECT_EQ(accessTestPtr->testVal, 2);
1607842Sgblack@eecs.umich.edu    EXPECT_EQ((*accessTestPtr).testVal, 2);
1617824Sgblack@eecs.umich.edu    accessTestPtr->testVal = 3;
1627842Sgblack@eecs.umich.edu    EXPECT_EQ(accessTest->testVal, 3);
1637824Sgblack@eecs.umich.edu    (*accessTestPtr).testVal = 4;
1647842Sgblack@eecs.umich.edu    EXPECT_EQ(accessTest->testVal, 4);
1657824Sgblack@eecs.umich.edu    accessTestPtr = NULL;
1667824Sgblack@eecs.umich.edu    accessTest = NULL;
1677842Sgblack@eecs.umich.edu    EXPECT_EQ(liveChange(), 0);
1687824Sgblack@eecs.umich.edu
1697824Sgblack@eecs.umich.edu    // Test bool and ! operator overloads.
1707842Sgblack@eecs.umich.edu    setCase("conversion to bool and ! overload");
1717824Sgblack@eecs.umich.edu    Ptr boolTest = new TestRC("bool test");
1727842Sgblack@eecs.umich.edu    EXPECT_EQ(boolTest, true);
1737842Sgblack@eecs.umich.edu    EXPECT_EQ(!boolTest, false);
1747824Sgblack@eecs.umich.edu    boolTest = NULL;
1757842Sgblack@eecs.umich.edu    EXPECT_EQ(boolTest, false);
1767842Sgblack@eecs.umich.edu    EXPECT_EQ(!boolTest, true);
1777842Sgblack@eecs.umich.edu    EXPECT_EQ(liveChange(), 0);
1787824Sgblack@eecs.umich.edu
1797824Sgblack@eecs.umich.edu    // Test the equality operators.
1807842Sgblack@eecs.umich.edu    setCase("equality operators");
1817824Sgblack@eecs.umich.edu    TestRC *equalTestA = new TestRC("equal test a");
1827824Sgblack@eecs.umich.edu    Ptr equalTestAPtr = equalTestA;
1837824Sgblack@eecs.umich.edu    Ptr equalTestAPtr2 = equalTestA;
1847824Sgblack@eecs.umich.edu    TestRC *equalTestB = new TestRC("equal test b");
1857824Sgblack@eecs.umich.edu    Ptr equalTestBPtr = equalTestB;
1867842Sgblack@eecs.umich.edu    EXPECT_TRUE(equalTestA == equalTestAPtr);
1877842Sgblack@eecs.umich.edu    EXPECT_TRUE(equalTestAPtr == equalTestA);
1887842Sgblack@eecs.umich.edu    EXPECT_TRUE(equalTestAPtr == equalTestAPtr2);
1897842Sgblack@eecs.umich.edu    EXPECT_TRUE(equalTestA != equalTestBPtr);
1907842Sgblack@eecs.umich.edu    EXPECT_TRUE(equalTestAPtr != equalTestB);
1917842Sgblack@eecs.umich.edu    EXPECT_TRUE(equalTestAPtr != equalTestBPtr);
1927824Sgblack@eecs.umich.edu
1937842Sgblack@eecs.umich.edu    return UnitTest::printResults();
1947824Sgblack@eecs.umich.edu}
195