-
Brad Payne (Vir Linden) authoredBrad Payne (Vir Linden) authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
lllazy_test.cpp 5.97 KiB
/**
* @file lllazy_test.cpp
* @author Nat Goodspeed
* @date 2009-01-28
* @brief Tests of lllazy.h.
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
* Copyright (c) 2009, Linden Research, Inc.
* $/LicenseInfo$
*/
// Precompiled header
#include "linden_common.h"
// associated header
#include "lllazy.h"
// STL headers
#include <iostream>
// std headers
// external library headers
#include <boost/lambda/construct.hpp>
#include <boost/lambda/bind.hpp>
// other Linden headers
#include "../test/lltut.h"
namespace bll = boost::lambda;
/*****************************************************************************
* Test classes
*****************************************************************************/
// Let's say that because of its many external dependencies, YuckyFoo is very
// hard to instantiate in a test harness.
class YuckyFoo
{
public:
virtual ~YuckyFoo() {}
virtual std::string whoami() const { return "YuckyFoo"; }
};
// Let's further suppose that YuckyBar is another hard-to-instantiate class.
class YuckyBar
{
public:
YuckyBar(const std::string& which):
mWhich(which)
{}
virtual ~YuckyBar() {}
virtual std::string identity() const { return std::string("YuckyBar(") + mWhich + ")"; }
private:
const std::string mWhich;
};
// Pretend that this class would be tough to test because, up until we started
// trying to test it, it contained instances of both YuckyFoo and YuckyBar.
// Now we've refactored so it contains LLLazy<YuckyFoo> and LLLazy<YuckyBar>.
// More than that, it contains them by virtue of deriving from
// LLLazyBase<YuckyFoo> and LLLazyBase<YuckyBar>.
// We postulate two different LLLazyBases because, with only one, you need not
// specify *which* get()/set() method you're talking about. That's a simpler
// case.
class NeedsTesting: public LLLazyBase<YuckyFoo>, public LLLazyBase<YuckyBar>
{
public:
NeedsTesting():
// mYuckyBar("RealYuckyBar")
LLLazyBase<YuckyBar>(bll::bind(bll::new_ptr<YuckyBar>(), "RealYuckyBar"))
{}
virtual ~NeedsTesting() {}
virtual std::string describe() const
{
return std::string("NeedsTesting(") + getLazy<YuckyFoo>(this).whoami() + ", " +
getLazy<YuckyBar>(this).identity() + ")";
}
private:
// These instance members were moved to LLLazyBases:
// YuckyFoo mYuckyFoo;
// YuckyBar mYuckyBar;
};
// Fake up a test YuckyFoo class
class TestFoo: public YuckyFoo
{
public:
virtual std::string whoami() const { return "TestFoo"; }
};
// and a test YuckyBar
class TestBar: public YuckyBar
{
public:
TestBar(const std::string& which): YuckyBar(which) {}
virtual std::string identity() const
{
return std::string("TestBar(") + YuckyBar::identity() + ")";
}
};
// So here's a test subclass of NeedsTesting that uses TestFoo and TestBar
// instead of YuckyFoo and YuckyBar.
class TestNeedsTesting: public NeedsTesting
{
public:
TestNeedsTesting()
{
// Exercise setLazy(T*)
setLazy<YuckyFoo>(this, new TestFoo());
// Exercise setLazy(Factory)
setLazy<YuckyBar>(this, bll::bind(bll::new_ptr<TestBar>(), "TestYuckyBar"));
}
virtual std::string describe() const
{
return std::string("TestNeedsTesting(") + NeedsTesting::describe() + ")";
}
void toolate()
{
setLazy<YuckyFoo>(this, new TestFoo());
}
};
// This class tests having an explicit LLLazy<T> instance as a named member,
// rather than deriving from LLLazyBase<T>.
class LazyMember
{
public:
YuckyFoo& getYuckyFoo() { return *mYuckyFoo; }
std::string whoisit() const { return mYuckyFoo->whoami(); }
protected:
LLLazy<YuckyFoo> mYuckyFoo;
};
// This is a test subclass of the above, dynamically replacing the
// LLLazy<YuckyFoo> member.
class TestLazyMember: public LazyMember
{
public:
// use factory setter
TestLazyMember()
{
mYuckyFoo.set(bll::new_ptr<TestFoo>());
}
// use instance setter
TestLazyMember(YuckyFoo* instance)
{
mYuckyFoo.set(instance);
}
};
/*****************************************************************************
* TUT
*****************************************************************************/
namespace tut
{
struct lllazy_data
{
};
typedef test_group<lllazy_data> lllazy_group;
typedef lllazy_group::object lllazy_object;
lllazy_group lllazygrp("lllazy");
template<> template<>
void lllazy_object::test<1>()
{
// Instantiate an official one, just because we can
NeedsTesting nt;
// and a test one
TestNeedsTesting tnt;
// std::cout << nt.describe() << '\n';
ensure_equals(nt.describe(), "NeedsTesting(YuckyFoo, YuckyBar(RealYuckyBar))");
// std::cout << tnt.describe() << '\n';
ensure_equals(tnt.describe(),
"TestNeedsTesting(NeedsTesting(TestFoo, TestBar(YuckyBar(TestYuckyBar))))");
}
template<> template<>
void lllazy_object::test<2>()
{
TestNeedsTesting tnt;
std::string threw;
try
{
tnt.toolate();
}
catch (const LLLazyCommon::InstanceChange& e)
{
threw = e.what();
}
ensure_contains("InstanceChange exception", threw, "replace LLLazy instance");
}
template<> template<>
void lllazy_object::test<3>()
{
{
LazyMember lm;
// operator*() on-demand instantiation
ensure_equals(lm.getYuckyFoo().whoami(), "YuckyFoo");
}
{
LazyMember lm;
// operator->() on-demand instantiation
ensure_equals(lm.whoisit(), "YuckyFoo");
}
}
template<> template<>
void lllazy_object::test<4>()
{
{
// factory setter
TestLazyMember tlm;
ensure_equals(tlm.whoisit(), "TestFoo");
}
{
// instance setter
TestLazyMember tlm(new TestFoo());
ensure_equals(tlm.whoisit(), "TestFoo");
}
}
} // namespace tut