PageRenderTime 21ms CodeModel.GetById 19ms RepoModel.GetById 0ms 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
Possible License(s): LGPL-2.1
  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. // Precompiled header
  29. #include "linden_common.h"
  30. // associated header
  31. #include "lllazy.h"
  32. // STL headers
  33. #include <iostream>
  34. // std headers
  35. // external library headers
  36. #include <boost/lambda/construct.hpp>
  37. #include <boost/lambda/bind.hpp>
  38. // other Linden headers
  39. #include "../test/lltut.h"
  40. namespace bll = boost::lambda;
  41. /*****************************************************************************
  42. * Test classes
  43. *****************************************************************************/
  44. // Let's say that because of its many external dependencies, YuckyFoo is very
  45. // hard to instantiate in a test harness.
  46. class YuckyFoo
  47. {
  48. public:
  49. virtual ~YuckyFoo() {}
  50. virtual std::string whoami() const { return "YuckyFoo"; }
  51. };
  52. // Let's further suppose that YuckyBar is another hard-to-instantiate class.
  53. class YuckyBar
  54. {
  55. public:
  56. YuckyBar(const std::string& which):
  57. mWhich(which)
  58. {}
  59. virtual ~YuckyBar() {}
  60. virtual std::string identity() const { return std::string("YuckyBar(") + mWhich + ")"; }
  61. private:
  62. const std::string mWhich;
  63. };
  64. // Pretend that this class would be tough to test because, up until we started
  65. // trying to test it, it contained instances of both YuckyFoo and YuckyBar.
  66. // Now we've refactored so it contains LLLazy<YuckyFoo> and LLLazy<YuckyBar>.
  67. // More than that, it contains them by virtue of deriving from
  68. // LLLazyBase<YuckyFoo> and LLLazyBase<YuckyBar>.
  69. // We postulate two different LLLazyBases because, with only one, you need not
  70. // specify *which* get()/set() method you're talking about. That's a simpler
  71. // case.
  72. class NeedsTesting: public LLLazyBase<YuckyFoo>, public LLLazyBase<YuckyBar>
  73. {
  74. public:
  75. NeedsTesting():
  76. // mYuckyBar("RealYuckyBar")
  77. LLLazyBase<YuckyBar>(bll::bind(bll::new_ptr<YuckyBar>(), "RealYuckyBar"))
  78. {}
  79. virtual ~NeedsTesting() {}
  80. virtual std::string describe() const
  81. {
  82. return std::string("NeedsTesting(") + getLazy<YuckyFoo>(this).whoami() + ", " +
  83. getLazy<YuckyBar>(this).identity() + ")";
  84. }
  85. private:
  86. // These instance members were moved to LLLazyBases:
  87. // YuckyFoo mYuckyFoo;
  88. // YuckyBar mYuckyBar;
  89. };
  90. // Fake up a test YuckyFoo class
  91. class TestFoo: public YuckyFoo
  92. {
  93. public:
  94. virtual std::string whoami() const { return "TestFoo"; }
  95. };
  96. // and a test YuckyBar
  97. class TestBar: public YuckyBar
  98. {
  99. public:
  100. TestBar(const std::string& which): YuckyBar(which) {}
  101. virtual std::string identity() const
  102. {
  103. return std::string("TestBar(") + YuckyBar::identity() + ")";
  104. }
  105. };
  106. // So here's a test subclass of NeedsTesting that uses TestFoo and TestBar
  107. // instead of YuckyFoo and YuckyBar.
  108. class TestNeedsTesting: public NeedsTesting
  109. {
  110. public:
  111. TestNeedsTesting()
  112. {
  113. // Exercise setLazy(T*)
  114. setLazy<YuckyFoo>(this, new TestFoo());
  115. // Exercise setLazy(Factory)
  116. setLazy<YuckyBar>(this, bll::bind(bll::new_ptr<TestBar>(), "TestYuckyBar"));
  117. }
  118. virtual std::string describe() const
  119. {
  120. return std::string("TestNeedsTesting(") + NeedsTesting::describe() + ")";
  121. }
  122. void toolate()
  123. {
  124. setLazy<YuckyFoo>(this, new TestFoo());
  125. }
  126. };
  127. // This class tests having an explicit LLLazy<T> instance as a named member,
  128. // rather than deriving from LLLazyBase<T>.
  129. class LazyMember
  130. {
  131. public:
  132. YuckyFoo& getYuckyFoo() { return *mYuckyFoo; }
  133. std::string whoisit() const { return mYuckyFoo->whoami(); }
  134. protected:
  135. LLLazy<YuckyFoo> mYuckyFoo;
  136. };
  137. // This is a test subclass of the above, dynamically replacing the
  138. // LLLazy<YuckyFoo> member.
  139. class TestLazyMember: public LazyMember
  140. {
  141. public:
  142. // use factory setter
  143. TestLazyMember()
  144. {
  145. mYuckyFoo.set(bll::new_ptr<TestFoo>());
  146. }
  147. // use instance setter
  148. TestLazyMember(YuckyFoo* instance)
  149. {
  150. mYuckyFoo.set(instance);
  151. }
  152. };
  153. /*****************************************************************************
  154. * TUT
  155. *****************************************************************************/
  156. namespace tut
  157. {
  158. struct lllazy_data
  159. {
  160. };
  161. typedef test_group<lllazy_data> lllazy_group;
  162. typedef lllazy_group::object lllazy_object;
  163. lllazy_group lllazygrp("lllazy");
  164. template<> template<>
  165. void lllazy_object::test<1>()
  166. {
  167. // Instantiate an official one, just because we can
  168. NeedsTesting nt;
  169. // and a test one
  170. TestNeedsTesting tnt;
  171. // std::cout << nt.describe() << '\n';
  172. ensure_equals(nt.describe(), "NeedsTesting(YuckyFoo, YuckyBar(RealYuckyBar))");
  173. // std::cout << tnt.describe() << '\n';
  174. ensure_equals(tnt.describe(),
  175. "TestNeedsTesting(NeedsTesting(TestFoo, TestBar(YuckyBar(TestYuckyBar))))");
  176. }
  177. template<> template<>
  178. void lllazy_object::test<2>()
  179. {
  180. TestNeedsTesting tnt;
  181. std::string threw;
  182. try
  183. {
  184. tnt.toolate();
  185. }
  186. catch (const LLLazyCommon::InstanceChange& e)
  187. {
  188. threw = e.what();
  189. }
  190. ensure_contains("InstanceChange exception", threw, "replace LLLazy instance");
  191. }
  192. template<> template<>
  193. void lllazy_object::test<3>()
  194. {
  195. {
  196. LazyMember lm;
  197. // operator*() on-demand instantiation
  198. ensure_equals(lm.getYuckyFoo().whoami(), "YuckyFoo");
  199. }
  200. {
  201. LazyMember lm;
  202. // operator->() on-demand instantiation
  203. ensure_equals(lm.whoisit(), "YuckyFoo");
  204. }
  205. }
  206. template<> template<>
  207. void lllazy_object::test<4>()
  208. {
  209. {
  210. // factory setter
  211. TestLazyMember tlm;
  212. ensure_equals(tlm.whoisit(), "TestFoo");
  213. }
  214. {
  215. // instance setter
  216. TestLazyMember tlm(new TestFoo());
  217. ensure_equals(tlm.whoisit(), "TestFoo");
  218. }
  219. }
  220. } // namespace tut