PageRenderTime 84ms CodeModel.GetById 41ms app.highlight 38ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llcommon/tests/lllazy_test.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 244 lines | 146 code | 24 blank | 74 comment | 0 complexity | fac681168003855bccbdc940c8bfd091 MD5 | raw file
  1/**
  2 * @file   lllazy_test.cpp
  3 * @author Nat Goodspeed
  4 * @date   2009-01-28
  5 * @brief  Tests of lllazy.h.
  6 * 
  7 * $LicenseInfo:firstyear=2009&license=viewerlgpl$
  8 * Second Life Viewer Source Code
  9 * Copyright (C) 2010, Linden Research, Inc.
 10 * 
 11 * This library is free software; you can redistribute it and/or
 12 * modify it under the terms of the GNU Lesser General Public
 13 * License as published by the Free Software Foundation;
 14 * version 2.1 of the License only.
 15 * 
 16 * This library is distributed in the hope that it will be useful,
 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 19 * Lesser General Public License for more details.
 20 * 
 21 * You should have received a copy of the GNU Lesser General Public
 22 * License along with this library; if not, write to the Free Software
 23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 24 * 
 25 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 26 * $/LicenseInfo$
 27 */
 28
 29// Precompiled header
 30#include "linden_common.h"
 31// associated header
 32#include "lllazy.h"
 33// STL headers
 34#include <iostream>
 35// std headers
 36// external library headers
 37#include <boost/lambda/construct.hpp>
 38#include <boost/lambda/bind.hpp>
 39// other Linden headers
 40#include "../test/lltut.h"
 41
 42namespace bll = boost::lambda;
 43
 44/*****************************************************************************
 45*   Test classes
 46*****************************************************************************/
 47
 48// Let's say that because of its many external dependencies, YuckyFoo is very
 49// hard to instantiate in a test harness.
 50class YuckyFoo
 51{
 52public:
 53    virtual ~YuckyFoo() {}
 54    virtual std::string whoami() const { return "YuckyFoo"; }
 55};
 56
 57// Let's further suppose that YuckyBar is another hard-to-instantiate class.
 58class YuckyBar
 59{
 60public:
 61    YuckyBar(const std::string& which):
 62        mWhich(which)
 63    {}
 64    virtual ~YuckyBar() {}
 65
 66    virtual std::string identity() const { return std::string("YuckyBar(") + mWhich + ")"; }
 67
 68private:
 69    const std::string mWhich;
 70};
 71
 72// Pretend that this class would be tough to test because, up until we started
 73// trying to test it, it contained instances of both YuckyFoo and YuckyBar.
 74// Now we've refactored so it contains LLLazy<YuckyFoo> and LLLazy<YuckyBar>.
 75// More than that, it contains them by virtue of deriving from
 76// LLLazyBase<YuckyFoo> and LLLazyBase<YuckyBar>.
 77// We postulate two different LLLazyBases because, with only one, you need not
 78// specify *which* get()/set() method you're talking about. That's a simpler
 79// case.
 80class NeedsTesting: public LLLazyBase<YuckyFoo>, public LLLazyBase<YuckyBar>
 81{
 82public:
 83    NeedsTesting():
 84        // mYuckyBar("RealYuckyBar")
 85        LLLazyBase<YuckyBar>(bll::bind(bll::new_ptr<YuckyBar>(), "RealYuckyBar"))
 86    {}
 87    virtual ~NeedsTesting() {}
 88
 89    virtual std::string describe() const
 90    {
 91        return std::string("NeedsTesting(") + getLazy<YuckyFoo>(this).whoami() + ", " +
 92            getLazy<YuckyBar>(this).identity() + ")";
 93    }
 94
 95private:
 96    // These instance members were moved to LLLazyBases:
 97    // YuckyFoo mYuckyFoo;
 98    // YuckyBar mYuckyBar;
 99};
