lldependencies_test.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:13k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /**
  2.  * @file   lldependencies_tut.cpp
  3.  * @author Nat Goodspeed
  4.  * @date   2008-09-17
  5.  * @brief  Test of lldependencies.h
  6.  * 
  7.  * $LicenseInfo:firstyear=2008&license=viewergpl$
  8.  * 
  9.  * Copyright (c) 2008-2010, Linden Research, Inc.
  10.  * 
  11.  * Second Life Viewer Source Code
  12.  * The source code in this file ("Source Code") is provided by Linden Lab
  13.  * to you under the terms of the GNU General Public License, version 2.0
  14.  * ("GPL"), unless you have obtained a separate licensing agreement
  15.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  16.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  17.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  18.  * 
  19.  * There are special exceptions to the terms and conditions of the GPL as
  20.  * it is applied to this Source Code. View the full text of the exception
  21.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  22.  * online at
  23.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  24.  * 
  25.  * By copying, modifying or distributing this software, you acknowledge
  26.  * that you have read and understood your obligations described above,
  27.  * and agree to abide by those obligations.
  28.  * 
  29.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  30.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  31.  * COMPLETENESS OR PERFORMANCE.
  32.  * $/LicenseInfo$
  33.  */
  34. // STL headers
  35. #include <iostream>
  36. #include <string>
  37. // std headers
  38. // external library headers
  39. #include <boost/assign/list_of.hpp>
  40. // Precompiled header
  41. #include "linden_common.h"
  42. // associated header
  43. #include "../lldependencies.h"
  44. // other Linden headers
  45. #include "../test/lltut.h"
  46. using boost::assign::list_of;
  47. #if LL_WINDOWS
  48. #pragma warning (disable : 4675) // "resolved by ADL" -- just as I want!
  49. #endif
  50. typedef LLDependencies<> StringDeps;
  51. typedef StringDeps::KeyList StringList;
  52. // We use the very cool boost::assign::list_of() construct to specify vectors
  53. // of strings inline. For reasons on which I'm not entirely clear, though, it
  54. // needs a helper function. You can use list_of() to construct an implicit
  55. // StringList (std::vector<std::string>) by conversion, e.g. for a function
  56. // parameter -- but if you simply write StringList(list_of("etc.")), you get
  57. // ambiguity errors. Shrug!
  58. template<typename CONTAINER>
  59. CONTAINER make(const CONTAINER& data)
  60. {
  61.     return data;
  62. }
  63. // Display an arbitary value as itself...
  64. template<typename T>
  65. std::ostream& display(std::ostream& out, const T& value)
  66. {
  67.     out << value;
  68.     return out;
  69. }
  70. // ...but display std::string enclosed in double quotes.
  71. template<>
  72. std::ostream& display(std::ostream& out, const std::string& value)
  73. {
  74.     out << '"' << value << '"';
  75.     return out;
  76. }
  77. // display any sequence compatible with Boost.Range
  78. template<typename SEQUENCE>
  79. std::ostream& display_seq(std::ostream& out,
  80.                           const std::string& open, const SEQUENCE& seq, const std::string& close)
  81. {
  82.     out << open;
  83.     typename boost::range_const_iterator<SEQUENCE>::type
  84.         sli = boost::begin(seq),
  85.         slend = boost::end(seq);
  86.     if (sli != slend)
  87.     {
  88.         display(out, *sli);
  89.         while (++sli != slend)
  90.         {
  91.             out << ", ";
  92.             display(out, *sli);
  93.         }
  94.     }
  95.     out << close;
  96.     return out;
  97. }
  98. // helper to dump a StringList to std::cout if needed
  99. template<typename ENTRY>
  100. std::ostream& operator<<(std::ostream& out, const std::vector<ENTRY>& list)
  101. {
  102.     display_seq(out, "(", list, ")");
  103.     return out;
  104. }
  105. template<typename ENTRY>
  106. std::ostream& operator<<(std::ostream& out, const std::set<ENTRY>& set)
  107. {
  108.     display_seq(out, "{", set, "}");
  109.     return out;
  110. }
  111. const std::string& extract_key(const LLDependencies<>::value_type& entry)
  112. {
  113.     return entry.first;
  114. }
  115. // helper to return a StringList of keys from LLDependencies::sort()
  116. StringList sorted_keys(LLDependencies<>& deps)
  117. {
  118.     // 1. Call deps.sort(), returning a value_type range of (key, node) pairs.
  119.     // 2. Use make_transform_range() to obtain a range of just keys.
  120.     // 3. Use instance_from_range to instantiate a StringList from that range.
  121.     // 4. Return by value "slices" instance_from_range<StringList> (a subclass
  122.     //    of StringList) to its base class StringList.
  123.     return instance_from_range<StringList>(make_transform_range(deps.sort(), extract_key));
  124. }
  125. template<typename RANGE>
  126. bool is_empty(const RANGE& range)
  127. {
  128.     return boost::begin(range) == boost::end(range);
  129. }
  130. /*****************************************************************************
  131. *   tut test group
  132. *****************************************************************************/
  133. namespace tut
  134. {
  135.     struct deps_data
  136.     {
  137.     };
  138.     typedef test_group<deps_data> deps_group;
  139.     typedef deps_group::object deps_object;
  140.     tut::deps_group depsgr("lldependencies");
  141.     template<> template<>
  142.     void deps_object::test<1>()
  143.     {
  144.         StringDeps deps;
  145.         StringList empty;
  146.         // The quick brown fox jumps over the lazy yellow dog.
  147.         // (note, "The" and "the" are distinct, else this test wouldn't work)
  148.         deps.add("lazy");
  149.         ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")));
  150.         deps.add("jumps");
  151.         ensure("found lazy", deps.get("lazy"));
  152.         ensure("not found dog.", ! deps.get("dog."));
  153.         // NOTE: Maybe it's overkill to test each of these intermediate
  154.         // results before all the interdependencies have been specified. My
  155.         // thought is simply that if the order changes, I'd like to know why.
  156.         // A change to the implementation of boost::topological_sort() would
  157.         // be an acceptable reason, and you can simply update the expected
  158.         // test output.
  159.         ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")("jumps")));
  160.         deps.add("The", 0, empty, list_of("fox")("dog."));
  161.         // Test key accessors
  162.         ensure("empty before deps for missing key", is_empty(deps.get_before_range("bogus")));
  163.         ensure("empty before deps for jumps", is_empty(deps.get_before_range("jumps")));
  164.         ensure_equals(instance_from_range< std::set<std::string> >(deps.get_before_range("The")),
  165.                       make< std::set<std::string> >(list_of("dog.")("fox")));
  166.         // resume building dependencies
  167.         ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")("jumps")("The")));
  168.         deps.add("the", 0, list_of("The"));
  169.         ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")("jumps")("The")("the")));
  170.         deps.add("fox", 0, list_of("The"), list_of("jumps"));
  171.         ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")("The")("the")("fox")("jumps")));
  172.         deps.add("the", 0, list_of("The")); // same, see if cache works
  173.         ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")("The")("the")("fox")("jumps")));
  174.         deps.add("jumps", 0, empty, list_of("over")); // update jumps deps
  175.         ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")("The")("the")("fox")("jumps")));
  176. /*==========================================================================*|
  177.         // It drives me nuts that this test doesn't work in the test
  178.         // framework, because -- for reasons unknown -- running the test
  179.         // framework on Mac OS X 10.5 Leopard and Windows XP Pro, the catch
  180.         // clause below doesn't catch the exception. Something about the TUT
  181.         // test framework?!? The identical code works fine in a standalone
  182.         // test program. Commenting out the test for now, in hopes that our
  183.         // real builds will be able to catch Cycle exceptions...
  184.         try
  185.         {
  186.             // We've already specified fox -> jumps and jumps -> over. Try an
  187.             // impossible constraint.
  188.             deps.add("over", 0, empty, list_of("fox"));
  189.         }
  190.         catch (const StringDeps::Cycle& e)
  191.         {
  192.             std::cout << "Cycle detected: " << e.what() << 'n';
  193.             // It's legal to add() an impossible constraint because we don't
  194.             // detect the cycle until sort(). So sort() can't know the minimum set
  195.             // of nodes to remove to make the StringDeps object valid again.
  196.             // Therefore we must break the cycle by hand.
  197.             deps.remove("over");
  198.         }
  199. |*==========================================================================*/
  200.         deps.add("dog.", 0, list_of("yellow")("lazy"));
  201.         ensure_equals(instance_from_range< std::set<std::string> >(deps.get_after_range("dog.")),
  202.                       make< std::set<std::string> >(list_of("lazy")("yellow")));
  203.         ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")("The")("the")("fox")("jumps")("dog.")));
  204.         deps.add("quick", 0, list_of("The"), list_of("fox")("brown"));
  205.         ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")("The")("the")("quick")("fox")("jumps")("dog.")));
  206.         deps.add("over", 0, list_of("jumps"), list_of("yellow")("the"));
  207.         ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")("The")("quick")("fox")("jumps")("over")("the")("dog.")));
  208.         deps.add("yellow", 0, list_of("the"), list_of("lazy"));
  209.         ensure_equals(sorted_keys(deps), make<StringList>(list_of("The")("quick")("fox")("jumps")("over")("the")("yellow")("lazy")("dog.")));
  210.         deps.add("brown");
  211.         // By now the dependencies are pretty well in place. A change to THIS
  212.         // order should be viewed with suspicion.
  213.         ensure_equals(sorted_keys(deps), make<StringList>(list_of("The")("quick")("brown")("fox")("jumps")("over")("the")("yellow")("lazy")("dog.")));
  214.         StringList keys(make<StringList>(list_of("The")("brown")("dog.")("fox")("jumps")("lazy")("over")("quick")("the")("yellow")));
  215.         ensure_equals(instance_from_range<StringList>(deps.get_key_range()), keys);
  216. #if (! defined(__GNUC__)) || (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 3)
  217.         // This is the succinct way, works on modern compilers
  218.         ensure_equals(instance_from_range<StringList>(make_transform_range(deps.get_range(), extract_key)), keys);
  219. #else   // gcc 3.3
  220.         StringDeps::range got_range(deps.get_range());
  221.         StringDeps::iterator kni = got_range.begin(), knend = got_range.end();
  222.         StringList::iterator ki = keys.begin(), kend = keys.end();
  223.         for ( ; kni != knend && ki != kend; ++kni, ++ki)
  224.         {
  225.             ensure_equals(kni->first, *ki);
  226.         }
  227.         ensure("get_range() returns proper length", kni == knend && ki == kend);
  228. #endif  // gcc 3.3
  229.         // blow off get_node_range() because they're all LLDependenciesEmpty instances
  230.     }
  231.     template<> template<>
  232.     void deps_object::test<2>()
  233.     {
  234.         typedef LLDependencies<std::string, int> NameIndexDeps;
  235.         NameIndexDeps nideps;
  236.         const NameIndexDeps& const_nideps(nideps);
  237.         nideps.add("def", 2, list_of("ghi"));
  238.         nideps.add("ghi", 3);
  239.         nideps.add("abc", 1, list_of("def"));
  240.         NameIndexDeps::range range(nideps.get_range());
  241.         ensure_equals(range.begin()->first, "abc");
  242.         ensure_equals(range.begin()->second, 1);
  243.         range.begin()->second = 0;
  244.         range.begin()->second = 1;
  245.         NameIndexDeps::const_range const_range(const_nideps.get_range());
  246.         NameIndexDeps::const_iterator const_iterator(const_range.begin());
  247.         ++const_iterator;
  248.         ensure_equals(const_iterator->first, "def");
  249.         ensure_equals(const_iterator->second, 2);
  250.         NameIndexDeps::node_range node_range(nideps.get_node_range());
  251.         ensure_equals(instance_from_range<std::vector<int> >(node_range), make< std::vector<int> >(list_of(1)(2)(3)));
  252.         *node_range.begin() = 0;
  253.         *node_range.begin() = 1;
  254.         NameIndexDeps::const_node_range const_node_range(const_nideps.get_node_range());
  255.         ensure_equals(instance_from_range<std::vector<int> >(const_node_range), make< std::vector<int> >(list_of(1)(2)(3)));
  256.         NameIndexDeps::const_key_range const_key_range(const_nideps.get_key_range());
  257.         ensure_equals(instance_from_range<StringList>(const_key_range), make<StringList>(list_of("abc")("def")("ghi")));
  258.         NameIndexDeps::sorted_range sorted(const_nideps.sort());
  259.         NameIndexDeps::sorted_iterator sortiter(sorted.begin());
  260.         ensure_equals(sortiter->first, "ghi");
  261.         ensure_equals(sortiter->second, 3);
  262.         // test all iterator-flavored versions of get_after_range()
  263.         StringList def(make<StringList>(list_of("def")));
  264.         ensure("empty abc before list", is_empty(nideps.get_before_range(nideps.get_range().begin())));
  265.         ensure_equals(instance_from_range<StringList>(nideps.get_after_range(nideps.get_range().begin())),
  266.                       def);
  267.         ensure_equals(instance_from_range<StringList>(const_nideps.get_after_range(const_nideps.get_range().begin())),
  268.                       def);
  269.         ensure_equals(instance_from_range<StringList>(nideps.get_after_range(nideps.get_node_range().begin())),
  270.                       def);
  271.         ensure_equals(instance_from_range<StringList>(const_nideps.get_after_range(const_nideps.get_node_range().begin())),
  272.                       def);
  273.         ensure_equals(instance_from_range<StringList>(nideps.get_after_range(nideps.get_key_range().begin())),
  274.                       def);
  275.         // advance from "ghi" to "def", which must come after "ghi"
  276.         ++sortiter;
  277.         ensure_equals(instance_from_range<StringList>(const_nideps.get_after_range(sortiter)),
  278.                       make<StringList>(list_of("ghi")));
  279.     }
  280. } // namespace tut