phoenix-firestorm/indra/llcommon/tests/llinstancetracker_test.cpp

184 lines
6.2 KiB
C++

/**
* @file llinstancetracker_test.cpp
* @author Nat Goodspeed
* @date 2009-11-10
* @brief Test for llinstancetracker.
*
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
// Precompiled header
#include "linden_common.h"
// associated header
#include "llinstancetracker.h"
// STL headers
#include <string>
#include <vector>
#include <set>
#include <algorithm> // std::sort()
// std headers
// external library headers
#include <boost/scoped_ptr.hpp>
// other Linden headers
#include "../test/lltut.h"
struct Keyed: public LLInstanceTracker<Keyed, std::string>
{
Keyed(const std::string& name):
LLInstanceTracker<Keyed, std::string>(name),
mName(name)
{}
std::string mName;
};
struct Unkeyed: public LLInstanceTracker<Unkeyed>
{
};
/*****************************************************************************
* TUT
*****************************************************************************/
namespace tut
{
struct llinstancetracker_data
{
};
typedef test_group<llinstancetracker_data> llinstancetracker_group;
typedef llinstancetracker_group::object object;
llinstancetracker_group llinstancetrackergrp("llinstancetracker");
template<> template<>
void object::test<1>()
{
ensure_equals(Keyed::instanceCount(), 0);
{
Keyed one("one");
ensure_equals(Keyed::instanceCount(), 1);
Keyed* found = Keyed::getInstance("one");
ensure("couldn't find stack Keyed", found);
ensure_equals("found wrong Keyed instance", found, &one);
{
boost::scoped_ptr<Keyed> two(new Keyed("two"));
ensure_equals(Keyed::instanceCount(), 2);
Keyed* found = Keyed::getInstance("two");
ensure("couldn't find heap Keyed", found);
ensure_equals("found wrong Keyed instance", found, two.get());
}
ensure_equals(Keyed::instanceCount(), 1);
}
Keyed* found = Keyed::getInstance("one");
ensure("Keyed key lives too long", ! found);
ensure_equals(Keyed::instanceCount(), 0);
}
template<> template<>
void object::test<2>()
{
ensure_equals(Unkeyed::instanceCount(), 0);
{
Unkeyed one;
ensure_equals(Unkeyed::instanceCount(), 1);
Unkeyed* found = Unkeyed::getInstance(&one);
ensure_equals(found, &one);
{
boost::scoped_ptr<Unkeyed> two(new Unkeyed);
ensure_equals(Unkeyed::instanceCount(), 2);
Unkeyed* found = Unkeyed::getInstance(two.get());
ensure_equals(found, two.get());
}
ensure_equals(Unkeyed::instanceCount(), 1);
}
ensure_equals(Unkeyed::instanceCount(), 0);
}
template<> template<>
void object::test<3>()
{
Keyed one("one"), two("two"), three("three");
// We don't want to rely on the underlying container delivering keys
// in any particular order. That allows us the flexibility to
// reimplement LLInstanceTracker using, say, a hash map instead of a
// std::map. We DO insist that every key appear exactly once.
typedef std::vector<std::string> StringVector;
StringVector keys(Keyed::beginKeys(), Keyed::endKeys());
std::sort(keys.begin(), keys.end());
StringVector::const_iterator ki(keys.begin());
ensure_equals(*ki++, "one");
ensure_equals(*ki++, "three");
ensure_equals(*ki++, "two");
// Use ensure() here because ensure_equals would want to display
// mismatched values, and frankly that wouldn't help much.
ensure("didn't reach end", ki == keys.end());
// Use a somewhat different approach to order independence with
// beginInstances(): explicitly capture the instances we know in a
// set, and delete them as we iterate through.
typedef std::set<Keyed*> InstanceSet;
InstanceSet instances;
instances.insert(&one);
instances.insert(&two);
instances.insert(&three);
for (Keyed::instance_iter ii(Keyed::beginInstances()), iend(Keyed::endInstances());
ii != iend; ++ii)
{
Keyed& ref = *ii;
ensure_equals("spurious instance", instances.erase(&ref), 1);
}
ensure_equals("unreported instance", instances.size(), 0);
}
template<> template<>
void object::test<4>()
{
Unkeyed one, two, three;
typedef std::set<Unkeyed*> KeySet;
KeySet keys;
keys.insert(&one);
keys.insert(&two);
keys.insert(&three);
{
Unkeyed::LLInstanceTrackerScopedGuard guard;
for (Unkeyed::key_iter ki(guard.beginKeys()), kend(guard.endKeys());
ki != kend; ++ki)
{
ensure_equals("spurious key", keys.erase(*ki), 1);
}
}
ensure_equals("unreported key", keys.size(), 0);
KeySet instances;
instances.insert(&one);
instances.insert(&two);
instances.insert(&three);
{
Unkeyed::LLInstanceTrackerScopedGuard guard;
for (Unkeyed::instance_iter ii(guard.beginInstances()), iend(guard.endInstances());
ii != iend; ++ii)
{
Unkeyed& ref = *ii;
ensure_equals("spurious instance", instances.erase(&ref), 1);
}
}
ensure_equals("unreported instance", instances.size(), 0);
}
} // namespace tut