100
101// Fake up a test YuckyFoo class
102class TestFoo: public YuckyFoo
103{
104public:
105    virtual std::string whoami() const { return "TestFoo"; }
106};
107
108// and a test YuckyBar
109class TestBar: public YuckyBar
110{
111public:
112    TestBar(const std::string& which): YuckyBar(which) {}
113    virtual std::string identity() const
114    {
115        return std::string("TestBar(") + YuckyBar::identity() + ")";
116    }
117};
118
119// So here's a test subclass of NeedsTesting that uses TestFoo and TestBar
120// instead of YuckyFoo and YuckyBar.
121class TestNeedsTesting: public NeedsTesting
122{
123public:
124    TestNeedsTesting()
125    {
126        // Exercise setLazy(T*)
127        setLazy<YuckyFoo>(this, new TestFoo());
128        // Exercise setLazy(Factory)
129        setLazy<YuckyBar>(this, bll::bind(bll::new_ptr<TestBar>(), "TestYuckyBar"));
130    }
131
132    virtual std::string describe() const
133    {
134        return std::string("TestNeedsTesting(") + NeedsTesting::describe() + ")";
135    }
136
137    void toolate()
138    {
139        setLazy<YuckyFoo>(this, new TestFoo());
140    }
141};
142
143// This class tests having an explicit LLLazy<T> instance as a named member,
144// rather than deriving from LLLazyBase<T>.
145class LazyMember
146{
147public:
148    YuckyFoo& getYuckyFoo() { return *mYuckyFoo; }
149    std::string whoisit() const { return mYuckyFoo->whoami(); }
150
151protected:
152    LLLazy<YuckyFoo> mYuckyFoo;
153};
154
155// This is a test subclass of the above, dynamically replacing the
156// LLLazy<YuckyFoo> member.
157class TestLazyMember: public LazyMember
158{
159public:
160    // use factory setter
161    TestLazyMember()
162    {
163        mYuckyFoo.set(bll::new_ptr<TestFoo>());
164    }
165
166    // use instance setter
167    TestLazyMember(YuckyFoo* instance)
168    {
169        mYuckyFoo.set(instance);
170    }
171};
172
173/*****************************************************************************
174*   TUT
175*****************************************************************************/
176namespace tut
177{
178    struct lllazy_data
179    {
180    };
181    typedef test_group<lllazy_data> lllazy_group;
182    typedef lllazy_group::object lllazy_object;
183    lllazy_group lllazygrp("lllazy");
184
185    template<> template<>
186    void lllazy_object::test<1>()
187    {
188        // Instantiate an official one, just because we can
189        NeedsTesting nt;
190        // and a test one
191        TestNeedsTesting tnt;
192//      std::cout << nt.describe() << '\n';
193        ensure_equals(nt.describe(), "NeedsTesting(YuckyFoo, YuckyBar(RealYuckyBar))");
194//      std::cout << tnt.describe() << '\n';
195        ensure_equals(tnt.describe(),
196                      "TestNeedsTesting(NeedsTesting(TestFoo, TestBar(YuckyBar(TestYuckyBar))))");
197    }
198
199    template<> template<>
200    void lllazy_object::test<2>()
201    {
202        TestNeedsTesting tnt;
203        std::string threw;
204        try
205        {
206            tnt.toolate();
207        }
208        catch (const LLLazyCommon::InstanceChange& e)
209        {
210            threw = e.what();
211        }
212        ensure_contains("InstanceChange exception", threw, "replace LLLazy instance");
213    }
214
215    template<> template<>
216    void lllazy_object::test<3>()
217    {
218        {
219            LazyMember lm;
220            // operator*() on-demand instantiation
221            ensure_equals(lm.getYuckyFoo().whoami(), "YuckyFoo");
222        }
223        {
224            LazyMember lm;
225            // operator->() on-demand instantiation
226            ensure_equals(lm.whoisit(), "YuckyFoo");
227        }
228    }
229
230    template<> template<>
231    void lllazy_object::test<4>()
232    {
233        {
234            // factory setter
235            TestLazyMember tlm;
236            ensure_equals(tlm.whoisit(), "TestFoo");
237        }
238        {
239            // instance setter
240            TestLazyMember tlm(new TestFoo());
241            ensure_equals(tlm.whoisit(), "TestFoo");
242        }
243    }
244} // namespace tut