diff options
Diffstat (limited to 'indra/llcommon')
-rw-r--r-- | indra/llcommon/CMakeLists.txt | 3 | ||||
-rw-r--r-- | indra/llcommon/indra_constants.h | 4 | ||||
-rw-r--r-- | indra/llcommon/llassettype.cpp | 10 | ||||
-rw-r--r-- | indra/llcommon/llinstancetracker.h | 15 | ||||
-rw-r--r-- | indra/llcommon/tests/llbase64_test.cpp | 2 | ||||
-rw-r--r-- | indra/llcommon/tests/lldate_test.cpp | 2 | ||||
-rw-r--r-- | indra/llcommon/tests/lldependencies_test.cpp | 275 | ||||
-rw-r--r-- | indra/llcommon/tests/llerror_test.cpp | 2 | ||||
-rw-r--r-- | indra/llcommon/tests/llframetimer_test.cpp | 2 | ||||
-rw-r--r-- | indra/llcommon/tests/llrand_test.cpp | 2 | ||||
-rw-r--r-- | indra/llcommon/tests/llsdserialize_test.cpp | 2 | ||||
-rw-r--r-- | indra/llcommon/tests/lluri_test.cpp | 2 | ||||
-rw-r--r-- | indra/llcommon/tests/reflection_test.cpp | 226 | ||||
-rw-r--r-- | indra/llcommon/tests/stringize_test.cpp | 110 |
14 files changed, 643 insertions, 14 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 13778f0f3b..e7aaf3c984 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -300,6 +300,7 @@ LL_ADD_INTEGRATION_TEST(commonmisc "" "${test_libs}") LL_ADD_INTEGRATION_TEST(bitpack "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llbase64 "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lldate "" "${test_libs}") +LL_ADD_INTEGRATION_TEST(lldependencies "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llerror "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llframetimer "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lllazy "" "${test_libs}") @@ -308,6 +309,8 @@ LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lluri "" "${test_libs}") +LL_ADD_INTEGRATION_TEST(reflection "" "${test_libs}") +LL_ADD_INTEGRATION_TEST(stringize "" "${test_libs}") # *TODO - reenable these once tcmalloc libs no longer break the build. #ADD_BUILD_TEST(llallocator llcommon) diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h index 4836d41fb3..6b75a720af 100644 --- a/indra/llcommon/indra_constants.h +++ b/indra/llcommon/indra_constants.h @@ -253,6 +253,10 @@ const U8 SIM_ACCESS_MAX = SIM_ACCESS_ADULT; // group constants const S32 MAX_AGENT_GROUPS = 25; +// attachment constants +const S32 MAX_AGENT_ATTACHMENTS = 38; +const U8 ATTACHMENT_ADD = 0x80; + // god levels const U8 GOD_MAINTENANCE = 250; const U8 GOD_FULL = 200; diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index 78aa6f4f37..b2a92861cc 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -112,12 +112,12 @@ LLAssetDictionary::LLAssetDictionary() ensemble_num <= S32(LLAssetType::AT_FOLDER_ENSEMBLE_END); ensemble_num++) { - addEntry(LLAssetType::EType(ensemble_num), new AssetEntry("ENSEMBLE", "ensemble", "ensemble", "New Folder", DAD_CATEGORY, TRUE, FALSE)); + addEntry(LLAssetType::EType(ensemble_num), new AssetEntry("ENSEMBLE", "ensemble", "ensemble", "New Folder", DAD_CATEGORY, FALSE, FALSE)); } - addEntry(LLAssetType::AT_CURRENT_OUTFIT, new AssetEntry("CURRENT", "current", "current outfit", "Current Outfit", DAD_CATEGORY, FALSE, TRUE)); - addEntry(LLAssetType::AT_OUTFIT, new AssetEntry("OUTFIT", "outfit", "outfit", "New Outfit", DAD_CATEGORY, TRUE, FALSE)); - addEntry(LLAssetType::AT_MY_OUTFITS, new AssetEntry("MY_OUTFITS", "my_otfts", "my outfits", "My Outfits", DAD_CATEGORY, FALSE, TRUE)); + addEntry(LLAssetType::AT_CURRENT_OUTFIT, new AssetEntry("CURRENT", "current", "current outfit", "Current Look", DAD_CATEGORY, FALSE, TRUE)); + addEntry(LLAssetType::AT_OUTFIT, new AssetEntry("OUTFIT", "outfit", "outfit", "New Look", DAD_CATEGORY, FALSE, FALSE)); + addEntry(LLAssetType::AT_MY_OUTFITS, new AssetEntry("MY_OUTFITS", "my_otfts", "my outfits", "My Looks", DAD_CATEGORY, FALSE, TRUE)); addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, "New Folder", DAD_NONE, FALSE, FALSE)); }; @@ -211,7 +211,7 @@ LLAssetType::EType LLAssetType::lookupHumanReadable(const std::string& readable_ iter++) { const AssetEntry *entry = iter->second; - if (readable_name == entry->mHumanName) + if (entry->mHumanName && (readable_name == entry->mHumanName)) { return iter->first; } diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index de25e364fa..ea50acbbc5 100644 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -71,13 +71,17 @@ private: static std::map<KEY, T*>& getMap() { - static std::map<KEY, T*>* sInstances = new std::map<KEY, T*>(); + if (! sInstances) + { + sInstances = new std::map<KEY, T*>; + } return *sInstances; } private: KEY mKey; + static std::map<KEY, T*>* sInstances; }; // explicit specialization for default case where KEY is T* @@ -101,10 +105,17 @@ protected: static std::set<T*>& getSet() // called after getReady() but before go() { - static std::set<T*>* sInstances = new std::set<T*>(); + if (! sInstances) + { + sInstances = new std::set<T*>; + } return *sInstances; } + + static std::set<T*>* sInstances; }; +template <typename T, typename KEY> std::map<KEY, T*>* LLInstanceTracker<T, KEY>::sInstances = NULL; +template <typename T> std::set<T*>* LLInstanceTracker<T, T*>::sInstances = NULL; #endif diff --git a/indra/llcommon/tests/llbase64_test.cpp b/indra/llcommon/tests/llbase64_test.cpp index dde43b5169..6009788b22 100644 --- a/indra/llcommon/tests/llbase64_test.cpp +++ b/indra/llcommon/tests/llbase64_test.cpp @@ -1,5 +1,5 @@ /** - * @file llbase64_tut.cpp + * @file llbase64_test.cpp * @author James Cook * @date 2007-02-04 * diff --git a/indra/llcommon/tests/lldate_test.cpp b/indra/llcommon/tests/lldate_test.cpp index 1e36fdd119..c31259227a 100644 --- a/indra/llcommon/tests/lldate_test.cpp +++ b/indra/llcommon/tests/lldate_test.cpp @@ -1,5 +1,5 @@ /** - * @file lldate_tut.cpp + * @file lldate_test.cpp * @author Adroit * @date 2007-02 * @brief LLDate test cases. diff --git a/indra/llcommon/tests/lldependencies_test.cpp b/indra/llcommon/tests/lldependencies_test.cpp new file mode 100644 index 0000000000..f3c25de8b5 --- /dev/null +++ b/indra/llcommon/tests/lldependencies_test.cpp @@ -0,0 +1,275 @@ +/** + * @file lldependencies_tut.cpp + * @author Nat Goodspeed + * @date 2008-09-17 + * @brief Test of lldependencies.h + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * Copyright (c) 2008, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// STL headers +#include <iostream> +#include <string> +// std headers +// external library headers +#include <boost/assign/list_of.hpp> +// Precompiled header +#include "linden_common.h" +// associated header +#include "../lldependencies.h" +// other Linden headers +#include "../test/lltut.h" + +using boost::assign::list_of; + +#if LL_WINDOWS +#pragma warning (disable : 4675) // "resolved by ADL" -- just as I want! +#endif + +typedef LLDependencies<> StringDeps; +typedef StringDeps::KeyList StringList; + +// We use the very cool boost::assign::list_of() construct to specify vectors +// of strings inline. For reasons on which I'm not entirely clear, though, it +// needs a helper function. You can use list_of() to construct an implicit +// StringList (std::vector<std::string>) by conversion, e.g. for a function +// parameter -- but if you simply write StringList(list_of("etc.")), you get +// ambiguity errors. Shrug! +template<typename CONTAINER> +CONTAINER make(const CONTAINER& data) +{ + return data; +} + +// Display an arbitary value as itself... +template<typename T> +std::ostream& display(std::ostream& out, const T& value) +{ + out << value; + return out; +} + +// ...but display std::string enclosed in double quotes. +template<> +std::ostream& display(std::ostream& out, const std::string& value) +{ + out << '"' << value << '"'; + return out; +} + +// display any sequence compatible with Boost.Range +template<typename SEQUENCE> +std::ostream& display_seq(std::ostream& out, + const std::string& open, const SEQUENCE& seq, const std::string& close) +{ + out << open; + typename boost::range_const_iterator<SEQUENCE>::type + sli = boost::begin(seq), + slend = boost::end(seq); + if (sli != slend) + { + display(out, *sli); + while (++sli != slend) + { + out << ", "; + display(out, *sli); + } + } + out << close; + return out; +} + +// helper to dump a StringList to std::cout if needed +template<typename ENTRY> +std::ostream& operator<<(std::ostream& out, const std::vector<ENTRY>& list) +{ + display_seq(out, "(", list, ")"); + return out; +} + +template<typename ENTRY> +std::ostream& operator<<(std::ostream& out, const std::set<ENTRY>& set) +{ + display_seq(out, "{", set, "}"); + return out; +} + +const std::string& extract_key(const LLDependencies<>::value_type& entry) +{ + return entry.first; +} + +// helper to return a StringList of keys from LLDependencies::sort() +StringList sorted_keys(LLDependencies<>& deps) +{ + // 1. Call deps.sort(), returning a value_type range of (key, node) pairs. + // 2. Use make_transform_range() to obtain a range of just keys. + // 3. Use instance_from_range to instantiate a StringList from that range. + // 4. Return by value "slices" instance_from_range<StringList> (a subclass + // of StringList) to its base class StringList. + return instance_from_range<StringList>(make_transform_range(deps.sort(), extract_key)); +} + +template<typename RANGE> +bool is_empty(const RANGE& range) +{ + return boost::begin(range) == boost::end(range); +} + +/***************************************************************************** +* tut test group +*****************************************************************************/ +namespace tut +{ + struct deps_data + { + }; + typedef test_group<deps_data> deps_group; + typedef deps_group::object deps_object; + tut::deps_group depsgr("lldependencies"); + + template<> template<> + void deps_object::test<1>() + { + StringDeps deps; + StringList empty; + // The quick brown fox jumps over the lazy yellow dog. + // (note, "The" and "the" are distinct, else this test wouldn't work) + deps.add("lazy"); + ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy"))); + deps.add("jumps"); + ensure("found lazy", deps.get("lazy")); + ensure("not found dog.", ! deps.get("dog.")); + // NOTE: Maybe it's overkill to test each of these intermediate + // results before all the interdependencies have been specified. My + // thought is simply that if the order changes, I'd like to know why. + // A change to the implementation of boost::topological_sort() would + // be an acceptable reason, and you can simply update the expected + // test output. + ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")("jumps"))); + deps.add("The", 0, empty, list_of("fox")("dog.")); + // Test key accessors + ensure("empty before deps for missing key", is_empty(deps.get_before_range("bogus"))); + ensure("empty before deps for jumps", is_empty(deps.get_before_range("jumps"))); + ensure_equals(instance_from_range< std::set<std::string> >(deps.get_before_range("The")), + make< std::set<std::string> >(list_of("dog.")("fox"))); + // resume building dependencies + ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")("jumps")("The"))); + deps.add("the", 0, list_of("The")); + ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")("jumps")("The")("the"))); + deps.add("fox", 0, list_of("The"), list_of("jumps")); + ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")("The")("the")("fox")("jumps"))); + deps.add("the", 0, list_of("The")); // same, see if cache works + ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")("The")("the")("fox")("jumps"))); + deps.add("jumps", 0, empty, list_of("over")); // update jumps deps + ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")("The")("the")("fox")("jumps"))); +/*==========================================================================*| + // It drives me nuts that this test doesn't work in the test + // framework, because -- for reasons unknown -- running the test + // framework on Mac OS X 10.5 Leopard and Windows XP Pro, the catch + // clause below doesn't catch the exception. Something about the TUT + // test framework?!? The identical code works fine in a standalone + // test program. Commenting out the test for now, in hopes that our + // real builds will be able to catch Cycle exceptions... + try + { + // We've already specified fox -> jumps and jumps -> over. Try an + // impossible constraint. + deps.add("over", 0, empty, list_of("fox")); + } + catch (const StringDeps::Cycle& e) + { + std::cout << "Cycle detected: " << e.what() << '\n'; + // It's legal to add() an impossible constraint because we don't + // detect the cycle until sort(). So sort() can't know the minimum set + // of nodes to remove to make the StringDeps object valid again. + // Therefore we must break the cycle by hand. + deps.remove("over"); + } +|*==========================================================================*/ + deps.add("dog.", 0, list_of("yellow")("lazy")); + ensure_equals(instance_from_range< std::set<std::string> >(deps.get_after_range("dog.")), + make< std::set<std::string> >(list_of("lazy")("yellow"))); + ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")("The")("the")("fox")("jumps")("dog."))); + deps.add("quick", 0, list_of("The"), list_of("fox")("brown")); + ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")("The")("the")("quick")("fox")("jumps")("dog."))); + deps.add("over", 0, list_of("jumps"), list_of("yellow")("the")); + ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")("The")("quick")("fox")("jumps")("over")("the")("dog."))); + deps.add("yellow", 0, list_of("the"), list_of("lazy")); + ensure_equals(sorted_keys(deps), make<StringList>(list_of("The")("quick")("fox")("jumps")("over")("the")("yellow")("lazy")("dog."))); + deps.add("brown"); + // By now the dependencies are pretty well in place. A change to THIS + // order should be viewed with suspicion. + ensure_equals(sorted_keys(deps), make<StringList>(list_of("The")("quick")("brown")("fox")("jumps")("over")("the")("yellow")("lazy")("dog."))); + + StringList keys(make<StringList>(list_of("The")("brown")("dog.")("fox")("jumps")("lazy")("over")("quick")("the")("yellow"))); + ensure_equals(instance_from_range<StringList>(deps.get_key_range()), keys); +#if (! defined(__GNUC__)) || (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 3) + // This is the succinct way, works on modern compilers + ensure_equals(instance_from_range<StringList>(make_transform_range(deps.get_range(), extract_key)), keys); +#else // gcc 3.3 + StringDeps::range got_range(deps.get_range()); + StringDeps::iterator kni = got_range.begin(), knend = got_range.end(); + StringList::iterator ki = keys.begin(), kend = keys.end(); + for ( ; kni != knend && ki != kend; ++kni, ++ki) + { + ensure_equals(kni->first, *ki); + } + ensure("get_range() returns proper length", kni == knend && ki == kend); +#endif // gcc 3.3 + // blow off get_node_range() because they're all LLDependenciesEmpty instances + } + + template<> template<> + void deps_object::test<2>() + { + typedef LLDependencies<std::string, int> NameIndexDeps; + NameIndexDeps nideps; + const NameIndexDeps& const_nideps(nideps); + nideps.add("def", 2, list_of("ghi")); + nideps.add("ghi", 3); + nideps.add("abc", 1, list_of("def")); + NameIndexDeps::range range(nideps.get_range()); + ensure_equals(range.begin()->first, "abc"); + ensure_equals(range.begin()->second, 1); + range.begin()->second = 0; + range.begin()->second = 1; + NameIndexDeps::const_range const_range(const_nideps.get_range()); + NameIndexDeps::const_iterator const_iterator(const_range.begin()); + ++const_iterator; + ensure_equals(const_iterator->first, "def"); + ensure_equals(const_iterator->second, 2); + NameIndexDeps::node_range node_range(nideps.get_node_range()); + ensure_equals(instance_from_range<std::vector<int> >(node_range), make< std::vector<int> >(list_of(1)(2)(3))); + *node_range.begin() = 0; + *node_range.begin() = 1; + NameIndexDeps::const_node_range const_node_range(const_nideps.get_node_range()); + ensure_equals(instance_from_range<std::vector<int> >(const_node_range), make< std::vector<int> >(list_of(1)(2)(3))); + NameIndexDeps::const_key_range const_key_range(const_nideps.get_key_range()); + ensure_equals(instance_from_range<StringList>(const_key_range), make<StringList>(list_of("abc")("def")("ghi"))); + NameIndexDeps::sorted_range sorted(const_nideps.sort()); + NameIndexDeps::sorted_iterator sortiter(sorted.begin()); + ensure_equals(sortiter->first, "ghi"); + ensure_equals(sortiter->second, 3); + + // test all iterator-flavored versions of get_after_range() + StringList def(make<StringList>(list_of("def"))); + ensure("empty abc before list", is_empty(nideps.get_before_range(nideps.get_range().begin()))); + ensure_equals(instance_from_range<StringList>(nideps.get_after_range(nideps.get_range().begin())), + def); + ensure_equals(instance_from_range<StringList>(const_nideps.get_after_range(const_nideps.get_range().begin())), + def); + ensure_equals(instance_from_range<StringList>(nideps.get_after_range(nideps.get_node_range().begin())), + def); + ensure_equals(instance_from_range<StringList>(const_nideps.get_after_range(const_nideps.get_node_range().begin())), + def); + ensure_equals(instance_from_range<StringList>(nideps.get_after_range(nideps.get_key_range().begin())), + def); + // advance from "ghi" to "def", which must come after "ghi" + ++sortiter; + ensure_equals(instance_from_range<StringList>(const_nideps.get_after_range(sortiter)), + make<StringList>(list_of("ghi"))); + } +} // namespace tut diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp index 8055647b94..1558df231a 100644 --- a/indra/llcommon/tests/llerror_test.cpp +++ b/indra/llcommon/tests/llerror_test.cpp @@ -1,5 +1,5 @@ /** - * @file llerror_tut.cpp + * @file llerror_test.cpp * @date December 2006 * @brief error unit tests * diff --git a/indra/llcommon/tests/llframetimer_test.cpp b/indra/llcommon/tests/llframetimer_test.cpp index 737c996d0f..1d047e41f8 100644 --- a/indra/llcommon/tests/llframetimer_test.cpp +++ b/indra/llcommon/tests/llframetimer_test.cpp @@ -1,5 +1,5 @@ /** - * @file lltiming_tut.cpp + * @file lltiming_test.cpp * @date 2006-07-23 * @brief Tests the timers. * diff --git a/indra/llcommon/tests/llrand_test.cpp b/indra/llcommon/tests/llrand_test.cpp index e5100e51dc..1f178d6fc9 100644 --- a/indra/llcommon/tests/llrand_test.cpp +++ b/indra/llcommon/tests/llrand_test.cpp @@ -1,5 +1,5 @@ /** - * @file llrandom_tut.cpp + * @file llrandom_test.cpp * @author Phoenix * @date 2007-01-25 * diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp index 8f6d9d8e26..6ab48ec34a 100644 --- a/indra/llcommon/tests/llsdserialize_test.cpp +++ b/indra/llcommon/tests/llsdserialize_test.cpp @@ -1,5 +1,5 @@ /** - * @file llsdserialize_tut.cpp + * @file llsdserialize_test.cpp * @date 2006-04 * @brief LLSDSerialize unit tests * diff --git a/indra/llcommon/tests/lluri_test.cpp b/indra/llcommon/tests/lluri_test.cpp index 4e5ad0df58..0a7c37d4b9 100644 --- a/indra/llcommon/tests/lluri_test.cpp +++ b/indra/llcommon/tests/lluri_test.cpp @@ -1,5 +1,5 @@ /** - * @file lluri_tut.cpp + * @file lluri_test.cpp * @brief LLURI unit tests * @date September 2006 * diff --git a/indra/llcommon/tests/reflection_test.cpp b/indra/llcommon/tests/reflection_test.cpp new file mode 100644 index 0000000000..5263e7fa64 --- /dev/null +++ b/indra/llcommon/tests/reflection_test.cpp @@ -0,0 +1,226 @@ +/** + * @file reflection_test.cpp + * @date May 2006 + * @brief Reflection unit tests. + * + * $LicenseInfo:firstyear=2006&license=viewergpl$ + * + * Copyright (c) 2006-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "../linden_common.h" +#include "../reflective.h" +#include "../metaclasst.h" +#include "../metapropertyt.h" +#include "../stdtypes.h" + +#include "../test/lltut.h" + +namespace tut +{ + class TestAggregatedData : public LLReflective + { + public: + TestAggregatedData() {;} + virtual const LLMetaClass& getMetaClass() const; + + private: + }; + + class TestReflectionData : public LLReflective + { + public: + TestReflectionData() : mInt(42), mString("foo"), mNullPtr(NULL), mPtr(new TestAggregatedData()), mRef(*(new TestAggregatedData)) {;} + virtual ~TestReflectionData() {delete mPtr;} + virtual const LLMetaClass& getMetaClass() const; + + static U32 getPropertyCount() {return 5;} + + private: + + friend class LLMetaClassT<TestReflectionData>; + S32 mInt; + std::string mString; + TestAggregatedData* mNullPtr; + TestAggregatedData* mPtr; + TestAggregatedData mObj; + TestAggregatedData& mRef; + }; +} + +template <> +void LLMetaClassT<tut::TestReflectionData>::reflectProperties(LLMetaClass& meta_class) +{ + reflectProperty(meta_class, "mInt", &tut::TestReflectionData::mInt); + reflectProperty(meta_class, "mString", &tut::TestReflectionData::mString); + reflectPtrProperty(meta_class, "mNullPtr", &tut::TestReflectionData::mNullPtr); + reflectPtrProperty(meta_class, "mPtr", &tut::TestReflectionData::mPtr); + reflectProperty(meta_class, "mObj", &tut::TestReflectionData::mObj); + //reflectProperty(meta_class, "mRef", &tut::TestReflectionData::mRef); // AARGH! +} + +namespace tut +{ + // virtual + const LLMetaClass& TestReflectionData::getMetaClass() const + { + return LLMetaClassT<TestReflectionData>::instance(); + } + + const LLMetaClass& TestAggregatedData::getMetaClass() const + { + return LLMetaClassT<TestAggregatedData>::instance(); + } +} + +namespace tut +{ + typedef tut::test_group<TestReflectionData> TestReflectionGroup; + typedef TestReflectionGroup::object TestReflectionObject; + TestReflectionGroup gTestReflectionGroup("reflection"); + + template<> template<> + void TestReflectionObject::test<1>() + { + // Check properties can be found. + const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance(); + const LLMetaProperty* null = NULL; + ensure_not_equals(meta_class.findProperty("mInt"), null); + ensure_not_equals(meta_class.findProperty("mString"), null); + } + + template<> template<> + void TestReflectionObject::test<2>() + { + // Check non-existent property cannot be found. + const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance(); + const LLMetaProperty* null = NULL; + ensure_equals(meta_class.findProperty("foo"), null); + } + + template<> template<> + void TestReflectionObject::test<3>() + { + // Check integer property has correct value. + const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance(); + ensure_equals(meta_class.findProperty("mInt")->getLLSD(this).asInteger(), 42); + } + + template<> template<> + void TestReflectionObject::test<4>() + { + // Check string property has correct value. + const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance(); + ensure_equals(meta_class.findProperty("mString")->getLLSD(this).asString(), std::string("foo")); + } + + template<> template<> + void TestReflectionObject::test<5>() + { + // Check NULL reference property has correct value. + const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance(); + const LLReflective* null = NULL; + ensure_equals(meta_class.findProperty("mNullPtr")->get(this), null); + } + + template<> template<> + void TestReflectionObject::test<6>() + { + // Check reference property has correct value. + const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance(); + const LLReflective* null = NULL; + const LLReflective* ref = meta_class.findProperty("mPtr")->get(this); + ensure_not_equals(ref, null); + } + + template<> template<> + void TestReflectionObject::test<7>() + { + // Check reflective property has correct value. + const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance(); + const LLReflective* null = NULL; + const LLReflective* ref = meta_class.findProperty("mObj")->get(this); + ensure_not_equals(ref, null); + } + + template<> template<> + void TestReflectionObject::test<8>() + { + // Check property count. + const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance(); + ensure_equals(meta_class.getPropertyCount(), TestReflectionData::getPropertyCount()); + } + + template<> template<> + void TestReflectionObject::test<9>() + { + // Check property iteration. + const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance(); + U32 count = 0; + LLMetaClass::PropertyIterator iter; + for(iter = meta_class.beginProperties(); iter != meta_class.endProperties(); ++iter) + { + ++count; + } + ensure_equals(count, TestReflectionData::getPropertyCount()); + } + + template<> template<> + void TestReflectionObject::test<10>() + { + // Check meta classes of different types do not compare equal. + const LLMetaClass* reflection_data_meta_class = &(LLMetaClassT<TestReflectionData>::instance()); + const LLMetaClass* aggregated_data_meta_class = &(LLMetaClassT<TestAggregatedData>::instance()); + ensure_not_equals(reflection_data_meta_class, aggregated_data_meta_class); + } + + template<> template<> + void TestReflectionObject::test<11>() + { + // Check class cast checks. + const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance(); + TestAggregatedData* aggregated_data = new TestAggregatedData(); + LLMetaClass::PropertyIterator iter; + U32 exception_count = 0; + for(iter = meta_class.beginProperties(); iter != meta_class.endProperties(); ++iter) + { + try + { + const LLMetaProperty* property = (*iter).second; + const LLReflective* reflective = property->get(aggregated_data); // Wrong reflective type, should throw exception. + + // useless op to get rid of compiler warning. + reflective = NULL; + } + catch(...) + { + ++exception_count; + } + } + ensure_equals(exception_count, getPropertyCount()); + + } +} diff --git a/indra/llcommon/tests/stringize_test.cpp b/indra/llcommon/tests/stringize_test.cpp new file mode 100644 index 0000000000..dd69787a1c --- /dev/null +++ b/indra/llcommon/tests/stringize_test.cpp @@ -0,0 +1,110 @@ +/** + * @file stringize_test.cpp + * @author Nat Goodspeed + * @date 2008-09-12 + * @brief Test of stringize.h + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +/*==========================================================================*| +#if LL_WINDOWS +#pragma warning (disable : 4675) // "resolved by ADL" -- just as I want! +#endif +|*==========================================================================*/ + +// STL headers +#include <iomanip> + +// Precompiled header +#include "linden_common.h" + +// associated header +#include "../stringize.h" + +// std headers +// external library headers +// other Linden headers +#include "../llsd.h" + +#include "../test/lltut.h" + +namespace tut +{ + struct stringize_data + { + stringize_data(): + c('c'), + s(17), + i(34), + l(68), + f(3.14159265358979f), + d(3.14159265358979), + // Including a space differentiates this from + // boost::lexical_cast<std::string>, which doesn't handle embedded + // spaces so well. + abc("abc def") + { + llsd["i"] = i; + llsd["d"] = d; + llsd["abc"] = abc; + } + + char c; + short s; + int i; + long l; + float f; + double d; + std::string abc; + LLSD llsd; + }; + typedef test_group<stringize_data> stringize_group; + typedef stringize_group::object stringize_object; + tut::stringize_group strzgrp("stringize"); + + template<> template<> + void stringize_object::test<1>() + { + ensure_equals(stringize(c), "c"); + ensure_equals(stringize(s), "17"); + ensure_equals(stringize(i), "34"); + ensure_equals(stringize(l), "68"); + ensure_equals(stringize(f), "3.14159"); + ensure_equals(stringize(d), "3.14159"); + ensure_equals(stringize(abc), "abc def"); + ensure_equals(stringize(llsd), "{'abc':'abc def','d':r3.14159,'i':i34}"); + } + + template<> template<> + void stringize_object::test<2>() + { + ensure_equals(STRINGIZE("c is " << c), "c is c"); + ensure_equals(STRINGIZE(std::setprecision(4) << d), "3.142"); + } +} // namespace tut |