From 6cb718568469e6138ecd0d40c6218da6d0359f0a Mon Sep 17 00:00:00 2001 From: Steven Bennetts Date: Thu, 8 Oct 2009 02:16:29 +0000 Subject: * EXT-1282 Fixed a crash when attempting to display strings with [] in them (merged from viewer-2.0-qa-4) --- indra/llcommon/llstring.cpp | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index 6516d1779e..f2edd5c559 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -1018,7 +1018,11 @@ S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions) bool found_replacement = false; std::string replacement; - if (tokens.size() == 1) + if (tokens.size() == 0) + { + found_replacement = false; + } + else if (tokens.size() == 1) { found_replacement = simpleReplacement (replacement, tokens[0], substitutions); } @@ -1054,9 +1058,9 @@ S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions) } else { - // we had no replacement, so leave the string we searched for so that it gets noticed by QA - // "hello [NAME_NOT_FOUND]" is output - output += std::string("[") + tokens[0] + std::string("]"); + // we had no replacement, use the string as is + // e.g. "hello [MISSING_REPLACEMENT]" or "-=[Stylized Name]=-" + output += std::string(s, key_start, start-key_start); } tokens.clear(); } @@ -1092,7 +1096,11 @@ S32 LLStringUtil::format(std::string& s, const LLSD& substitutions) bool found_replacement = false; std::string replacement; - if (tokens.size() == 1) + if (tokens.size() == 0) + { + found_replacement = false; + } + else if (tokens.size() == 1) { found_replacement = simpleReplacement (replacement, tokens[0], substitutions); } @@ -1120,9 +1128,9 @@ S32 LLStringUtil::format(std::string& s, const LLSD& substitutions) } else { - // we had no replacement, so leave the string we searched for so that it gets noticed by QA - // "hello [NAME_NOT_FOUND]" is output - output += std::string("[") + tokens[0] + std::string("]"); + // we had no replacement, use the string as is + // e.g. "hello [MISSING_REPLACEMENT]" or "-=[Stylized Name]=-" + output += std::string(s, key_start, start-key_start); } tokens.clear(); } -- cgit v1.3 From 7db4992f34c67b5585a3250b21efbd27393d38d7 Mon Sep 17 00:00:00 2001 From: Adam Moss Date: Thu, 8 Oct 2009 11:47:27 +0000 Subject: DEV-41081 turn llstring_tut into a real llcommon unit (well, integration :() test. --- indra/llcommon/CMakeLists.txt | 9 +- indra/llcommon/tests/llstring_test.cpp | 745 +++++++++++++++++++++++++++++++++ 2 files changed, 750 insertions(+), 4 deletions(-) create mode 100644 indra/llcommon/tests/llstring_test.cpp (limited to 'indra/llcommon') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index bc4e44d7e6..ad1eb1b310 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -3,7 +3,6 @@ project(llcommon) include(00-Common) -include(LLAddBuildTest) include(LLCommon) include(Boost) @@ -224,8 +223,7 @@ set_source_files_properties(${llcommon_HEADER_FILES} list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES}) add_library (llcommon ${llcommon_SOURCE_FILES}) -target_link_libraries( - llcommon +target_link_libraries(llcommon ${APRUTIL_LIBRARIES} ${APR_LIBRARIES} ${EXPAT_LIBRARIES} @@ -234,7 +232,8 @@ target_link_libraries( ${BOOST_REGEX_LIBRARY} ) -include(LLAddBuildTest) +#add unit tests +INCLUDE(LLAddBuildTest) SET(llcommon_TEST_SOURCE_FILES ) LL_ADD_PROJECT_UNIT_TESTS(llcommon "${llcommon_TEST_SOURCE_FILES}") @@ -244,6 +243,8 @@ set(test_libs llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES}) # Have to treat lllazy test as an integration test until this issue is resolved: # https://jira.lindenlab.com/jira/browse/DEV-29456 LL_ADD_INTEGRATION_TEST(lllazy lllazy.cpp "${test_libs}") +# Also puzzled as to why *CMake* barfs when this is a *unit* test. +LL_ADD_INTEGRATION_TEST(llstring llstring.cpp "${test_libs}") # *TODO - reenable these once tcmalloc libs no longer break the build. #ADD_BUILD_TEST(llallocator llcommon) diff --git a/indra/llcommon/tests/llstring_test.cpp b/indra/llcommon/tests/llstring_test.cpp new file mode 100644 index 0000000000..13894efad0 --- /dev/null +++ b/indra/llcommon/tests/llstring_test.cpp @@ -0,0 +1,745 @@ +/** + * @file llstring_test.cpp + * @author Adroit, Steve Linden, Tofu Linden + * @date 2006-12-24 + * @brief Test cases of llstring.cpp + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-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 "../test/lltut.h" + +#include "../llstring.h" + +namespace tut +{ + struct string_index + { + }; + typedef test_group string_index_t; + typedef string_index_t::object string_index_object_t; + tut::string_index_t tut_string_index("string_test"); + + template<> template<> + void string_index_object_t::test<1>() + { + std::string llstr1; + ensure("Empty std::string", (llstr1.size() == 0) && llstr1.empty()); + + std::string llstr2("Hello"); + ensure("std::string = Hello", (!strcmp(llstr2.c_str(), "Hello")) && (llstr2.size() == 5) && !llstr2.empty()); + + std::string llstr3(llstr2); + ensure("std::string = std::string(std::string)", (!strcmp(llstr3.c_str(), "Hello")) && (llstr3.size() == 5) && !llstr3.empty()); + + std::string str("Hello World"); + std::string llstr4(str, 6); + ensure("std::string = std::string(s, size_type pos, size_type n = npos)", (!strcmp(llstr4.c_str(), "World")) && (llstr4.size() == 5) && !llstr4.empty()); + + std::string llstr5(str, str.size()); + ensure("std::string = std::string(s, size_type pos, size_type n = npos)", (llstr5.size() == 0) && llstr5.empty()); + + std::string llstr6(5, 'A'); + ensure("std::string = std::string(count, c)", (!strcmp(llstr6.c_str(), "AAAAA")) && (llstr6.size() == 5) && !llstr6.empty()); + + std::string llstr7("Hello World", 5); + ensure("std::string(s, n)", (!strcmp(llstr7.c_str(), "Hello")) && (llstr7.size() == 5) && !llstr7.empty()); + + std::string llstr8("Hello World", 6, 5); + ensure("std::string(s, n, count)", (!strcmp(llstr8.c_str(), "World")) && (llstr8.size() == 5) && !llstr8.empty()); + + std::string llstr9("Hello World", sizeof("Hello World")-1, 5); // go past end + ensure("std::string(s, n, count) goes past end", (llstr9.size() == 0) && llstr9.empty()); + } + + template<> template<> + void string_index_object_t::test<3>() + { + std::string str("Len=5"); + ensure("isValidIndex failed", LLStringUtil::isValidIndex(str, 0) == TRUE && + LLStringUtil::isValidIndex(str, 5) == TRUE && + LLStringUtil::isValidIndex(str, 6) == FALSE); + + std::string str1; + ensure("isValidIndex failed fo rempty string", LLStringUtil::isValidIndex(str1, 0) == FALSE); + } + + template<> template<> + void string_index_object_t::test<4>() + { + std::string str_val(" Testing the extra whitespaces "); + LLStringUtil::trimHead(str_val); + ensure_equals("1: trimHead failed", str_val, "Testing the extra whitespaces "); + + std::string str_val1("\n\t\r\n Testing the extra whitespaces "); + LLStringUtil::trimHead(str_val1); + ensure_equals("2: trimHead failed", str_val1, "Testing the extra whitespaces "); + } + + template<> template<> + void string_index_object_t::test<5>() + { + std::string str_val(" Testing the extra whitespaces "); + LLStringUtil::trimTail(str_val); + ensure_equals("1: trimTail failed", str_val, " Testing the extra whitespaces"); + + std::string str_val1("\n Testing the extra whitespaces \n\t\r\n "); + LLStringUtil::trimTail(str_val1); + ensure_equals("2: trimTail failed", str_val1, "\n Testing the extra whitespaces"); + } + + + template<> template<> + void string_index_object_t::test<6>() + { + std::string str_val(" \t \r Testing the extra \r\n whitespaces \n \t "); + LLStringUtil::trim(str_val); + ensure_equals("1: trim failed", str_val, "Testing the extra \r\n whitespaces"); + } + + template<> template<> + void string_index_object_t::test<7>() + { + std::string str("Second LindenLabs"); + LLStringUtil::truncate(str, 6); + ensure_equals("1: truncate", str, "Second"); + + // further truncate more than the length + LLStringUtil::truncate(str, 0); + ensure_equals("2: truncate", str, ""); + } + + template<> template<> + void string_index_object_t::test<8>() + { + std::string str_val("SecondLife Source"); + LLStringUtil::toUpper(str_val); + ensure_equals("toUpper failed", str_val, "SECONDLIFE SOURCE"); + } + + template<> template<> + void string_index_object_t::test<9>() + { + std::string str_val("SecondLife Source"); + LLStringUtil::toLower(str_val); + ensure_equals("toLower failed", str_val, "secondlife source"); + } + + template<> template<> + void string_index_object_t::test<10>() + { + std::string str_val("Second"); + ensure("1. isHead failed", LLStringUtil::isHead(str_val, "SecondLife Source") == TRUE); + ensure("2. isHead failed", LLStringUtil::isHead(str_val, " SecondLife Source") == FALSE); + std::string str_val2(""); + ensure("3. isHead failed", LLStringUtil::isHead(str_val2, "") == FALSE); + } + + template<> template<> + void string_index_object_t::test<11>() + { + std::string str_val("Hello.\n\n Lindenlabs. \n This is \na simple test.\n"); + std::string orig_str_val(str_val); + LLStringUtil::addCRLF(str_val); + ensure_equals("addCRLF failed", str_val, "Hello.\r\n\r\n Lindenlabs. \r\n This is \r\na simple test.\r\n"); + LLStringUtil::removeCRLF(str_val); + ensure_equals("removeCRLF failed", str_val, orig_str_val); + } + + template<> template<> + void string_index_object_t::test<12>() + { + std::string str_val("Hello.\n\n\t \t Lindenlabs. \t\t"); + std::string orig_str_val(str_val); + LLStringUtil::replaceTabsWithSpaces(str_val, 1); + ensure_equals("replaceTabsWithSpaces failed", str_val, "Hello.\n\n Lindenlabs. "); + LLStringUtil::replaceTabsWithSpaces(orig_str_val, 0); + ensure_equals("replaceTabsWithSpaces failed for 0", orig_str_val, "Hello.\n\n Lindenlabs. "); + + str_val = "\t\t\t\t"; + LLStringUtil::replaceTabsWithSpaces(str_val, 0); + ensure_equals("replaceTabsWithSpaces failed for all tabs", str_val, ""); + } + + template<> template<> + void string_index_object_t::test<13>() + { + std::string str_val("Hello.\n\n\t\t\r\nLindenlabsX."); + LLStringUtil::replaceNonstandardASCII(str_val, 'X'); + ensure_equals("replaceNonstandardASCII failed", str_val, "Hello.\n\nXXX\nLindenlabsX."); + } + + template<> template<> + void string_index_object_t::test<14>() + { + std::string str_val("Hello.\n\t\r\nABCDEFGHIABABAB"); + LLStringUtil::replaceChar(str_val, 'A', 'X'); + ensure_equals("1: replaceChar failed", str_val, "Hello.\n\t\r\nXBCDEFGHIXBXBXB"); + std::string str_val1("Hello.\n\t\r\nABCDEFGHIABABAB"); + } + + template<> template<> + void string_index_object_t::test<15>() + { + std::string str_val("Hello.\n\r\t"); + ensure("containsNonprintable failed", LLStringUtil::containsNonprintable(str_val) == TRUE); + + str_val = "ABC "; + ensure("containsNonprintable failed", LLStringUtil::containsNonprintable(str_val) == FALSE); + } + + template<> template<> + void string_index_object_t::test<16>() + { + std::string str_val("Hello.\n\r\t Again!"); + LLStringUtil::stripNonprintable(str_val); + ensure_equals("stripNonprintable failed", str_val, "Hello. Again!"); + + str_val = "\r\n\t\t"; + LLStringUtil::stripNonprintable(str_val); + ensure_equals("stripNonprintable resulting in empty string failed", str_val, ""); + } + + template<> template<> + void string_index_object_t::test<17>() + { + BOOL value; + std::string str_val("1"); + ensure("convertToBOOL 1 failed", LLStringUtil::convertToBOOL(str_val, value) && value); + str_val = "T"; + ensure("convertToBOOL T failed", LLStringUtil::convertToBOOL(str_val, value) && value); + str_val = "t"; + ensure("convertToBOOL t failed", LLStringUtil::convertToBOOL(str_val, value) && value); + str_val = "TRUE"; + ensure("convertToBOOL TRUE failed", LLStringUtil::convertToBOOL(str_val, value) && value); + str_val = "True"; + ensure("convertToBOOL True failed", LLStringUtil::convertToBOOL(str_val, value) && value); + str_val = "true"; + ensure("convertToBOOL true failed", LLStringUtil::convertToBOOL(str_val, value) && value); + + str_val = "0"; + ensure("convertToBOOL 0 failed", LLStringUtil::convertToBOOL(str_val, value) && !value); + str_val = "F"; + ensure("convertToBOOL F failed", LLStringUtil::convertToBOOL(str_val, value) && !value); + str_val = "f"; + ensure("convertToBOOL f failed", LLStringUtil::convertToBOOL(str_val, value) && !value); + str_val = "FALSE"; + ensure("convertToBOOL FASLE failed", LLStringUtil::convertToBOOL(str_val, value) && !value); + str_val = "False"; + ensure("convertToBOOL False failed", LLStringUtil::convertToBOOL(str_val, value) && !value); + str_val = "false"; + ensure("convertToBOOL false failed", LLStringUtil::convertToBOOL(str_val, value) && !value); + + str_val = "Tblah"; + ensure("convertToBOOL false failed", !LLStringUtil::convertToBOOL(str_val, value)); + } + + template<> template<> + void string_index_object_t::test<18>() + { + U8 value; + std::string str_val("255"); + ensure("1: convertToU8 failed", LLStringUtil::convertToU8(str_val, value) && value == 255); + + str_val = "0"; + ensure("2: convertToU8 failed", LLStringUtil::convertToU8(str_val, value) && value == 0); + + str_val = "-1"; + ensure("3: convertToU8 failed", !LLStringUtil::convertToU8(str_val, value)); + + str_val = "256"; // bigger than MAX_U8 + ensure("4: convertToU8 failed", !LLStringUtil::convertToU8(str_val, value)); + } + + template<> template<> + void string_index_object_t::test<19>() + { + S8 value; + std::string str_val("127"); + ensure("1: convertToS8 failed", LLStringUtil::convertToS8(str_val, value) && value == 127); + + str_val = "0"; + ensure("2: convertToS8 failed", LLStringUtil::convertToS8(str_val, value) && value == 0); + + str_val = "-128"; + ensure("3: convertToS8 failed", LLStringUtil::convertToS8(str_val, value) && value == -128); + + str_val = "128"; // bigger than MAX_S8 + ensure("4: convertToS8 failed", !LLStringUtil::convertToS8(str_val, value)); + + str_val = "-129"; + ensure("5: convertToS8 failed", !LLStringUtil::convertToS8(str_val, value)); + } + + template<> template<> + void string_index_object_t::test<20>() + { + S16 value; + std::string str_val("32767"); + ensure("1: convertToS16 failed", LLStringUtil::convertToS16(str_val, value) && value == 32767); + + str_val = "0"; + ensure("2: convertToS16 failed", LLStringUtil::convertToS16(str_val, value) && value == 0); + + str_val = "-32768"; + ensure("3: convertToS16 failed", LLStringUtil::convertToS16(str_val, value) && value == -32768); + + str_val = "32768"; + ensure("4: convertToS16 failed", !LLStringUtil::convertToS16(str_val, value)); + + str_val = "-32769"; + ensure("5: convertToS16 failed", !LLStringUtil::convertToS16(str_val, value)); + } + + template<> template<> + void string_index_object_t::test<21>() + { + U16 value; + std::string str_val("65535"); //0xFFFF + ensure("1: convertToU16 failed", LLStringUtil::convertToU16(str_val, value) && value == 65535); + + str_val = "0"; + ensure("2: convertToU16 failed", LLStringUtil::convertToU16(str_val, value) && value == 0); + + str_val = "-1"; + ensure("3: convertToU16 failed", !LLStringUtil::convertToU16(str_val, value)); + + str_val = "65536"; + ensure("4: convertToU16 failed", !LLStringUtil::convertToU16(str_val, value)); + } + + template<> template<> + void string_index_object_t::test<22>() + { + U32 value; + std::string str_val("4294967295"); //0xFFFFFFFF + ensure("1: convertToU32 failed", LLStringUtil::convertToU32(str_val, value) && value == 4294967295UL); + + str_val = "0"; + ensure("2: convertToU32 failed", LLStringUtil::convertToU32(str_val, value) && value == 0); + + str_val = "4294967296"; + ensure("3: convertToU32 failed", !LLStringUtil::convertToU32(str_val, value)); + } + + template<> template<> + void string_index_object_t::test<23>() + { + S32 value; + std::string str_val("2147483647"); //0x7FFFFFFF + ensure("1: convertToS32 failed", LLStringUtil::convertToS32(str_val, value) && value == 2147483647); + + str_val = "0"; + ensure("2: convertToS32 failed", LLStringUtil::convertToS32(str_val, value) && value == 0); + + // Avoid "unary minus operator applied to unsigned type" warning on VC++. JC + S32 min_val = -2147483647 - 1; + str_val = "-2147483648"; + ensure("3: convertToS32 failed", LLStringUtil::convertToS32(str_val, value) && value == min_val); + + str_val = "2147483648"; + ensure("4: convertToS32 failed", !LLStringUtil::convertToS32(str_val, value)); + + str_val = "-2147483649"; + ensure("5: convertToS32 failed", !LLStringUtil::convertToS32(str_val, value)); + } + + template<> template<> + void string_index_object_t::test<24>() + { + F32 value; + std::string str_val("2147483647"); //0x7FFFFFFF + ensure("1: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == 2147483647); + + str_val = "0"; + ensure("2: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == 0); + + /* Need to find max/min F32 values + str_val = "-2147483648"; + ensure("3: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == -2147483648); + + str_val = "2147483648"; + ensure("4: convertToF32 failed", !LLStringUtil::convertToF32(str_val, value)); + + str_val = "-2147483649"; + ensure("5: convertToF32 failed", !LLStringUtil::convertToF32(str_val, value)); + */ + } + + template<> template<> + void string_index_object_t::test<25>() + { + F64 value; + std::string str_val("9223372036854775807"); //0x7FFFFFFFFFFFFFFF + ensure("1: convertToF64 failed", LLStringUtil::convertToF64(str_val, value) && value == 9223372036854775807LL); + + str_val = "0"; + ensure("2: convertToF64 failed", LLStringUtil::convertToF64(str_val, value) && value == 0.0F); + + /* Need to find max/min F64 values + str_val = "-2147483648"; + ensure("3: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == -2147483648); + + str_val = "2147483648"; + ensure("4: convertToF32 failed", !LLStringUtil::convertToF32(str_val, value)); + + str_val = "-2147483649"; + ensure("5: convertToF32 failed", !LLStringUtil::convertToF32(str_val, value)); + */ + } + + template<> template<> + void string_index_object_t::test<26>() + { + const char* str1 = NULL; + const char* str2 = NULL; + + ensure("1: compareStrings failed", LLStringUtil::compareStrings(str1, str2) == 0); + str2 = "A"; + ensure("2: compareStrings failed", LLStringUtil::compareStrings(str1, str2) > 0); + ensure("3: compareStrings failed", LLStringUtil::compareStrings(str2, str1) < 0); + + str1 = "A is smaller than B"; + str2 = "B is greater than A"; + ensure("4: compareStrings failed", LLStringUtil::compareStrings(str1, str2) < 0); + + str2 = "A is smaller than B"; + ensure("5: compareStrings failed", LLStringUtil::compareStrings(str1, str2) == 0); + } + + template<> template<> + void string_index_object_t::test<27>() + { + const char* str1 = NULL; + const char* str2 = NULL; + + ensure("1: compareInsensitive failed", LLStringUtil::compareInsensitive(str1, str2) == 0); + str2 = "A"; + ensure("2: compareInsensitive failed", LLStringUtil::compareInsensitive(str1, str2) > 0); + ensure("3: compareInsensitive failed", LLStringUtil::compareInsensitive(str2, str1) < 0); + + str1 = "A is equal to a"; + str2 = "a is EQUAL to A"; + ensure("4: compareInsensitive failed", LLStringUtil::compareInsensitive(str1, str2) == 0); + } + + template<> template<> + void string_index_object_t::test<28>() + { + std::string lhs_str("PROgraM12files"); + std::string rhs_str("PROgram12Files"); + ensure("compareDict 1 failed", LLStringUtil::compareDict(lhs_str, rhs_str) < 0); + ensure("precedesDict 1 failed", LLStringUtil::precedesDict(lhs_str, rhs_str) == TRUE); + + lhs_str = "PROgram12Files"; + rhs_str = "PROgram12Files"; + ensure("compareDict 2 failed", LLStringUtil::compareDict(lhs_str, rhs_str) == 0); + ensure("precedesDict 2 failed", LLStringUtil::precedesDict(lhs_str, rhs_str) == FALSE); + + lhs_str = "PROgram12Files"; + rhs_str = "PROgRAM12FILES"; + ensure("compareDict 3 failed", LLStringUtil::compareDict(lhs_str, rhs_str) > 0); + ensure("precedesDict 3 failed", LLStringUtil::precedesDict(lhs_str, rhs_str) == FALSE); + } + + template<> template<> + void string_index_object_t::test<29>() + { + char str1[] = "First String..."; + char str2[100]; + + LLStringUtil::copy(str2, str1, 100); + ensure("LLStringUtil::copy with enough dest length failed", strcmp(str2, str1) == 0); + LLStringUtil::copy(str2, str1, sizeof("First")); + ensure("LLStringUtil::copy with less dest length failed", strcmp(str2, "First") == 0); + } + + template<> template<> + void string_index_object_t::test<30>() + { + std::string str1 = "This is the sentence..."; + std::string str2 = "This is the "; + std::string str3 = "first "; + std::string str4 = "This is the first sentence..."; + std::string str5 = "This is the sentence...first "; + std::string dest; + + dest = str1; + LLStringUtil::copyInto(dest, str3, str2.length()); + ensure("LLStringUtil::copyInto insert failed", dest == str4); + + dest = str1; + LLStringUtil::copyInto(dest, str3, dest.length()); + ensure("LLStringUtil::copyInto append failed", dest == str5); + } + + template<> template<> + void string_index_object_t::test<31>() + { + std::string stripped; + + // Plain US ASCII text, including spaces and punctuation, + // should not be altered. + std::string simple_text = "Hello, world!"; + stripped = LLStringFn::strip_invalid_xml(simple_text); + ensure("Simple text passed unchanged", stripped == simple_text); + + // Control characters should be removed + // except for 0x09, 0x0a, 0x0d + std::string control_chars; + for (char c = 0x01; c < 0x20; c++) + { + control_chars.push_back(c); + } + std::string allowed_control_chars; + allowed_control_chars.push_back( (char)0x09 ); + allowed_control_chars.push_back( (char)0x0a ); + allowed_control_chars.push_back( (char)0x0d ); + + stripped = LLStringFn::strip_invalid_xml(control_chars); + ensure("Only tab, LF, CR control characters allowed", + stripped == allowed_control_chars); + + // UTF-8 should be passed intact, including high byte + // characters. Try Francais (with C squiggle cedilla) + std::string french = "Fran"; + french.push_back( (char)0xC3 ); + french.push_back( (char)0xA7 ); + french += "ais"; + stripped = LLStringFn::strip_invalid_xml( french ); + ensure("UTF-8 high byte text is allowed", french == stripped ); + } + + template<> template<> + void string_index_object_t::test<32>() + { + // Test LLStringUtil::format() string interpolation + LLStringUtil::format_map_t fmt_map; + std::string s; + int subcount; + + fmt_map["[TRICK1]"] = "[A]"; + fmt_map["[A]"] = "a"; + fmt_map["[B]"] = "b"; + fmt_map["[AAA]"] = "aaa"; + fmt_map["[BBB]"] = "bbb"; + fmt_map["[TRICK2]"] = "[A]"; + fmt_map["[EXPLOIT]"] = "!!!!!!!!!!!![EXPLOIT]!!!!!!!!!!!!"; + fmt_map["[KEYLONGER]"] = "short"; + fmt_map["[KEYSHORTER]"] = "Am I not a long string?"; + fmt_map["?"] = "?"; + fmt_map["[DELETE]"] = ""; + + for (LLStringUtil::format_map_t::const_iterator iter = fmt_map.begin(); iter != fmt_map.end(); ++iter) + { + // Test when source string is entirely one key + std::string s1 = (std::string)iter->first; + std::string s2 = (std::string)iter->second; + subcount = LLStringUtil::format(s1, fmt_map); + ensure_equals("LLStringUtil::format: Raw interpolation result", s1, s2); + if (s1 == "?") + { + ensure_equals("LLStringUtil::format: Raw interpolation result count", 0, subcount); + } + else + { + ensure_equals("LLStringUtil::format: Raw interpolation result count", 1, subcount); + } + } + + for (LLStringUtil::format_map_t::const_iterator iter = fmt_map.begin(); iter != fmt_map.end(); ++iter) + { + // Test when source string is one key, duplicated + std::string s1 = (std::string)iter->first; + std::string s2 = (std::string)iter->second; + s = s1 + s1 + s1 + s1; + subcount = LLStringUtil::format(s, fmt_map); + ensure_equals("LLStringUtil::format: Rawx4 interpolation result", s, s2 + s2 + s2 + s2); + if (s1 == "?") + { + ensure_equals("LLStringUtil::format: Rawx4 interpolation result count", 0, subcount); + } + else + { + ensure_equals("LLStringUtil::format: Rawx4 interpolation result count", 4, subcount); + } + } + + // Test when source string has no keys + std::string srcs = "!!!!!!!!!!!!!!!!"; + s = srcs; + subcount = LLStringUtil::format(s, fmt_map); + ensure_equals("LLStringUtil::format: No key test result", s, srcs); + ensure_equals("LLStringUtil::format: No key test result count", 0, subcount); + + // Test when source string has no keys and is empty + std::string srcs3; + s = srcs3; + subcount = LLStringUtil::format(s, fmt_map); + ensure("LLStringUtil::format: No key test3 result", s.empty()); + ensure_equals("LLStringUtil::format: No key test3 result count", 0, subcount); + + // Test a substitution where a key is substituted with blankness + std::string srcs2 = "[DELETE]"; + s = srcs2; + subcount = LLStringUtil::format(s, fmt_map); + ensure("LLStringUtil::format: Delete key test2 result", s.empty()); + ensure_equals("LLStringUtil::format: Delete key test2 result count", 1, subcount); + + // Test an assorted substitution + std::string srcs4 = "[TRICK1][A][B][AAA][BBB][TRICK2][KEYLONGER][KEYSHORTER]?[DELETE]"; + s = srcs4; + subcount = LLStringUtil::format(s, fmt_map); + ensure_equals("LLStringUtil::format: Assorted Test1 result", s, "[A]abaaabbb[A]shortAm I not a long string??"); + ensure_equals("LLStringUtil::format: Assorted Test1 result count", 9, subcount); + + // Test an assorted substitution + std::string srcs5 = "[DELETE]?[KEYSHORTER][KEYLONGER][TRICK2][BBB][AAA][B][A][TRICK1]"; + s = srcs5; + subcount = LLStringUtil::format(s, fmt_map); + ensure_equals("LLStringUtil::format: Assorted Test2 result", s, "?Am I not a long string?short[A]bbbaaaba[A]"); + ensure_equals("LLStringUtil::format: Assorted Test2 result count", 9, subcount); + + // Test an assorted substitution + std::string srcs8 = "foo[DELETE]bar?"; + s = srcs8; + subcount = LLStringUtil::format(s, fmt_map); + ensure_equals("LLStringUtil::format: Assorted Test3 result", s, "foobar?"); + ensure_equals("LLStringUtil::format: Assorted Test3 result count", 1, subcount); + } + + template<> template<> + void string_index_object_t::test<33>() + { + // Test LLStringUtil::format() string interpolation + LLStringUtil::format_map_t blank_fmt_map; + std::string s; + int subcount; + + // Test substituting out of a blank format_map + std::string srcs6 = "12345"; + s = srcs6; + subcount = LLStringUtil::format(s, blank_fmt_map); + ensure_equals("LLStringUtil::format: Blankfmt Test1 result", s, "12345"); + ensure_equals("LLStringUtil::format: Blankfmt Test1 result count", 0, subcount); + + // Test substituting a blank string out of a blank format_map + std::string srcs7; + s = srcs7; + subcount = LLStringUtil::format(s, blank_fmt_map); + ensure("LLStringUtil::format: Blankfmt Test2 result", s.empty()); + ensure_equals("LLStringUtil::format: Blankfmt Test2 result count", 0, subcount); + } + + template<> template<> + void string_index_object_t::test<34>() + { + // Test that incorrect LLStringUtil::format() use does not explode. + LLStringUtil::format_map_t nasty_fmt_map; + std::string s; + int subcount; + + nasty_fmt_map[""] = "never used"; // see, this is nasty. + + // Test substituting out of a nasty format_map + std::string srcs6 = "12345"; + s = srcs6; + subcount = LLStringUtil::format(s, nasty_fmt_map); + ensure_equals("LLStringUtil::format: Nastyfmt Test1 result", s, "12345"); + ensure_equals("LLStringUtil::format: Nastyfmt Test1 result count", 0, subcount); + + // Test substituting a blank string out of a nasty format_map + std::string srcs7; + s = srcs7; + subcount = LLStringUtil::format(s, nasty_fmt_map); + ensure("LLStringUtil::format: Nastyfmt Test2 result", s.empty()); + ensure_equals("LLStringUtil::format: Nastyfmt Test2 result count", 0, subcount); + } + + template<> template<> + void string_index_object_t::test<35>() + { + // Make sure startsWith works + std::string string("anybody in there?"); + std::string substr("anybody"); + ensure("startsWith works.", LLStringUtil::startsWith(string, substr)); + } + + template<> template<> + void string_index_object_t::test<36>() + { + // Make sure startsWith correctly fails + std::string string("anybody in there?"); + std::string substr("there"); + ensure("startsWith fails.", !LLStringUtil::startsWith(string, substr)); + } + + template<> template<> + void string_index_object_t::test<37>() + { + // startsWith fails on empty strings + std::string value("anybody in there?"); + std::string empty; + ensure("empty string.", !LLStringUtil::startsWith(value, empty)); + ensure("empty substr.", !LLStringUtil::startsWith(empty, value)); + ensure("empty everything.", !LLStringUtil::startsWith(empty, empty)); + } + + template<> template<> + void string_index_object_t::test<38>() + { + // Make sure endsWith works correctly + std::string string("anybody in there?"); + std::string substr("there?"); + ensure("endsWith works.", LLStringUtil::endsWith(string, substr)); + } + + template<> template<> + void string_index_object_t::test<39>() + { + // Make sure endsWith correctly fails + std::string string("anybody in there?"); + std::string substr("anybody"); + ensure("endsWith fails.", !LLStringUtil::endsWith(string, substr)); + substr = "there"; + ensure("endsWith fails.", !LLStringUtil::endsWith(string, substr)); + substr = "ther?"; + ensure("endsWith fails.", !LLStringUtil::endsWith(string, substr)); + } + + template<> template<> + void string_index_object_t::test<40>() + { + // endsWith fails on empty strings + std::string value("anybody in there?"); + std::string empty; + ensure("empty string.", !LLStringUtil::endsWith(value, empty)); + ensure("empty substr.", !LLStringUtil::endsWith(empty, value)); + ensure("empty everything.", !LLStringUtil::endsWith(empty, empty)); + } +} -- cgit v1.3 From 2bfe1fc2bc355f455c018a575b97452f5ac8a729 Mon Sep 17 00:00:00 2001 From: Adam Moss Date: Thu, 8 Oct 2009 12:00:24 +0000 Subject: Extend automated string tests to cover the formerly-crashing "[]" substitution case (EXT-1282, DEV-41081) Also 'fix' string tests to match the new expected behaviour of LLStringUtil::format(). They must have been failing dreadfully before, but the legacy tut tests aren't run in a viewer-only build, so... --- indra/llcommon/tests/llstring_test.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/tests/llstring_test.cpp b/indra/llcommon/tests/llstring_test.cpp index 13894efad0..1f4603631a 100644 --- a/indra/llcommon/tests/llstring_test.cpp +++ b/indra/llcommon/tests/llstring_test.cpp @@ -554,6 +554,7 @@ namespace tut fmt_map["[KEYSHORTER]"] = "Am I not a long string?"; fmt_map["?"] = "?"; fmt_map["[DELETE]"] = ""; + fmt_map["[]"] = "[]"; // doesn't do a substitution, but shouldn't crash either for (LLStringUtil::format_map_t::const_iterator iter = fmt_map.begin(); iter != fmt_map.end(); ++iter) { @@ -562,7 +563,7 @@ namespace tut std::string s2 = (std::string)iter->second; subcount = LLStringUtil::format(s1, fmt_map); ensure_equals("LLStringUtil::format: Raw interpolation result", s1, s2); - if (s1 == "?") + if (s1 == "?" || s1 == "[]") // no interp expected { ensure_equals("LLStringUtil::format: Raw interpolation result count", 0, subcount); } @@ -580,7 +581,7 @@ namespace tut s = s1 + s1 + s1 + s1; subcount = LLStringUtil::format(s, fmt_map); ensure_equals("LLStringUtil::format: Rawx4 interpolation result", s, s2 + s2 + s2 + s2); - if (s1 == "?") + if (s1 == "?" || s1 == "[]") // no interp expected { ensure_equals("LLStringUtil::format: Rawx4 interpolation result count", 0, subcount); } -- cgit v1.3 From 1ee157028845048d931c0c7fdd1bcac53bda324e Mon Sep 17 00:00:00 2001 From: Adam Moss Date: Thu, 8 Oct 2009 13:52:53 +0000 Subject: DEV-41090 convert legacy llrand tut test into a llcommon integration test. --- indra/llcommon/CMakeLists.txt | 5 +- indra/llcommon/tests/llrand_test.cpp | 133 +++++++++++++++++++++++++++++++++++ indra/test/CMakeLists.txt | 1 - 3 files changed, 136 insertions(+), 3 deletions(-) create mode 100644 indra/llcommon/tests/llrand_test.cpp (limited to 'indra/llcommon') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index ad1eb1b310..25ec6c3668 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -243,8 +243,9 @@ set(test_libs llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES}) # Have to treat lllazy test as an integration test until this issue is resolved: # https://jira.lindenlab.com/jira/browse/DEV-29456 LL_ADD_INTEGRATION_TEST(lllazy lllazy.cpp "${test_libs}") -# Also puzzled as to why *CMake* barfs when this is a *unit* test. -LL_ADD_INTEGRATION_TEST(llstring llstring.cpp "${test_libs}") +# Also puzzled as to why *CMake* barfs when these are *unit* tests. +LL_ADD_INTEGRATION_TEST(llstring "llstring.cpp" "${test_libs}") +LL_ADD_INTEGRATION_TEST(llrand "llrand.cpp" "${test_libs}") # *TODO - reenable these once tcmalloc libs no longer break the build. #ADD_BUILD_TEST(llallocator llcommon) diff --git a/indra/llcommon/tests/llrand_test.cpp b/indra/llcommon/tests/llrand_test.cpp new file mode 100644 index 0000000000..e5100e51dc --- /dev/null +++ b/indra/llcommon/tests/llrand_test.cpp @@ -0,0 +1,133 @@ +/** + * @file llrandom_tut.cpp + * @author Phoenix + * @date 2007-01-25 + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-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 "../test/lltut.h" + +#include "../llrand.h" + + +namespace tut +{ + struct random + { + }; + + typedef test_group random_t; + typedef random_t::object random_object_t; + tut::random_t tut_random("random"); + + template<> template<> + void random_object_t::test<1>() + { + F32 number = 0.0f; + for(S32 ii = 0; ii < 100000; ++ii) + { + number = ll_frand(); + ensure("frand >= 0", (number >= 0.0f)); + ensure("frand < 1", (number < 1.0f)); + } + } + + template<> template<> + void random_object_t::test<2>() + { + F64 number = 0.0f; + for(S32 ii = 0; ii < 100000; ++ii) + { + number = ll_drand(); + ensure("drand >= 0", (number >= 0.0)); + ensure("drand < 1", (number < 1.0)); + } + } + + template<> template<> + void random_object_t::test<3>() + { + F32 number = 0.0f; + for(S32 ii = 0; ii < 100000; ++ii) + { + number = ll_frand(2.0f) - 1.0f; + ensure("frand >= 0", (number >= -1.0f)); + ensure("frand < 1", (number <= 1.0f)); + } + } + + template<> template<> + void random_object_t::test<4>() + { + F32 number = 0.0f; + for(S32 ii = 0; ii < 100000; ++ii) + { + number = ll_frand(-7.0); + ensure("drand <= 0", (number <= 0.0)); + ensure("drand > -7", (number > -7.0)); + } + } + + template<> template<> + void random_object_t::test<5>() + { + F64 number = 0.0f; + for(S32 ii = 0; ii < 100000; ++ii) + { + number = ll_drand(-2.0); + ensure("drand <= 0", (number <= 0.0)); + ensure("drand > -2", (number > -2.0)); + } + } + + template<> template<> + void random_object_t::test<6>() + { + S32 number = 0; + for(S32 ii = 0; ii < 100000; ++ii) + { + number = ll_rand(100); + ensure("rand >= 0", (number >= 0)); + ensure("rand < 100", (number < 100)); + } + } + + template<> template<> + void random_object_t::test<7>() + { + S32 number = 0; + for(S32 ii = 0; ii < 100000; ++ii) + { + number = ll_rand(-127); + ensure("rand <= 0", (number <= 0)); + ensure("rand > -127", (number > -127)); + } + } +} diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt index 277695758e..a842548980 100644 --- a/indra/test/CMakeLists.txt +++ b/indra/test/CMakeLists.txt @@ -52,7 +52,6 @@ set(test_SOURCE_FILES llnamevalue_tut.cpp llpermissions_tut.cpp llpipeutil.cpp - llrandom_tut.cpp llsaleinfo_tut.cpp llscriptresource_tut.cpp llsdmessagebuilder_tut.cpp -- cgit v1.3 From bb533f4d1123ff20d177ee4a3c7f69405da18bf5 Mon Sep 17 00:00:00 2001 From: Adam Moss Date: Thu, 8 Oct 2009 13:59:07 +0000 Subject: suppress win32 warning about strcpy. yuck. --- indra/llcommon/tests/llstring_test.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'indra/llcommon') diff --git a/indra/llcommon/tests/llstring_test.cpp b/indra/llcommon/tests/llstring_test.cpp index 1f4603631a..1d99214d69 100644 --- a/indra/llcommon/tests/llstring_test.cpp +++ b/indra/llcommon/tests/llstring_test.cpp @@ -32,6 +32,9 @@ * $/LicenseInfo$ */ +// win32 kludge-o-rama +#define _CRT_SECURE_NO_WARNINGS + #include "../test/lltut.h" #include "../llstring.h" -- cgit v1.3 From 9665d7a71bcd5cd79889b2b4908beaf66b76341d Mon Sep 17 00:00:00 2001 From: Adam Moss Date: Thu, 8 Oct 2009 14:14:13 +0000 Subject: DEV-41081 - better than using the msvc kludge for suppressing warnings about memcpy, don't actually use memcpy - use our own safe 'copy' method. also stripNonprintable() is probably a little faster now... --- indra/llcommon/llstring.h | 7 ++++--- indra/llcommon/tests/llstring_test.cpp | 3 --- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index d0def896cf..8f70726a9e 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -991,14 +991,15 @@ void LLStringUtilBase::stripNonprintable(std::basic_string& string) { return; } - char* c_string = new char[string.size() + 1]; + size_t src_size = string.size(); + char* c_string = new char[src_size + 1]; if(c_string == NULL) { return; } - strcpy(c_string, string.c_str()); /*Flawfinder: ignore*/ + copy(c_string, string.c_str(), src_size+1); char* write_head = &c_string[0]; - for (size_type i = 0; i < string.size(); i++) + for (size_type i = 0; i < src_size; i++) { char* read_head = &string[i]; write_head = &c_string[j]; diff --git a/indra/llcommon/tests/llstring_test.cpp b/indra/llcommon/tests/llstring_test.cpp index 1d99214d69..1f4603631a 100644 --- a/indra/llcommon/tests/llstring_test.cpp +++ b/indra/llcommon/tests/llstring_test.cpp @@ -32,9 +32,6 @@ * $/LicenseInfo$ */ -// win32 kludge-o-rama -#define _CRT_SECURE_NO_WARNINGS - #include "../test/lltut.h" #include "../llstring.h" -- cgit v1.3 From a1c239b4b6c13c11071964660adc907c61f90e30 Mon Sep 17 00:00:00 2001 From: Adam Moss Date: Thu, 8 Oct 2009 14:15:59 +0000 Subject: DEV-41080 expand the test case for LLStringUtil::containsNonprintable() --- indra/llcommon/tests/llstring_test.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'indra/llcommon') diff --git a/indra/llcommon/tests/llstring_test.cpp b/indra/llcommon/tests/llstring_test.cpp index 1f4603631a..6a2ebc61f5 100644 --- a/indra/llcommon/tests/llstring_test.cpp +++ b/indra/llcommon/tests/llstring_test.cpp @@ -223,6 +223,10 @@ namespace tut str_val = "\r\n\t\t"; LLStringUtil::stripNonprintable(str_val); ensure_equals("stripNonprintable resulting in empty string failed", str_val, ""); + + str_val = ""; + LLStringUtil::stripNonprintable(str_val); + ensure_equals("stripNonprintable of empty string resulting in empty string failed", str_val, ""); } template<> template<> -- cgit v1.3 From c017455439723c16502bd660b83a7a2abcaf297c Mon Sep 17 00:00:00 2001 From: Adam Moss Date: Thu, 8 Oct 2009 15:45:34 +0000 Subject: DEV-41080 - I found out why llmath can't be unit tested and fixed it, this checkin is some harmless preparation for that... --- indra/llcommon/CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 25ec6c3668..371786c44d 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -235,15 +235,13 @@ target_link_libraries(llcommon #add unit tests INCLUDE(LLAddBuildTest) SET(llcommon_TEST_SOURCE_FILES + # unit-testing llcommon is not possible right now as the test-harness *itself* depends upon llcommon, causing a circular dependency. Add your 'unit' tests as integration tests for now. ) LL_ADD_PROJECT_UNIT_TESTS(llcommon "${llcommon_TEST_SOURCE_FILES}") #set(TEST_DEBUG on) set(test_libs llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES}) -# Have to treat lllazy test as an integration test until this issue is resolved: -# https://jira.lindenlab.com/jira/browse/DEV-29456 LL_ADD_INTEGRATION_TEST(lllazy lllazy.cpp "${test_libs}") -# Also puzzled as to why *CMake* barfs when these are *unit* tests. LL_ADD_INTEGRATION_TEST(llstring "llstring.cpp" "${test_libs}") LL_ADD_INTEGRATION_TEST(llrand "llrand.cpp" "${test_libs}") -- cgit v1.3 From b73e71ebdf4366b11d3fd43ac80e2a3dc7f30cb2 Mon Sep 17 00:00:00 2001 From: Adam Moss Date: Mon, 12 Oct 2009 14:13:57 +0000 Subject: DEV-41174 more automated testing love * turn llnamevalue_tut into a llmessage unit test * turn llsdserialize_tut into a llcommon integration test * re-enable the (quite slow) llsdserialize test on win32 now that it doesn't have to run on every recompile * re-enable all llmessage unit tests on linux viewer builds --- indra/llcommon/CMakeLists.txt | 5 +- indra/llcommon/tests/llsdserialize_test.cpp | 1432 +++++++++++++++++++++++++++ indra/llmessage/CMakeLists.txt | 60 +- indra/llmessage/tests/llnamevalue_test.cpp | 412 ++++++++ indra/test/CMakeLists.txt | 2 - 5 files changed, 1875 insertions(+), 36 deletions(-) create mode 100644 indra/llcommon/tests/llsdserialize_test.cpp create mode 100644 indra/llmessage/tests/llnamevalue_test.cpp (limited to 'indra/llcommon') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 371786c44d..0861783df1 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -241,9 +241,10 @@ LL_ADD_PROJECT_UNIT_TESTS(llcommon "${llcommon_TEST_SOURCE_FILES}") #set(TEST_DEBUG on) set(test_libs llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES}) -LL_ADD_INTEGRATION_TEST(lllazy lllazy.cpp "${test_libs}") -LL_ADD_INTEGRATION_TEST(llstring "llstring.cpp" "${test_libs}") +LL_ADD_INTEGRATION_TEST(lllazy "lllazy.cpp" "${test_libs}") LL_ADD_INTEGRATION_TEST(llrand "llrand.cpp" "${test_libs}") +LL_ADD_INTEGRATION_TEST(llsdserialize "llsdserialize.cpp" "${test_libs}") +LL_ADD_INTEGRATION_TEST(llstring "llstring.cpp" "${test_libs}") # *TODO - reenable these once tcmalloc libs no longer break the build. #ADD_BUILD_TEST(llallocator llcommon) diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp new file mode 100644 index 0000000000..662b599c55 --- /dev/null +++ b/indra/llcommon/tests/llsdserialize_test.cpp @@ -0,0 +1,1432 @@ +/** + * @file llsdserialize_tut.cpp + * @date 2006-04 + * @brief LLSDSerialize 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$ + */ + +#if !LL_WINDOWS +#include +#endif + +#include "linden_common.h" +#include "../llsd.h" +#include "../llsdserialize.h" +#include "../llformat.h" + +#include "../test/lltut.h" + + +#if LL_WINDOWS +#include +typedef U32 uint32_t; +#endif + +namespace tut +{ + struct sd_xml_data + { + sd_xml_data() + { + mFormatter = new LLSDXMLFormatter; + } + LLSD mSD; + LLPointer mFormatter; + void xml_test(const char* name, const std::string& expected) + { + std::ostringstream ostr; + mFormatter->format(mSD, ostr); + ensure_equals(name, ostr.str(), expected); + } + }; + + typedef test_group sd_xml_test; + typedef sd_xml_test::object sd_xml_object; + tut::sd_xml_test sd_xml_stream("sd_xml_serialization"); + + template<> template<> + void sd_xml_object::test<1>() + { + // random atomic tests + std::string expected; + + expected = "\n"; + xml_test("undef", expected); + + mSD = 3463; + expected = "3463\n"; + xml_test("integer", expected); + + mSD = ""; + expected = "\n"; + xml_test("empty string", expected); + + mSD = "foobar"; + expected = "foobar\n"; + xml_test("string", expected); + + mSD = LLUUID::null; + expected = "\n"; + xml_test("null uuid", expected); + + mSD = LLUUID("c96f9b1e-f589-4100-9774-d98643ce0bed"); + expected = "c96f9b1e-f589-4100-9774-d98643ce0bed\n"; + xml_test("uuid", expected); + + mSD = LLURI("https://secondlife.com/login"); + expected = "https://secondlife.com/login\n"; + xml_test("uri", expected); + + mSD = LLDate("2006-04-24T16:11:33Z"); + expected = "2006-04-24T16:11:33Z\n"; + xml_test("date", expected); + + // *FIX: test binary + } + + template<> template<> + void sd_xml_object::test<2>() + { + // tests with boolean values. + std::string expected; + + mFormatter->boolalpha(true); + mSD = true; + expected = "true\n"; + xml_test("bool alpha true", expected); + mSD = false; + expected = "false\n"; + xml_test("bool alpha false", expected); + + mFormatter->boolalpha(false); + mSD = true; + expected = "1\n"; + xml_test("bool true", expected); + mSD = false; + expected = "0\n"; + xml_test("bool false", expected); + } + + + template<> template<> + void sd_xml_object::test<3>() + { + // tests with real values. + std::string expected; + + mFormatter->realFormat("%.2f"); + mSD = 1.0; + expected = "1.00\n"; + xml_test("real 1", expected); + + mSD = -34379.0438; + expected = "-34379.04\n"; + xml_test("real reduced precision", expected); + mFormatter->realFormat("%.4f"); + expected = "-34379.0438\n"; + xml_test("higher precision", expected); + + mFormatter->realFormat("%.0f"); + mSD = 0.0; + expected = "0\n"; + xml_test("no decimal 0", expected); + mSD = 3287.4387; + expected = "3287\n"; + xml_test("no decimal real number", expected); + } + + template<> template<> + void sd_xml_object::test<4>() + { + // tests with arrays + std::string expected; + + mSD = LLSD::emptyArray(); + expected = "\n"; + xml_test("empty array", expected); + + mSD.append(LLSD()); + expected = "\n"; + xml_test("1 element array", expected); + + mSD.append(1); + expected = "1\n"; + xml_test("2 element array", expected); + } + + template<> template<> + void sd_xml_object::test<5>() + { + // tests with arrays + std::string expected; + + mSD = LLSD::emptyMap(); + expected = "\n"; + xml_test("empty map", expected); + + mSD["foo"] = "bar"; + expected = "foobar\n"; + xml_test("1 element map", expected); + + mSD["baz"] = LLSD(); + expected = "bazfoobar\n"; + xml_test("2 element map", expected); + } + + + class TestLLSDSerializeData + { + public: + TestLLSDSerializeData(); + ~TestLLSDSerializeData(); + + void doRoundTripTests(const std::string&); + void checkRoundTrip(const std::string&, const LLSD& v); + + LLPointer mFormatter; + LLPointer mParser; + }; + + TestLLSDSerializeData::TestLLSDSerializeData() + { + } + + TestLLSDSerializeData::~TestLLSDSerializeData() + { + } + + void TestLLSDSerializeData::checkRoundTrip(const std::string& msg, const LLSD& v) + { + std::stringstream stream; + mFormatter->format(v, stream); + //llinfos << "checkRoundTrip: length " << stream.str().length() << llendl; + LLSD w; + mParser->reset(); // reset() call is needed since test code re-uses mParser + mParser->parse(stream, w, stream.str().size()); + + try + { + ensure_equals(msg.c_str(), w, v); + } + catch (...) + { + std::cerr << "the serialized string was:" << std::endl; + std::cerr << stream.str() << std::endl; + throw; + } + } + + static void fillmap(LLSD& root, U32 width, U32 depth) + { + if(depth == 0) + { + root["foo"] = "bar"; + return; + } + + for(U32 i = 0; i < width; ++i) + { + std::string key = llformat("child %d", i); + root[key] = LLSD::emptyMap(); + fillmap(root[key], width, depth - 1); + } + } + + void TestLLSDSerializeData::doRoundTripTests(const std::string& msg) + { + LLSD v; + checkRoundTrip(msg + " undefined", v); + + v = true; + checkRoundTrip(msg + " true bool", v); + + v = false; + checkRoundTrip(msg + " false bool", v); + + v = 1; + checkRoundTrip(msg + " positive int", v); + + v = 0; + checkRoundTrip(msg + " zero int", v); + + v = -1; + checkRoundTrip(msg + " negative int", v); + + v = 1234.5f; + checkRoundTrip(msg + " positive float", v); + + v = 0.0f; + checkRoundTrip(msg + " zero float", v); + + v = -1234.5f; + checkRoundTrip(msg + " negative float", v); + + // FIXME: need a NaN test + + v = LLUUID::null; + checkRoundTrip(msg + " null uuid", v); + + LLUUID newUUID; + newUUID.generate(); + v = newUUID; + checkRoundTrip(msg + " new uuid", v); + + v = ""; + checkRoundTrip(msg + " empty string", v); + + v = "some string"; + checkRoundTrip(msg + " non-empty string", v); + + v = +"Second Life is a 3-D virtual world entirely built and owned by its residents. " +"Since opening to the public in 2003, it has grown explosively and today is " +"inhabited by nearly 100,000 people from around the globe.\n" +"\n" +"From the moment you enter the World you'll discover a vast digital continent, " +"teeming with people, entertainment, experiences and opportunity. Once you've " +"explored a bit, perhaps you'll find a perfect parcel of land to build your " +"house or business.\n" +"\n" +"You'll also be surrounded by the Creations of your fellow residents. Because " +"residents retain the rights to their digital creations, they can buy, sell " +"and trade with other residents.\n" +"\n" +"The Marketplace currently supports millions of US dollars in monthly " +"transactions. This commerce is handled with the in-world currency, the Linden " +"dollar, which can be converted to US dollars at several thriving online " +"currency exchanges.\n" +"\n" +"Welcome to Second Life. We look forward to seeing you in-world!\n" + ; + checkRoundTrip(msg + " long string", v); + + static const U32 block_size = 0x000020; + for (U32 block = 0x000000; block <= 0x10ffff; block += block_size) + { + std::ostringstream out; + + for (U32 c = block; c < block + block_size; ++c) + { + if (c <= 0x000001f + && c != 0x000009 + && c != 0x00000a) + { + // see XML standard, sections 2.2 and 4.1 + continue; + } + if (0x00d800 <= c && c <= 0x00dfff) { continue; } + if (0x00fdd0 <= c && c <= 0x00fdef) { continue; } + if ((c & 0x00fffe) == 0x00fffe) { continue; } + // see Unicode standard, section 15.8 + + if (c <= 0x00007f) + { + out << (char)(c & 0x7f); + } + else if (c <= 0x0007ff) + { + out << (char)(0xc0 | ((c >> 6) & 0x1f)); + out << (char)(0x80 | ((c >> 0) & 0x3f)); + } + else if (c <= 0x00ffff) + { + out << (char)(0xe0 | ((c >> 12) & 0x0f)); + out << (char)(0x80 | ((c >> 6) & 0x3f)); + out << (char)(0x80 | ((c >> 0) & 0x3f)); + } + else + { + out << (char)(0xf0 | ((c >> 18) & 0x07)); + out << (char)(0x80 | ((c >> 12) & 0x3f)); + out << (char)(0x80 | ((c >> 6) & 0x3f)); + out << (char)(0x80 | ((c >> 0) & 0x3f)); + } + } + + v = out.str(); + + std::ostringstream blockmsg; + blockmsg << msg << " unicode string block 0x" << std::hex << block; + checkRoundTrip(blockmsg.str(), v); + } + + LLDate epoch; + v = epoch; + checkRoundTrip(msg + " epoch date", v); + + LLDate aDay("2002-12-07T05:07:15.00Z"); + v = aDay; + checkRoundTrip(msg + " date", v); + + LLURI path("http://slurl.com/secondlife/Ambleside/57/104/26/"); + v = path; + checkRoundTrip(msg + " url", v); + + const char source[] = "it must be a blue moon again"; + std::vector data; + copy(&source[0], &source[sizeof(source)], back_inserter(data)); + + v = data; + checkRoundTrip(msg + " binary", v); + + v = LLSD::emptyMap(); + checkRoundTrip(msg + " empty map", v); + + v = LLSD::emptyMap(); + v["name"] = "luke"; //v.insert("name", "luke"); + v["age"] = 3; //v.insert("age", 3); + checkRoundTrip(msg + " map", v); + + v.clear(); + v["a"]["1"] = true; + v["b"]["0"] = false; + checkRoundTrip(msg + " nested maps", v); + + v = LLSD::emptyArray(); + checkRoundTrip(msg + " empty array", v); + + v = LLSD::emptyArray(); + v.append("ali"); + v.append(28); + checkRoundTrip(msg + " array", v); + + v.clear(); + v[0][0] = true; + v[1][0] = false; + checkRoundTrip(msg + " nested arrays", v); + + v = LLSD::emptyMap(); + fillmap(v, 10, 6); // 10^6 maps + checkRoundTrip(msg + " many nested maps", v); + } + + typedef tut::test_group TestLLSDSerialzeGroup; + typedef TestLLSDSerialzeGroup::object TestLLSDSerializeObject; + TestLLSDSerialzeGroup gTestLLSDSerializeGroup("llsd serialization"); + + template<> template<> + void TestLLSDSerializeObject::test<1>() + { + mFormatter = new LLSDNotationFormatter(); + mParser = new LLSDNotationParser(); + doRoundTripTests("notation serialization"); + } + + template<> template<> + void TestLLSDSerializeObject::test<2>() + { + mFormatter = new LLSDXMLFormatter(); + mParser = new LLSDXMLParser(); + doRoundTripTests("xml serialization"); + } + + template<> template<> + void TestLLSDSerializeObject::test<3>() + { + mFormatter = new LLSDBinaryFormatter(); + mParser = new LLSDBinaryParser(); + doRoundTripTests("binary serialization"); + } + + + /** + * @class TestLLSDParsing + * @brief Base class for of a parse tester. + */ + template + class TestLLSDParsing + { + public: + TestLLSDParsing() + { + mParser = new parser_t; + } + + void ensureParse( + const std::string& msg, + const std::string& in, + const LLSD& expected_value, + S32 expected_count) + { + std::stringstream input; + input.str(in); + + LLSD parsed_result; + mParser->reset(); // reset() call is needed since test code re-uses mParser + S32 parsed_count = mParser->parse(input, parsed_result, in.size()); + ensure_equals(msg.c_str(), parsed_result, expected_value); + + // This count check is really only useful for expected + // parse failures, since the ensures equal will already + // require eqality. + std::string count_msg(msg); + count_msg += " (count)"; + ensure_equals(count_msg, parsed_count, expected_count); + } + + LLPointer mParser; + }; + + + /** + * @class TestLLSDXMLParsing + * @brief Concrete instance of a parse tester. + */ + class TestLLSDXMLParsing : public TestLLSDParsing + { + public: + TestLLSDXMLParsing() {} + }; + + typedef tut::test_group TestLLSDXMLParsingGroup; + typedef TestLLSDXMLParsingGroup::object TestLLSDXMLParsingObject; + TestLLSDXMLParsingGroup gTestLLSDXMLParsingGroup("llsd XML parsing"); + + template<> template<> + void TestLLSDXMLParsingObject::test<1>() + { + // test handling of xml not recognized as llsd results in an + // LLSD Undefined + ensureParse( + "malformed xml", + "ha ha", + LLSD(), + LLSDParser::PARSE_FAILURE); + ensureParse( + "not llsd", + "

ha ha

", + LLSD(), + LLSDParser::PARSE_FAILURE); + ensureParse( + "value without llsd", + "ha ha", + LLSD(), + LLSDParser::PARSE_FAILURE); + ensureParse( + "key without llsd", + "ha ha", + LLSD(), + LLSDParser::PARSE_FAILURE); + } + + + template<> template<> + void TestLLSDXMLParsingObject::test<2>() + { + // test handling of unrecognized or unparseable llsd values + LLSD v; + v["amy"] = 23; + v["bob"] = LLSD(); + v["cam"] = 1.23; + + ensureParse( + "unknown data type", + "" + "amy23" + "bob99999999999999999" + "cam1.23" + "", + v, + v.size() + 1); + } + + template<> template<> + void TestLLSDXMLParsingObject::test<3>() + { + // test handling of nested bad data + + LLSD v; + v["amy"] = 23; + v["cam"] = 1.23; + + ensureParse( + "map with html", + "" + "amy23" + "ha ha" + "cam1.23" + "", + v, + v.size() + 1); + + v.clear(); + v["amy"] = 23; + v["cam"] = 1.23; + ensureParse( + "map with value for key", + "" + "amy23" + "ha ha" + "cam1.23" + "", + v, + v.size() + 1); + + v.clear(); + v["amy"] = 23; + v["bob"] = LLSD::emptyMap(); + v["cam"] = 1.23; + ensureParse( + "map with map of html", + "" + "amy23" + "bob" + "" + "ha ha" + "" + "cam1.23" + "", + v, + v.size() + 1); + + v.clear(); + v[0] = 23; + v[1] = LLSD(); + v[2] = 1.23; + + ensureParse( + "array value of html", + "" + "23" + "ha ha" + "1.23" + "", + v, + v.size() + 1); + + v.clear(); + v[0] = 23; + v[1] = LLSD::emptyMap(); + v[2] = 1.23; + ensureParse( + "array with map of html", + "" + "23" + "" + "ha ha" + "" + "1.23" + "", + v, + v.size() + 1); + } + + /* + TODO: + test XML parsing + binary with unrecognized encoding + nested LLSD tags + multiple values inside an LLSD + */ + + + /** + * @class TestLLSDNotationParsing + * @brief Concrete instance of a parse tester. + */ + class TestLLSDNotationParsing : public TestLLSDParsing + { + public: + TestLLSDNotationParsing() {} + }; + + typedef tut::test_group TestLLSDNotationParsingGroup; + typedef TestLLSDNotationParsingGroup::object TestLLSDNotationParsingObject; + TestLLSDNotationParsingGroup gTestLLSDNotationParsingGroup( + "llsd notation parsing"); + + template<> template<> + void TestLLSDNotationParsingObject::test<1>() + { + // test handling of xml not recognized as llsd results in an + // LLSD Undefined + ensureParse( + "malformed notation map", + "{'ha ha'", + LLSD(), + LLSDParser::PARSE_FAILURE); + ensureParse( + "malformed notation array", + "['ha ha'", + LLSD(), + LLSDParser::PARSE_FAILURE); + ensureParse( + "malformed notation string", + "'ha ha", + LLSD(), + LLSDParser::PARSE_FAILURE); + ensureParse( + "bad notation noise", + "g48ejlnfr", + LLSD(), + LLSDParser::PARSE_FAILURE); + } + + template<> template<> + void TestLLSDNotationParsingObject::test<2>() + { + ensureParse("valid undef", "!", LLSD(), 1); + } + + template<> template<> + void TestLLSDNotationParsingObject::test<3>() + { + LLSD val = false; + ensureParse("valid boolean false 0", "false", val, 1); + ensureParse("valid boolean false 1", "f", val, 1); + ensureParse("valid boolean false 2", "0", val, 1); + ensureParse("valid boolean false 3", "F", val, 1); + ensureParse("valid boolean false 4", "FALSE", val, 1); + val = true; + ensureParse("valid boolean true 0", "true", val, 1); + ensureParse("valid boolean true 1", "t", val, 1); + ensureParse("valid boolean true 2", "1", val, 1); + ensureParse("valid boolean true 3", "T", val, 1); + ensureParse("valid boolean true 4", "TRUE", val, 1); + + val.clear(); + ensureParse("invalid true", "TR", val, LLSDParser::PARSE_FAILURE); + ensureParse("invalid false", "FAL", val, LLSDParser::PARSE_FAILURE); + } + + template<> template<> + void TestLLSDNotationParsingObject::test<4>() + { + LLSD val = 123; + ensureParse("valid integer", "i123", val, 1); + val.clear(); + ensureParse("invalid integer", "421", val, LLSDParser::PARSE_FAILURE); + } + + template<> template<> + void TestLLSDNotationParsingObject::test<5>() + { + LLSD val = 456.7; + ensureParse("valid real", "r456.7", val, 1); + val.clear(); + ensureParse("invalid real", "456.7", val, LLSDParser::PARSE_FAILURE); + } + + template<> template<> + void TestLLSDNotationParsingObject::test<6>() + { + LLUUID id; + LLSD val = id; + ensureParse( + "unparseable uuid", + "u123", + LLSD(), + LLSDParser::PARSE_FAILURE); + id.generate(); + val = id; + std::string uuid_str("u"); + uuid_str += id.asString(); + ensureParse("valid uuid", uuid_str.c_str(), val, 1); + } + + template<> template<> + void TestLLSDNotationParsingObject::test<7>() + { + LLSD val = std::string("foolish"); + ensureParse("valid string 1", "\"foolish\"", val, 1); + val = std::string("g'day"); + ensureParse("valid string 2", "\"g'day\"", val, 1); + val = std::string("have a \"nice\" day"); + ensureParse("valid string 3", "'have a \"nice\" day'", val, 1); + val = std::string("whatever"); + ensureParse("valid string 4", "s(8)\"whatever\"", val, 1); + } + + template<> template<> + void TestLLSDNotationParsingObject::test<8>() + { + ensureParse( + "invalid string 1", + "s(7)\"whatever\"", + LLSD(), + LLSDParser::PARSE_FAILURE); + ensureParse( + "invalid string 2", + "s(9)\"whatever\"", + LLSD(), + LLSDParser::PARSE_FAILURE); + } + + template<> template<> + void TestLLSDNotationParsingObject::test<9>() + { + LLSD val = LLURI("http://www.google.com"); + ensureParse("valid uri", "l\"http://www.google.com\"", val, 1); + } + + template<> template<> + void TestLLSDNotationParsingObject::test<10>() + { + LLSD val = LLDate("2007-12-28T09:22:53.10Z"); + ensureParse("valid date", "d\"2007-12-28T09:22:53.10Z\"", val, 1); + } + + template<> template<> + void TestLLSDNotationParsingObject::test<11>() + { + std::vector vec; + vec.push_back((U8)'a'); vec.push_back((U8)'b'); vec.push_back((U8)'c'); + vec.push_back((U8)'3'); vec.push_back((U8)'2'); vec.push_back((U8)'1'); + LLSD val = vec; + ensureParse("valid binary b64", "b64\"YWJjMzIx\"", val, 1); + ensureParse("valid bainry b16", "b16\"616263333231\"", val, 1); + ensureParse("valid bainry raw", "b(6)\"abc321\"", val, 1); + } + + template<> template<> + void TestLLSDNotationParsingObject::test<12>() + { + ensureParse( + "invalid -- binary length specified too long", + "b(7)\"abc321\"", + LLSD(), + LLSDParser::PARSE_FAILURE); + ensureParse( + "invalid -- binary length specified way too long", + "b(1000000)\"abc321\"", + LLSD(), + LLSDParser::PARSE_FAILURE); + } + + template<> template<> + void TestLLSDNotationParsingObject::test<13>() + { + LLSD val; + val["amy"] = 23; + val["bob"] = LLSD(); + val["cam"] = 1.23; + ensureParse("simple map", "{'amy':i23,'bob':!,'cam':r1.23}", val, 4); + + val["bob"] = LLSD::emptyMap(); + val["bob"]["vehicle"] = std::string("bicycle"); + ensureParse( + "nested map", + "{'amy':i23,'bob':{'vehicle':'bicycle'},'cam':r1.23}", + val, + 5); + } + + template<> template<> + void TestLLSDNotationParsingObject::test<14>() + { + LLSD val; + val.append(23); + val.append(LLSD()); + val.append(1.23); + ensureParse("simple array", "[i23,!,r1.23]", val, 4); + val[1] = LLSD::emptyArray(); + val[1].append("bicycle"); + ensureParse("nested array", "[i23,['bicycle'],r1.23]", val, 5); + } + + template<> template<> + void TestLLSDNotationParsingObject::test<15>() + { + LLSD val; + val["amy"] = 23; + val["bob"]["dogs"] = LLSD::emptyArray(); + val["bob"]["dogs"].append(LLSD::emptyMap()); + val["bob"]["dogs"][0]["name"] = std::string("groove"); + val["bob"]["dogs"][0]["breed"] = std::string("samoyed"); + val["bob"]["dogs"].append(LLSD::emptyMap()); + val["bob"]["dogs"][1]["name"] = std::string("greyley"); + val["bob"]["dogs"][1]["breed"] = std::string("chow/husky"); + val["cam"] = 1.23; + ensureParse( + "nested notation", + "{'amy':i23," + " 'bob':{'dogs':[" + "{'name':'groove', 'breed':'samoyed'}," + "{'name':'greyley', 'breed':'chow/husky'}]}," + " 'cam':r1.23}", + val, + 11); + } + + template<> template<> + void TestLLSDNotationParsingObject::test<16>() + { + // text to make sure that incorrect sizes bail because + std::string bad_str("s(5)\"hi\""); + ensureParse( + "size longer than bytes left", + bad_str, + LLSD(), + LLSDParser::PARSE_FAILURE); + } + + template<> template<> + void TestLLSDNotationParsingObject::test<17>() + { + // text to make sure that incorrect sizes bail because + std::string bad_bin("b(5)\"hi\""); + ensureParse( + "size longer than bytes left", + bad_bin, + LLSD(), + LLSDParser::PARSE_FAILURE); + } + + /** + * @class TestLLSDBinaryParsing + * @brief Concrete instance of a parse tester. + */ + class TestLLSDBinaryParsing : public TestLLSDParsing + { + public: + TestLLSDBinaryParsing() {} + }; + + typedef tut::test_group TestLLSDBinaryParsingGroup; + typedef TestLLSDBinaryParsingGroup::object TestLLSDBinaryParsingObject; + TestLLSDBinaryParsingGroup gTestLLSDBinaryParsingGroup( + "llsd binary parsing"); + + template<> template<> + void TestLLSDBinaryParsingObject::test<1>() + { + std::vector vec; + vec.resize(6); + vec[0] = 'a'; vec[1] = 'b'; vec[2] = 'c'; + vec[3] = '3'; vec[4] = '2'; vec[5] = '1'; + std::string string_expected((char*)&vec[0], vec.size()); + LLSD value = string_expected; + + vec.resize(11); + vec[0] = 's'; // for string + vec[5] = 'a'; vec[6] = 'b'; vec[7] = 'c'; + vec[8] = '3'; vec[9] = '2'; vec[10] = '1'; + + uint32_t size = htonl(6); + memcpy(&vec[1], &size, sizeof(uint32_t)); + std::string str_good((char*)&vec[0], vec.size()); + ensureParse("correct string parse", str_good, value, 1); + + size = htonl(7); + memcpy(&vec[1], &size, sizeof(uint32_t)); + std::string str_bad_1((char*)&vec[0], vec.size()); + ensureParse( + "incorrect size string parse", + str_bad_1, + LLSD(), + LLSDParser::PARSE_FAILURE); + + size = htonl(100000); + memcpy(&vec[1], &size, sizeof(uint32_t)); + std::string str_bad_2((char*)&vec[0], vec.size()); + ensureParse( + "incorrect size string parse", + str_bad_2, + LLSD(), + LLSDParser::PARSE_FAILURE); + } + + template<> template<> + void TestLLSDBinaryParsingObject::test<2>() + { + std::vector vec; + vec.resize(6); + vec[0] = 'a'; vec[1] = 'b'; vec[2] = 'c'; + vec[3] = '3'; vec[4] = '2'; vec[5] = '1'; + LLSD value = vec; + + vec.resize(11); + vec[0] = 'b'; // for binary + vec[5] = 'a'; vec[6] = 'b'; vec[7] = 'c'; + vec[8] = '3'; vec[9] = '2'; vec[10] = '1'; + + uint32_t size = htonl(6); + memcpy(&vec[1], &size, sizeof(uint32_t)); + std::string str_good((char*)&vec[0], vec.size()); + ensureParse("correct binary parse", str_good, value, 1); + + size = htonl(7); + memcpy(&vec[1], &size, sizeof(uint32_t)); + std::string str_bad_1((char*)&vec[0], vec.size()); + ensureParse( + "incorrect size binary parse 1", + str_bad_1, + LLSD(), + LLSDParser::PARSE_FAILURE); + + size = htonl(100000); + memcpy(&vec[1], &size, sizeof(uint32_t)); + std::string str_bad_2((char*)&vec[0], vec.size()); + ensureParse( + "incorrect size binary parse 2", + str_bad_2, + LLSD(), + LLSDParser::PARSE_FAILURE); + } + + template<> template<> + void TestLLSDBinaryParsingObject::test<3>() + { + // test handling of xml not recognized as llsd results in an + // LLSD Undefined + ensureParse( + "malformed binary map", + "{'ha ha'", + LLSD(), + LLSDParser::PARSE_FAILURE); + ensureParse( + "malformed binary array", + "['ha ha'", + LLSD(), + LLSDParser::PARSE_FAILURE); + ensureParse( + "malformed binary string", + "'ha ha", + LLSD(), + LLSDParser::PARSE_FAILURE); + ensureParse( + "bad noise", + "g48ejlnfr", + LLSD(), + LLSDParser::PARSE_FAILURE); + } + template<> template<> + void TestLLSDBinaryParsingObject::test<4>() + { + ensureParse("valid undef", "!", LLSD(), 1); + } + + template<> template<> + void TestLLSDBinaryParsingObject::test<5>() + { + LLSD val = false; + ensureParse("valid boolean false 2", "0", val, 1); + val = true; + ensureParse("valid boolean true 2", "1", val, 1); + + val.clear(); + ensureParse("invalid true", "t", val, LLSDParser::PARSE_FAILURE); + ensureParse("invalid false", "f", val, LLSDParser::PARSE_FAILURE); + } + + template<> template<> + void TestLLSDBinaryParsingObject::test<6>() + { + std::vector vec; + vec.push_back('{'); + vec.resize(vec.size() + 4); + uint32_t size = htonl(1); + memcpy(&vec[1], &size, sizeof(uint32_t)); + vec.push_back('k'); + int key_size_loc = vec.size(); + size = htonl(1); // 1 too short + vec.resize(vec.size() + 4); + memcpy(&vec[key_size_loc], &size, sizeof(uint32_t)); + vec.push_back('a'); vec.push_back('m'); vec.push_back('y'); + vec.push_back('i'); + int integer_loc = vec.size(); + vec.resize(vec.size() + 4); + uint32_t val_int = htonl(23); + memcpy(&vec[integer_loc], &val_int, sizeof(uint32_t)); + std::string str_bad_1((char*)&vec[0], vec.size()); + ensureParse( + "invalid key size", + str_bad_1, + LLSD(), + LLSDParser::PARSE_FAILURE); + + // check with correct size, but unterminated map (missing '}') + size = htonl(3); // correct size + memcpy(&vec[key_size_loc], &size, sizeof(uint32_t)); + std::string str_bad_2((char*)&vec[0], vec.size()); + ensureParse( + "valid key size, unterminated map", + str_bad_2, + LLSD(), + LLSDParser::PARSE_FAILURE); + + // check w/ correct size and correct map termination + LLSD val; + val["amy"] = 23; + vec.push_back('}'); + std::string str_good((char*)&vec[0], vec.size()); + ensureParse( + "valid map", + str_good, + val, + 2); + + // check w/ incorrect sizes and correct map termination + size = htonl(0); // 1 too few (for the map entry) + memcpy(&vec[1], &size, sizeof(uint32_t)); + std::string str_bad_3((char*)&vec[0], vec.size()); + ensureParse( + "invalid map too long", + str_bad_3, + LLSD(), + LLSDParser::PARSE_FAILURE); + + size = htonl(2); // 1 too many + memcpy(&vec[1], &size, sizeof(uint32_t)); + std::string str_bad_4((char*)&vec[0], vec.size()); + ensureParse( + "invalid map too short", + str_bad_4, + LLSD(), + LLSDParser::PARSE_FAILURE); + } + + template<> template<> + void TestLLSDBinaryParsingObject::test<7>() + { + std::vector vec; + vec.push_back('['); + vec.resize(vec.size() + 4); + uint32_t size = htonl(1); // 1 too short + memcpy(&vec[1], &size, sizeof(uint32_t)); + vec.push_back('"'); vec.push_back('a'); vec.push_back('m'); + vec.push_back('y'); vec.push_back('"'); vec.push_back('i'); + int integer_loc = vec.size(); + vec.resize(vec.size() + 4); + uint32_t val_int = htonl(23); + memcpy(&vec[integer_loc], &val_int, sizeof(uint32_t)); + + std::string str_bad_1((char*)&vec[0], vec.size()); + ensureParse( + "invalid array size", + str_bad_1, + LLSD(), + LLSDParser::PARSE_FAILURE); + + // check with correct size, but unterminated map (missing ']') + size = htonl(2); // correct size + memcpy(&vec[1], &size, sizeof(uint32_t)); + std::string str_bad_2((char*)&vec[0], vec.size()); + ensureParse( + "unterminated array", + str_bad_2, + LLSD(), + LLSDParser::PARSE_FAILURE); + + // check w/ correct size and correct map termination + LLSD val; + val.append("amy"); + val.append(23); + vec.push_back(']'); + std::string str_good((char*)&vec[0], vec.size()); + ensureParse( + "valid array", + str_good, + val, + 3); + + // check with too many elements + size = htonl(3); // 1 too long + memcpy(&vec[1], &size, sizeof(uint32_t)); + std::string str_bad_3((char*)&vec[0], vec.size()); + ensureParse( + "array too short", + str_bad_3, + LLSD(), + LLSDParser::PARSE_FAILURE); + } + + template<> template<> + void TestLLSDBinaryParsingObject::test<8>() + { + std::vector vec; + vec.push_back('{'); + vec.resize(vec.size() + 4); + memset(&vec[1], 0, 4); + vec.push_back('}'); + std::string str_good((char*)&vec[0], vec.size()); + LLSD val = LLSD::emptyMap(); + ensureParse( + "empty map", + str_good, + val, + 1); + } + + template<> template<> + void TestLLSDBinaryParsingObject::test<9>() + { + std::vector vec; + vec.push_back('['); + vec.resize(vec.size() + 4); + memset(&vec[1], 0, 4); + vec.push_back(']'); + std::string str_good((char*)&vec[0], vec.size()); + LLSD val = LLSD::emptyArray(); + ensureParse( + "empty array", + str_good, + val, + 1); + } + + template<> template<> + void TestLLSDBinaryParsingObject::test<10>() + { + std::vector vec; + vec.push_back('l'); + vec.resize(vec.size() + 4); + uint32_t size = htonl(14); // 1 too long + memcpy(&vec[1], &size, sizeof(uint32_t)); + vec.push_back('h'); vec.push_back('t'); vec.push_back('t'); + vec.push_back('p'); vec.push_back(':'); vec.push_back('/'); + vec.push_back('/'); vec.push_back('s'); vec.push_back('l'); + vec.push_back('.'); vec.push_back('c'); vec.push_back('o'); + vec.push_back('m'); + std::string str_bad((char*)&vec[0], vec.size()); + ensureParse( + "invalid uri length size", + str_bad, + LLSD(), + LLSDParser::PARSE_FAILURE); + + LLSD val; + val = LLURI("http://sl.com"); + size = htonl(13); // correct length + memcpy(&vec[1], &size, sizeof(uint32_t)); + std::string str_good((char*)&vec[0], vec.size()); + ensureParse( + "valid key size", + str_good, + val, + 1); + } + +/* + template<> template<> + void TestLLSDBinaryParsingObject::test<11>() + { + } +*/ + + /** + * @class TestLLSDCrossCompatible + * @brief Miscellaneous serialization and parsing tests + */ + class TestLLSDCrossCompatible + { + public: + TestLLSDCrossCompatible() {} + + void ensureBinaryAndNotation( + const std::string& msg, + const LLSD& input) + { + // to binary, and back again + std::stringstream str1; + S32 count1 = LLSDSerialize::toBinary(input, str1); + LLSD actual_value_bin; + S32 count2 = LLSDSerialize::fromBinary( + actual_value_bin, + str1, + LLSDSerialize::SIZE_UNLIMITED); + ensure_equals( + "ensureBinaryAndNotation binary count", + count2, + count1); + + // to notation and back again + std::stringstream str2; + S32 count3 = LLSDSerialize::toNotation(actual_value_bin, str2); + ensure_equals( + "ensureBinaryAndNotation notation count1", + count3, + count2); + LLSD actual_value_notation; + S32 count4 = LLSDSerialize::fromNotation( + actual_value_notation, + str2, + LLSDSerialize::SIZE_UNLIMITED); + ensure_equals( + "ensureBinaryAndNotation notation count2", + count4, + count3); + ensure_equals( + (msg + " (binaryandnotation)").c_str(), + actual_value_notation, + input); + } + + void ensureBinaryAndXML( + const std::string& msg, + const LLSD& input) + { + // to binary, and back again + std::stringstream str1; + S32 count1 = LLSDSerialize::toBinary(input, str1); + LLSD actual_value_bin; + S32 count2 = LLSDSerialize::fromBinary( + actual_value_bin, + str1, + LLSDSerialize::SIZE_UNLIMITED); + ensure_equals( + "ensureBinaryAndXML binary count", + count2, + count1); + + // to xml and back again + std::stringstream str2; + S32 count3 = LLSDSerialize::toXML(actual_value_bin, str2); + ensure_equals( + "ensureBinaryAndXML xml count1", + count3, + count2); + LLSD actual_value_xml; + S32 count4 = LLSDSerialize::fromXML(actual_value_xml, str2); + ensure_equals( + "ensureBinaryAndXML xml count2", + count4, + count3); + ensure_equals((msg + " (binaryandxml)").c_str(), actual_value_xml, input); + } + }; + + typedef tut::test_group TestLLSDCompatibleGroup; + typedef TestLLSDCompatibleGroup::object TestLLSDCompatibleObject; + TestLLSDCompatibleGroup gTestLLSDCompatibleGroup( + "llsd serialize compatible"); + + template<> template<> + void TestLLSDCompatibleObject::test<1>() + { + LLSD test; + ensureBinaryAndNotation("undef", test); + ensureBinaryAndXML("undef", test); + test = true; + ensureBinaryAndNotation("boolean true", test); + ensureBinaryAndXML("boolean true", test); + test = false; + ensureBinaryAndNotation("boolean false", test); + ensureBinaryAndXML("boolean false", test); + test = 0; + ensureBinaryAndNotation("integer zero", test); + ensureBinaryAndXML("integer zero", test); + test = 1; + ensureBinaryAndNotation("integer positive", test); + ensureBinaryAndXML("integer positive", test); + test = -234567; + ensureBinaryAndNotation("integer negative", test); + ensureBinaryAndXML("integer negative", test); + test = 0.0; + ensureBinaryAndNotation("real zero", test); + ensureBinaryAndXML("real zero", test); + test = 1.0; + ensureBinaryAndNotation("real positive", test); + ensureBinaryAndXML("real positive", test); + test = -1.0; + ensureBinaryAndNotation("real negative", test); + ensureBinaryAndXML("real negative", test); + } + + template<> template<> + void TestLLSDCompatibleObject::test<2>() + { + LLSD test; + test = "foobar"; + ensureBinaryAndNotation("string", test); + ensureBinaryAndXML("string", test); + } + + template<> template<> + void TestLLSDCompatibleObject::test<3>() + { + LLSD test; + LLUUID id; + id.generate(); + test = id; + ensureBinaryAndNotation("uuid", test); + ensureBinaryAndXML("uuid", test); + } + + template<> template<> + void TestLLSDCompatibleObject::test<4>() + { + LLSD test; + test = LLDate(12345.0); + ensureBinaryAndNotation("date", test); + ensureBinaryAndXML("date", test); + } + + template<> template<> + void TestLLSDCompatibleObject::test<5>() + { + LLSD test; + test = LLURI("http://www.secondlife.com/"); + ensureBinaryAndNotation("uri", test); + ensureBinaryAndXML("uri", test); + } + + template<> template<> + void TestLLSDCompatibleObject::test<6>() + { + LLSD test; + typedef std::vector buf_t; + buf_t val; + for(int ii = 0; ii < 100; ++ii) + { + srand(ii); /* Flawfinder: ignore */ + S32 size = rand() % 100 + 10; + std::generate_n( + std::back_insert_iterator(val), + size, + rand); + } + test = val; + ensureBinaryAndNotation("binary", test); + ensureBinaryAndXML("binary", test); + } + + template<> template<> + void TestLLSDCompatibleObject::test<7>() + { + LLSD test; + test = LLSD::emptyArray(); + test.append(1); + test.append("hello"); + ensureBinaryAndNotation("array", test); + ensureBinaryAndXML("array", test); + } + + template<> template<> + void TestLLSDCompatibleObject::test<8>() + { + LLSD test; + test = LLSD::emptyArray(); + test["foo"] = "bar"; + test["baz"] = 100; + ensureBinaryAndNotation("map", test); + ensureBinaryAndXML("map", test); + } +} + diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index 1e8b5517e4..31ea747f52 100644 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -205,39 +205,35 @@ list(APPEND llmessage_SOURCE_FILES ${llmessage_HEADER_FILES}) add_library (llmessage ${llmessage_SOURCE_FILES}) target_link_libraries( - llmessage - ${CURL_LIBRARIES} - ${CARES_LIBRARIES} - ${OPENSSL_LIBRARIES} - ${CRYPTO_LIBRARIES} - ${XMLRPCEPI_LIBRARIES} - ) + llmessage + ${CURL_LIBRARIES} + ${CARES_LIBRARIES} + ${OPENSSL_LIBRARIES} + ${CRYPTO_LIBRARIES} + ${XMLRPCEPI_LIBRARIES} + ) -IF (NOT LINUX AND VIEWER) - # When building the viewer the tests links against the shared objects. - # These can not be found when we try to run the tests, so we had to disable them, for the viewer build. - # TODO: Can someone with viewer knowledge figure out how to make these find the correct so. - SET(llmessage_TEST_SOURCE_FILES - # llhttpclientadapter.cpp - lltrustedmessageservice.cpp - lltemplatemessagedispatcher.cpp - ) +SET(llmessage_TEST_SOURCE_FILES + # llhttpclientadapter.cpp + llnamevalue.cpp + lltrustedmessageservice.cpp + lltemplatemessagedispatcher.cpp + ) # set(TEST_DEBUG on) - set(test_libs - ${LLMESSAGE_LIBRARIES} - ${WINDOWS_LIBRARIES} - ${LLVFS_LIBRARIES} - ${LLMATH_LIBRARIES} - ${LLCOMMON_LIBRARIES} - ) +set(test_libs + ${LLMESSAGE_LIBRARIES} + ${WINDOWS_LIBRARIES} + ${LLVFS_LIBRARIES} + ${LLMATH_LIBRARIES} + ${LLCOMMON_LIBRARIES} + ) - LL_ADD_INTEGRATION_TEST( - llsdmessage - "llsdmessage.cpp" - "${test_libs}" - ${PYTHON_EXECUTABLE} - "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llsdmessage_peer.py" - ) +LL_ADD_INTEGRATION_TEST( + llsdmessage + "llsdmessage.cpp" + "${test_libs}" + ${PYTHON_EXECUTABLE} + "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llsdmessage_peer.py" + ) - LL_ADD_PROJECT_UNIT_TESTS(llmessage "${llmessage_TEST_SOURCE_FILES}") -ENDIF (NOT LINUX AND VIEWER) +LL_ADD_PROJECT_UNIT_TESTS(llmessage "${llmessage_TEST_SOURCE_FILES}") diff --git a/indra/llmessage/tests/llnamevalue_test.cpp b/indra/llmessage/tests/llnamevalue_test.cpp new file mode 100644 index 0000000000..3146e7f979 --- /dev/null +++ b/indra/llmessage/tests/llnamevalue_test.cpp @@ -0,0 +1,412 @@ +/** + * @file llnamevalue_tut.cpp + * @author Adroit + * @date 2007-02 + * @brief LLNameValue unit test + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-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 "llsdserialize.h" + +#include "../llnamevalue.h" + +#include "../test/lltut.h" + + +#if LL_WINDOWS +// disable unreachable code warnings +#pragma warning(disable: 4702) +#endif + +namespace tut +{ + struct namevalue_test + { + namevalue_test() + { + } + }; + typedef test_group namevalue_t; + typedef namevalue_t::object namevalue_object_t; + tut::namevalue_t tut_namevalue("namevalue_test"); + + + template<> template<> + void namevalue_object_t::test<1>() + { + // LLNameValue() + LLNameValue nValue; + ensure("mName should have been NULL", nValue.mName == NULL); + ensure("getTypeEnum failed",nValue.getTypeEnum() == NVT_NULL); + ensure("getClassEnum failed",nValue.getClassEnum() == NVC_NULL); + ensure("getSendtoEnum failed",nValue.getSendtoEnum() == NVS_NULL); + + LLNameValue nValue1(" SecondLife ASSET RW SIM 232324343"); + + } + + // LLNameValue(const char* data); + // LLNameValue(const char* name, const char* data, const char* type, const char* nvclass, const char* nvsendto, + // TNameValueCallback nvcb = NULL, void** user_data = NULL); + template<> template<> + void namevalue_object_t::test<2>() + { + LLNameValue nValue(" SecondLife ASSET RW S 232324343"); + ensure("mName not set correctly", (0 == strcmp(nValue.mName,"SecondLife"))); + ensure("getTypeEnum failed", nValue.getTypeEnum() == NVT_ASSET); + ensure("getClassEnum failed", nValue.getClassEnum() == NVC_READ_WRITE); + ensure("getSendtoEnum failed", nValue.getSendtoEnum() == NVS_SIM); + ensure("getString failed", (0==strcmp(nValue.getAsset(),"232324343"))); + ensure("sendToData or sendToViewer failed", !nValue.sendToData() && !nValue.sendToViewer()); + + LLNameValue nValue1("\n\r SecondLife_1 STRING READ_WRITE SIM 232324343"); + ensure("1. mName not set correctly", (0 == strcmp(nValue1.mName,"SecondLife_1"))); + ensure("1. getTypeEnum failed", nValue1.getTypeEnum() == NVT_STRING); + ensure("1. getClassEnum failed", nValue1.getClassEnum() == NVC_READ_WRITE); + ensure("1. getSendtoEnum failed", nValue1.getSendtoEnum() == NVS_SIM); + ensure("1. getString failed", (0==strcmp(nValue1.getString(),"232324343"))); + ensure("1. sendToData or sendToViewer failed", !nValue1.sendToData() && !nValue1.sendToViewer()); + + LLNameValue nValue2("SecondLife", "23.5", "F32", "R", "DS"); + ensure("2. getTypeEnum failed", nValue2.getTypeEnum() == NVT_F32); + ensure("2. getClassEnum failed", nValue2.getClassEnum() == NVC_READ_ONLY); + ensure("2. getSendtoEnum failed", nValue2.getSendtoEnum() == NVS_DATA_SIM); + ensure("2. getF32 failed", *nValue2.getF32() == 23.5f); + ensure("2. sendToData or sendToViewer failed", nValue2.sendToData() && !nValue2.sendToViewer()); + + LLNameValue nValue3("SecondLife", "-43456787", "S32", "READ_ONLY", "SIM_SPACE"); + ensure("3. getTypeEnum failed", nValue3.getTypeEnum() == NVT_S32); + ensure("3. getClassEnum failed", nValue3.getClassEnum() == NVC_READ_ONLY); + ensure("3. getSendtoEnum failed", nValue3.getSendtoEnum() == NVS_DATA_SIM); + ensure("3. getS32 failed", *nValue3.getS32() == -43456787); + ensure("sendToData or sendToViewer failed", nValue3.sendToData() && !nValue3.sendToViewer()); + + LLNameValue nValue4("SecondLife", "<1.0, 2.0, 3.0>", "VEC3", "RW", "SV"); + LLVector3 llvec4(1.0, 2.0, 3.0); + ensure("4. getTypeEnum failed", nValue4.getTypeEnum() == NVT_VEC3); + ensure("4. getClassEnum failed", nValue4.getClassEnum() == NVC_READ_WRITE); + ensure("4. getSendtoEnum failed", nValue4.getSendtoEnum() == NVS_SIM_VIEWER); + ensure("4. getVec3 failed", *nValue4.getVec3() == llvec4); + ensure("4. sendToData or sendToViewer failed", !nValue4.sendToData() && nValue4.sendToViewer()); + + LLNameValue nValue5("SecondLife", "-1.0, 2.4, 3", "VEC3", "RW", "SIM_VIEWER"); + LLVector3 llvec5(-1.0f, 2.4f, 3); + ensure("5. getTypeEnum failed", nValue5.getTypeEnum() == NVT_VEC3); + ensure("5. getClassEnum failed", nValue5.getClassEnum() == NVC_READ_WRITE); + ensure("5. getSendtoEnum failed", nValue5.getSendtoEnum() == NVS_SIM_VIEWER); + ensure("5. getVec3 failed", *nValue5.getVec3() == llvec5); + ensure("5. sendToData or sendToViewer failed", !nValue5.sendToData() && nValue5.sendToViewer()); + + LLNameValue nValue6("SecondLife", "89764323", "U32", "RW", "DSV"); + ensure("6. getTypeEnum failed", nValue6.getTypeEnum() == NVT_U32); + ensure("6. getClassEnum failed", nValue6.getClassEnum() == NVC_READ_WRITE); + ensure("6. getSendtoEnum failed", nValue6.getSendtoEnum() == NVS_DATA_SIM_VIEWER); + ensure("6. getU32 failed", *nValue6.getU32() == 89764323); + ensure("6. sendToData or sendToViewer failed", nValue6.sendToData() && nValue6.sendToViewer()); + + LLNameValue nValue7("SecondLife", "89764323323232", "U64", "RW", "SIM_SPACE_VIEWER"); + U64 u64_7 = U64L(89764323323232); + ensure("7. getTypeEnum failed", nValue7.getTypeEnum() == NVT_U64); + ensure("7. getClassEnum failed", nValue7.getClassEnum() == NVC_READ_WRITE); + ensure("7. getSendtoEnum failed", nValue7.getSendtoEnum() == NVS_DATA_SIM_VIEWER); + ensure("7. getU32 failed", *nValue7.getU64() == u64_7); + ensure("7. sendToData or sendToViewer failed", nValue7.sendToData() && nValue7.sendToViewer()); + } + + // LLNameValue(const char* name, const char* data, const char* type, const char* nvclass, + // TNameValueCallback nvcb = NULL, void** user_data = NULL); + template<> template<> + void namevalue_object_t::test<3>() + { + LLNameValue nValue("SecondLife", "232324343", "ASSET", "READ_WRITE"); + ensure("mName not set correctly", (0 == strcmp(nValue.mName,"SecondLife"))); + ensure("getTypeEnum failed", nValue.getTypeEnum() == NVT_ASSET); + ensure("getClassEnum failed", nValue.getClassEnum() == NVC_READ_WRITE); + ensure("getSendtoEnum failed", nValue.getSendtoEnum() == NVS_SIM); + ensure("getString failed", (0==strcmp(nValue.getAsset(),"232324343"))); + + LLNameValue nValue1("SecondLife", "232324343", "STRING", "READ_WRITE"); + ensure("1. mName not set correctly", (0 == strcmp(nValue1.mName,"SecondLife"))); + ensure("1. getTypeEnum failed", nValue1.getTypeEnum() == NVT_STRING); + ensure("1. getClassEnum failed", nValue1.getClassEnum() == NVC_READ_WRITE); + ensure("1. getSendtoEnum failed", nValue1.getSendtoEnum() == NVS_SIM); + ensure("1. getString failed", (0==strcmp(nValue1.getString(),"232324343"))); + + LLNameValue nValue2("SecondLife", "23.5", "F32", "R"); + ensure("2. getTypeEnum failed", nValue2.getTypeEnum() == NVT_F32); + ensure("2. getClassEnum failed", nValue2.getClassEnum() == NVC_READ_ONLY); + ensure("2. getSendtoEnum failed", nValue2.getSendtoEnum() == NVS_SIM); + ensure("2. getF32 failed", *nValue2.getF32() == 23.5f); + + LLNameValue nValue3("SecondLife", "-43456787", "S32", "READ_ONLY"); + ensure("3. getTypeEnum failed", nValue3.getTypeEnum() == NVT_S32); + ensure("3. getClassEnum failed", nValue3.getClassEnum() == NVC_READ_ONLY); + ensure("3. getSendtoEnum failed", nValue3.getSendtoEnum() == NVS_SIM); + ensure("3. getS32 failed", *nValue3.getS32() == -43456787); + + LLNameValue nValue4("SecondLife", "<1.0, 2.0, 3.0>", "VEC3", "RW"); + LLVector3 llvec4(1.0, 2.0, 3.0); + ensure("4. getTypeEnum failed", nValue4.getTypeEnum() == NVT_VEC3); + ensure("4. getClassEnum failed", nValue4.getClassEnum() == NVC_READ_WRITE); + ensure("4. getSendtoEnum failed", nValue4.getSendtoEnum() == NVS_SIM); + ensure("4. getVec3 failed", *nValue4.getVec3() == llvec4); + + LLNameValue nValue5("SecondLife", "-1.0, 2.4, 3", "VEC3", "RW"); + LLVector3 llvec5(-1.0f, 2.4f, 3); + ensure("5. getTypeEnum failed", nValue5.getTypeEnum() == NVT_VEC3); + ensure("5. getClassEnum failed", nValue5.getClassEnum() == NVC_READ_WRITE); + ensure("5. getSendtoEnum failed", nValue5.getSendtoEnum() == NVS_SIM); + ensure("5. getVec3 failed", *nValue5.getVec3() == llvec5); + + LLNameValue nValue6("SecondLife", "89764323", "U32", "RW"); + ensure("6. getTypeEnum failed", nValue6.getTypeEnum() == NVT_U32); + ensure("6. getClassEnum failed", nValue6.getClassEnum() == NVC_READ_WRITE); + ensure("6. getSendtoEnum failed", nValue6.getSendtoEnum() == NVS_SIM); + ensure("6. getU32 failed", *nValue6.getU32() == 89764323); + + LLNameValue nValue7("SecondLife", "89764323323232", "U64", "RW"); + U64 u64_7 = U64L(89764323323232); + ensure("7. getTypeEnum failed", nValue7.getTypeEnum() == NVT_U64); + ensure("7. getClassEnum failed", nValue7.getClassEnum() == NVC_READ_WRITE); + ensure("7. getSendtoEnum failed", nValue7.getSendtoEnum() == NVS_SIM); + ensure("7. getU32 failed", *nValue7.getU64() == u64_7); + } + + // LLNameValue(const char* name, const char* type, const char* nvclass, + // TNameValueCallback nvcb = NULL, void** user_data = NULL); + template<> template<> + void namevalue_object_t::test<4>() + { + LLNameValue nValue("SecondLife", "STRING", "READ_WRITE"); + ensure("mName not set correctly", (0 == strcmp(nValue.mName,"SecondLife"))); + ensure("getTypeEnum failed", nValue.getTypeEnum() == NVT_STRING); + ensure("getClassEnum failed", nValue.getClassEnum() == NVC_READ_WRITE); + ensure("getSendtoEnum failed", nValue.getSendtoEnum() == NVS_SIM); + + LLNameValue nValue1("SecondLife", "ASSET", "READ_WRITE"); + ensure("1. mName not set correctly", (0 == strcmp(nValue1.mName,"SecondLife"))); + ensure("1. getTypeEnum for RW failed", nValue1.getTypeEnum() == NVT_ASSET); + ensure("1. getClassEnum for RW failed", nValue1.getClassEnum() == NVC_READ_WRITE); + ensure("1. getSendtoEnum for RW failed", nValue1.getSendtoEnum() == NVS_SIM); + + LLNameValue nValue2("SecondLife", "F32", "READ_ONLY"); + ensure("2. getTypeEnum failed", nValue2.getTypeEnum() == NVT_F32); + ensure("2. getClassEnum failed", nValue2.getClassEnum() == NVC_READ_ONLY); + ensure("2. getSendtoEnum failed", nValue2.getSendtoEnum() == NVS_SIM); + + LLNameValue nValue3("SecondLife", "S32", "READ_ONLY"); + ensure("3. getTypeEnum failed", nValue3.getTypeEnum() == NVT_S32); + ensure("3. getClassEnum failed", nValue3.getClassEnum() == NVC_READ_ONLY); + ensure("3. getSendtoEnum failed", nValue3.getSendtoEnum() == NVS_SIM); + + LLNameValue nValue4("SecondLife", "VEC3", "READ_WRITE"); + ensure("4. getTypeEnum failed", nValue4.getTypeEnum() == NVT_VEC3); + ensure("4. getClassEnum failed", nValue4.getClassEnum() == NVC_READ_WRITE); + ensure("4. getSendtoEnum failed", nValue4.getSendtoEnum() == NVS_SIM); + + LLNameValue nValue6("SecondLife", "U32", "READ_WRITE"); + ensure("6. getTypeEnum failed", nValue6.getTypeEnum() == NVT_U32); + ensure("6. getClassEnum failed", nValue6.getClassEnum() == NVC_READ_WRITE); + ensure("6. getSendtoEnum failed", nValue6.getSendtoEnum() == NVS_SIM); + + LLNameValue nValue7("SecondLife", "U64", "READ_WRITE"); + ensure("7. getTypeEnum failed", nValue7.getTypeEnum() == NVT_U64); + ensure("7. getClassEnum failed", nValue7.getClassEnum() == NVC_READ_WRITE); + ensure("7. getSendtoEnum failed", nValue7.getSendtoEnum() == NVS_SIM); + } + + template<> template<> + void namevalue_object_t::test<5>() + { + LLNameValue nValue("SecondLife", "This is a test", "STRING", "RW", "SIM"); + + ensure("getString failed", (0 == strcmp(nValue.getString(),"This is a test"))); + } + + template<> template<> + void namevalue_object_t::test<6>() + { + LLNameValue nValue("SecondLife", "This is a test", "ASSET", "RW", "S"); + ensure("getAsset failed", (0 == strcmp(nValue.getAsset(),"This is a test"))); + } + + template<> template<> + void namevalue_object_t::test<7>() + { + LLNameValue nValue("SecondLife", "555555", "F32", "RW", "SIM"); + + ensure("getF32 failed",*nValue.getF32() == 555555.f); + } + + template<> template<> + void namevalue_object_t::test<8>() + { + LLNameValue nValue("SecondLife", "-5555", "S32", "RW", "SIM"); + + ensure("getS32 failed", *nValue.getS32() == -5555); + + S32 sVal = 0x7FFFFFFF; + nValue.setS32(sVal); + ensure("getS32 failed", *nValue.getS32() == sVal); + + sVal = -0x7FFFFFFF; + nValue.setS32(sVal); + ensure("getS32 failed", *nValue.getS32() == sVal); + + sVal = 0; + nValue.setS32(sVal); + ensure("getS32 failed", *nValue.getS32() == sVal); + } + + template<> template<> + void namevalue_object_t::test<9>() + { + LLNameValue nValue("SecondLife", "<-3, 2, 1>", "VEC3", "RW", "SIM"); + LLVector3 vecExpected(-3, 2, 1); + LLVector3 vec; + nValue.getVec3(vec); + ensure("getVec3 failed", vec == vecExpected); + } + + template<> template<> + void namevalue_object_t::test<10>() + { + LLNameValue nValue("SecondLife", "12345678", "U32", "RW", "SIM"); + + ensure("getU32 failed",*nValue.getU32() == 12345678); + + U32 val = 0xFFFFFFFF; + nValue.setU32(val); + ensure("U32 max", *nValue.getU32() == val); + + val = 0; + nValue.setU32(val); + ensure("U32 min", *nValue.getU32() == val); + } + + template<> template<> + void namevalue_object_t::test<11>() + { + //skip_fail("incomplete support for U64."); + LLNameValue nValue("SecondLife", "44444444444", "U64", "RW", "SIM"); + + ensure("getU64 failed",*nValue.getU64() == U64L(44444444444)); + + // there is no LLNameValue::setU64() + } + + + template<> template<> + void namevalue_object_t::test<12>() + { + //skip_fail("incomplete support for U64."); + LLNameValue nValue("SecondLife U64 RW DSV 44444444444"); + std::string ret_str = nValue.printNameValue(); + + ensure_equals("1:printNameValue failed",ret_str,"SecondLife U64 RW DSV 44444444444"); + + LLNameValue nValue1(ret_str.c_str()); + ensure_equals("Serialization of printNameValue failed", *nValue.getU64(), *nValue1.getU64()); + } + + template<> template<> + void namevalue_object_t::test<13>() + { + LLNameValue nValue("SecondLife STRING RW DSV 44444444444"); + std::string ret_str = nValue.printData(); + ensure_equals("1:printData failed",ret_str,"44444444444"); + + LLNameValue nValue1("SecondLife S32 RW DSV 44444"); + ret_str = nValue1.printData(); + ensure_equals("2:printData failed",ret_str,"44444"); + } + + template<> template<> + void namevalue_object_t::test<14>() + { + LLNameValue nValue("SecodLife STRING RW SIM 22222"); + std::ostringstream stream1,stream2,stream3, stream4, stream5; + stream1 << nValue; + ensure_equals("STRING << failed",stream1.str(),"22222"); + + LLNameValue nValue1("SecodLife F32 RW SIM 22222"); + stream2 << nValue1; + ensure_equals("F32 << failed",stream2.str(),"22222"); + + LLNameValue nValue2("SecodLife S32 RW SIM 22222"); + stream3<< nValue2; + ensure_equals("S32 << failed",stream3.str(),"22222"); + + LLNameValue nValue3("SecodLife U32 RW SIM 122222"); + stream4<< nValue3; + ensure_equals("U32 << failed",stream4.str(),"122222"); + + // I don't think we use U64 name value pairs. JC + //skip_fail("incomplete support for U64."); + //LLNameValue nValue4("SecodLife U64 RW SIM 22222"); + //stream5<< nValue4; + //ensure("U64 << failed",0 == strcmp((stream5.str()).c_str(),"22222")); + } + + template<> template<> + void namevalue_object_t::test<15>() + { + LLNameValue nValue("SecondLife", "This is a test", "ASSET", "R", "S"); + + ensure("getAsset failed", (0 == strcmp(nValue.getAsset(),"This is a test"))); + // this should not have updated as it is read only. + nValue.setAsset("New Value should not be updated"); + ensure("setAsset on ReadOnly failed", (0 == strcmp(nValue.getAsset(),"This is a test"))); + + LLNameValue nValue1("SecondLife", "1234", "U32", "R", "S"); + // this should not have updated as it is read only. + nValue1.setU32(4567); + ensure("setU32 on ReadOnly failed", *nValue1.getU32() == 1234); + + LLNameValue nValue2("SecondLife", "1234", "S32", "R", "S"); + // this should not have updated as it is read only. + nValue2.setS32(4567); + ensure("setS32 on ReadOnly failed", *nValue2.getS32() == 1234); + + LLNameValue nValue3("SecondLife", "1234", "F32", "R", "S"); + // this should not have updated as it is read only. + nValue3.setF32(4567); + ensure("setF32 on ReadOnly failed", *nValue3.getF32() == 1234); + + LLNameValue nValue4("SecondLife", "<1,2,3>", "VEC3", "R", "S"); + // this should not have updated as it is read only. + LLVector3 vec(4,5,6); + nValue3.setVec3(vec); + LLVector3 vec1(1,2,3); + ensure("setVec3 on ReadOnly failed", *nValue4.getVec3() == vec1); + + // cant test for U64 as no set64 exists nor any operators support U64 type + } +} diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt index a842548980..bb33f0956d 100644 --- a/indra/test/CMakeLists.txt +++ b/indra/test/CMakeLists.txt @@ -49,7 +49,6 @@ set(test_SOURCE_FILES llmime_tut.cpp llmessageconfig_tut.cpp llmodularmath_tut.cpp - llnamevalue_tut.cpp llpermissions_tut.cpp llpipeutil.cpp llsaleinfo_tut.cpp @@ -57,7 +56,6 @@ set(test_SOURCE_FILES llsdmessagebuilder_tut.cpp llsdmessagereader_tut.cpp llsd_new_tut.cpp - llsdserialize_tut.cpp llsdutil_tut.cpp llservicebuilder_tut.cpp llstreamtools_tut.cpp -- cgit v1.3 From c3c03419fec9147c3be3518d46078279155d8f44 Mon Sep 17 00:00:00 2001 From: Adam Moss Date: Mon, 12 Oct 2009 14:20:51 +0000 Subject: DEV-41175 convert legacy common.cpp tut test into llcommon integration test. --- indra/llcommon/CMakeLists.txt | 1 + indra/llcommon/tests/commonmisc_test.cpp | 677 +++++++++++++++++++++++++++++++ indra/test/CMakeLists.txt | 1 - 3 files changed, 678 insertions(+), 1 deletion(-) create mode 100644 indra/llcommon/tests/commonmisc_test.cpp (limited to 'indra/llcommon') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 0861783df1..8e562ad5e0 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -241,6 +241,7 @@ LL_ADD_PROJECT_UNIT_TESTS(llcommon "${llcommon_TEST_SOURCE_FILES}") #set(TEST_DEBUG on) set(test_libs llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES}) +LL_ADD_INTEGRATION_TEST(commonmisc "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lllazy "lllazy.cpp" "${test_libs}") LL_ADD_INTEGRATION_TEST(llrand "llrand.cpp" "${test_libs}") LL_ADD_INTEGRATION_TEST(llsdserialize "llsdserialize.cpp" "${test_libs}") diff --git a/indra/llcommon/tests/commonmisc_test.cpp b/indra/llcommon/tests/commonmisc_test.cpp new file mode 100644 index 0000000000..ca27fe9b23 --- /dev/null +++ b/indra/llcommon/tests/commonmisc_test.cpp @@ -0,0 +1,677 @@ +/** + * @file common.cpp + * @author Phoenix + * @date 2005-10-12 + * @brief Common templates for test framework + * + * $LicenseInfo:firstyear=2005&license=viewergpl$ + * + * Copyright (c) 2005-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$ + */ + +/** + * + * THOROUGH_DESCRIPTION of common.cpp + * + */ + +#include +#include +#include + +#include "linden_common.h" + +#include "../llmemorystream.h" +#include "../llsd.h" +#include "../llsdserialize.h" +#include "../u64.h" +#include "../llhash.h" + +#include "../test/lltut.h" + + +#if LL_WINDOWS +// disable overflow warnings +#pragma warning(disable: 4307) +#endif + +namespace tut +{ + struct sd_data + { + }; + typedef test_group sd_test; + typedef sd_test::object sd_object; + tut::sd_test sd("llsd"); + + template<> template<> + void sd_object::test<1>() + { + std::ostringstream resp; + resp << "{'connect':true, 'position':[r128,r128,r128], 'look_at':[r0,r1,r0], 'agent_access':'M', 'region_x':i8192, 'region_y':i8192}"; + std::string str = resp.str(); + LLMemoryStream mstr((U8*)str.c_str(), str.size()); + LLSD response; + S32 count = LLSDSerialize::fromNotation(response, mstr, str.size()); + ensure("stream parsed", response.isDefined()); + ensure_equals("stream parse count", count, 13); + ensure_equals("sd type", response.type(), LLSD::TypeMap); + ensure_equals("map element count", response.size(), 6); + ensure_equals("value connect", response["connect"].asBoolean(), true); + ensure_equals("value region_x", response["region_x"].asInteger(),8192); + ensure_equals("value region_y", response["region_y"].asInteger(),8192); + } + + template<> template<> + void sd_object::test<2>() + { + const std::string decoded("random"); + //const std::string encoded("cmFuZG9t\n"); + const std::string streamed("b(6)\"random\""); + typedef std::vector buf_t; + buf_t buf; + std::copy( + decoded.begin(), + decoded.end(), + std::back_insert_iterator(buf)); + LLSD sd; + sd = buf; + std::stringstream str; + S32 count = LLSDSerialize::toNotation(sd, str); + ensure_equals("output count", count, 1); + std::string actual(str.str()); + ensure_equals("formatted binary encoding", actual, streamed); + sd.clear(); + LLSDSerialize::fromNotation(sd, str, str.str().size()); + std::vector after; + after = sd.asBinary(); + ensure_equals("binary decoded size", after.size(), decoded.size()); + ensure("binary decoding", (0 == memcmp( + &after[0], + decoded.c_str(), + decoded.size()))); + } + + template<> template<> + void sd_object::test<3>() + { + for(S32 i = 0; i < 100; ++i) + { + // gen up a starting point + typedef std::vector buf_t; + buf_t source; + srand(i); /* Flawfinder: ignore */ + S32 size = rand() % 1000 + 10; + std::generate_n( + std::back_insert_iterator(source), + size, + rand); + LLSD sd(source); + std::stringstream str; + S32 count = LLSDSerialize::toNotation(sd, str); + sd.clear(); + ensure_equals("format count", count, 1); + LLSD sd2; + count = LLSDSerialize::fromNotation(sd2, str, str.str().size()); + ensure_equals("parse count", count, 1); + buf_t dest = sd2.asBinary(); + str.str(""); + str << "binary encoding size " << i; + ensure_equals(str.str().c_str(), dest.size(), source.size()); + str.str(""); + str << "binary encoding " << i; + ensure(str.str().c_str(), (source == dest)); + } + } + + template<> template<> + void sd_object::test<4>() + { + std::ostringstream ostr; + ostr << "{'task_id':u1fd77b79-a8e7-25a5-9454-02a4d948ba1c}\n" + << "{\n\tname\tObject|\n}\n"; + std::string expected = ostr.str(); + std::stringstream serialized; + serialized << "'" << LLSDNotationFormatter::escapeString(expected) + << "'"; + LLSD sd; + S32 count = LLSDSerialize::fromNotation( + sd, + serialized, + serialized.str().size()); + ensure_equals("parse count", count, 1); + ensure_equals("String streaming", sd.asString(), expected); + } + + template<> template<> + void sd_object::test<5>() + { + for(S32 i = 0; i < 100; ++i) + { + // gen up a starting point + typedef std::vector buf_t; + buf_t source; + srand(666 + i); /* Flawfinder: ignore */ + S32 size = rand() % 1000 + 10; + std::generate_n( + std::back_insert_iterator(source), + size, + rand); + std::stringstream str; + str << "b(" << size << ")\""; + str.write((const char*)&source[0], size); + str << "\""; + LLSD sd; + S32 count = LLSDSerialize::fromNotation(sd, str, str.str().size()); + ensure_equals("binary parse", count, 1); + buf_t actual = sd.asBinary(); + ensure_equals("binary size", actual.size(), (size_t)size); + ensure("binary data", (0 == memcmp(&source[0], &actual[0], size))); + } + } + + template<> template<> + void sd_object::test<6>() + { + std::string expected("'{\"task_id\":u1fd77b79-a8e7-25a5-9454-02a4d948ba1c}'\t\n\t\t"); + std::stringstream str; + str << "s(" << expected.size() << ")'"; + str.write(expected.c_str(), expected.size()); + str << "'"; + LLSD sd; + S32 count = LLSDSerialize::fromNotation(sd, str, str.str().size()); + ensure_equals("parse count", count, 1); + std::string actual = sd.asString(); + ensure_equals("string sizes", actual.size(), expected.size()); + ensure_equals("string content", actual, expected); + } + + template<> template<> + void sd_object::test<7>() + { + std::string msg("come on in"); + std::stringstream stream; + stream << "{'connect':1, 'message':'" << msg << "'," + << " 'position':[r45.65,r100.1,r25.5]," + << " 'look_at':[r0,r1,r0]," + << " 'agent_access':'PG'}"; + LLSD sd; + S32 count = LLSDSerialize::fromNotation( + sd, + stream, + stream.str().size()); + ensure_equals("parse count", count, 12); + ensure_equals("bool value", sd["connect"].asBoolean(), true); + ensure_equals("message value", sd["message"].asString(), msg); + ensure_equals("pos x", sd["position"][0].asReal(), 45.65); + ensure_equals("pos y", sd["position"][1].asReal(), 100.1); + ensure_equals("pos z", sd["position"][2].asReal(), 25.5); + ensure_equals("look x", sd["look_at"][0].asReal(), 0.0); + ensure_equals("look y", sd["look_at"][1].asReal(), 1.0); + ensure_equals("look z", sd["look_at"][2].asReal(), 0.0); + } + + template<> template<> + void sd_object::test<8>() + { + std::stringstream resp; + resp << "{'label':'short string test', 'singlechar':'a', 'empty':'', 'endoftest':'end' }"; + LLSD response; + S32 count = LLSDSerialize::fromNotation( + response, + resp, + resp.str().size()); + ensure_equals("parse count", count, 5); + ensure_equals("sd type", response.type(), LLSD::TypeMap); + ensure_equals("map element count", response.size(), 4); + ensure_equals("singlechar", response["singlechar"].asString(), "a"); + ensure_equals("empty", response["empty"].asString(), ""); + } + + template<> template<> + void sd_object::test<9>() + { + std::ostringstream resp; + resp << "{'label':'short binary test', 'singlebinary':b(1)\"A\", 'singlerawstring':s(1)\"A\", 'endoftest':'end' }"; + std::string str = resp.str(); + LLSD sd; + LLMemoryStream mstr((U8*)str.c_str(), str.size()); + S32 count = LLSDSerialize::fromNotation(sd, mstr, str.size()); + ensure_equals("parse count", count, 5); + ensure("sd created", sd.isDefined()); + ensure_equals("sd type", sd.type(), LLSD::TypeMap); + ensure_equals("map element count", sd.size(), 4); + ensure_equals( + "label", + sd["label"].asString(), + "short binary test"); + std::vector bin = sd["singlebinary"].asBinary(); + std::vector expected; + expected.resize(1); + expected[0] = 'A'; + ensure("single binary", (0 == memcmp(&bin[0], &expected[0], 1))); + ensure_equals( + "single string", + sd["singlerawstring"].asString(), + std::string("A")); + ensure_equals("end", sd["endoftest"].asString(), "end"); + } + + template<> template<> + void sd_object::test<10>() + { + + std::string message("parcel '' is naughty."); + std::stringstream str; + str << "{'message':'" << LLSDNotationFormatter::escapeString(message) + << "'}"; + std::string expected_str("{'message':'parcel \\'\\' is naughty.'}"); + std::string actual_str = str.str(); + ensure_equals("stream contents", actual_str, expected_str); + LLSD sd; + S32 count = LLSDSerialize::fromNotation(sd, str, actual_str.size()); + ensure_equals("parse count", count, 2); + ensure("valid parse", sd.isDefined()); + std::string actual = sd["message"].asString(); + ensure_equals("message contents", actual, message); + } + + template<> template<> + void sd_object::test<11>() + { + std::string expected("\"\"\"\"''''''\""); + std::stringstream str; + str << "'" << LLSDNotationFormatter::escapeString(expected) << "'"; + LLSD sd; + S32 count = LLSDSerialize::fromNotation(sd, str, str.str().size()); + ensure_equals("parse count", count, 1); + ensure_equals("string value", sd.asString(), expected); + } + + template<> template<> + void sd_object::test<12>() + { + std::string expected("mytest\\"); + std::stringstream str; + str << "'" << LLSDNotationFormatter::escapeString(expected) << "'"; + LLSD sd; + S32 count = LLSDSerialize::fromNotation(sd, str, str.str().size()); + ensure_equals("parse count", count, 1); + ensure_equals("string value", sd.asString(), expected); + } + + template<> template<> + void sd_object::test<13>() + { + for(S32 i = 0; i < 1000; ++i) + { + // gen up a starting point + std::string expected; + srand(1337 + i); /* Flawfinder: ignore */ + S32 size = rand() % 30 + 5; + std::generate_n( + std::back_insert_iterator(expected), + size, + rand); + std::stringstream str; + str << "'" << LLSDNotationFormatter::escapeString(expected) << "'"; + LLSD sd; + S32 count = LLSDSerialize::fromNotation(sd, str, expected.size()); + ensure_equals("parse count", count, 1); + std::string actual = sd.asString(); +/* + if(actual != expected) + { + llwarns << "iteration " << i << llendl; + std::ostringstream e_str; + std::string::iterator iter = expected.begin(); + std::string::iterator end = expected.end(); + for(; iter != end; ++iter) + { + e_str << (S32)((U8)(*iter)) << " "; + } + e_str << std::endl; + llsd_serialize_string(e_str, expected); + llwarns << "expected size: " << expected.size() << llendl; + llwarns << "expected: " << e_str.str() << llendl; + + std::ostringstream a_str; + iter = actual.begin(); + end = actual.end(); + for(; iter != end; ++iter) + { + a_str << (S32)((U8)(*iter)) << " "; + } + a_str << std::endl; + llsd_serialize_string(a_str, actual); + llwarns << "actual size: " << actual.size() << llendl; + llwarns << "actual: " << a_str.str() << llendl; + } +*/ + ensure_equals("string value", actual, expected); + } + } + + template<> template<> + void sd_object::test<14>() + { +//#if LL_WINDOWS && _MSC_VER >= 1400 +// skip_fail("Fails on VS2005 due to broken LLSDSerialize::fromNotation() parser."); +//#endif + std::string param = "[{'version':i1},{'data':{'binary_bucket':b(0)\"\"},'from_id':u3c115e51-04f4-523c-9fa6-98aff1034730,'from_name':'Phoenix Linden','id':u004e45e5-5576-277a-fba7-859d6a4cb5c8,'message':'hey','offline':i0,'timestamp':i0,'to_id':u3c5f1bb4-5182-7546-6401-1d329b4ff2f8,'type':i0},{'agent_id':u3c115e51-04f4-523c-9fa6-98aff1034730,'god_level':i0,'limited_to_estate':i1}]"; + std::istringstream istr; + istr.str(param); + LLSD param_sd; + LLSDSerialize::fromNotation(param_sd, istr, param.size()); + ensure_equals("parsed type", param_sd.type(), LLSD::TypeArray); + LLSD version_sd = param_sd[0]; + ensure_equals("version type", version_sd.type(), LLSD::TypeMap); + ensure("has version", version_sd.has("version")); + ensure_equals("version number", version_sd["version"].asInteger(), 1); + LLSD src_sd = param_sd[1]; + ensure_equals("src type", src_sd.type(), LLSD::TypeMap); + LLSD dst_sd = param_sd[2]; + ensure_equals("dst type", dst_sd.type(), LLSD::TypeMap); + } + + template<> template<> + void sd_object::test<15>() + { + std::string val = "[{'failures':!,'successfuls':[u3c115e51-04f4-523c-9fa6-98aff1034730]}]"; + std::istringstream istr; + istr.str(val); + LLSD sd; + LLSDSerialize::fromNotation(sd, istr, val.size()); + ensure_equals("parsed type", sd.type(), LLSD::TypeArray); + ensure_equals("parsed size", sd.size(), 1); + LLSD failures = sd[0]["failures"]; + ensure("no failures.", failures.isUndefined()); + LLSD success = sd[0]["successfuls"]; + ensure_equals("success type", success.type(), LLSD::TypeArray); + ensure_equals("success size", success.size(), 1); + ensure_equals("success instance type", success[0].type(), LLSD::TypeUUID); + } + + template<> template<> + void sd_object::test<16>() + { + std::string val = "[f,t,0,1,{'foo':t,'bar':f}]"; + std::istringstream istr; + istr.str(val); + LLSD sd; + LLSDSerialize::fromNotation(sd, istr, val.size()); + ensure_equals("parsed type", sd.type(), LLSD::TypeArray); + ensure_equals("parsed size", sd.size(), 5); + ensure_equals("element 0 false", sd[0].asBoolean(), false); + ensure_equals("element 1 true", sd[1].asBoolean(), true); + ensure_equals("element 2 false", sd[2].asBoolean(), false); + ensure_equals("element 3 true", sd[3].asBoolean(), true); + LLSD map = sd[4]; + ensure_equals("element 4 type", map.type(), LLSD::TypeMap); + ensure_equals("map foo type", map["foo"].type(), LLSD::TypeBoolean); + ensure_equals("map foo value", map["foo"].asBoolean(), true); + ensure_equals("map bar type", map["bar"].type(), LLSD::TypeBoolean); + ensure_equals("map bar value", map["bar"].asBoolean(), false); + } + +/* + template<> template<> + void sd_object::test<16>() + { + } +*/ +} + +#if 0 +'{\'task_id\':u1fd77b79-a8e7-25a5-9454-02a4d948ba1c}\n{\n\tname\tObject|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t00082000\n\t\tcreator_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t00000000-0000-0000-0000-000000000000\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t10284\n\ttotal_crc\t35\n\ttype\t1\n\ttask_valid\t2\n\ttravel_access\t21\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t0\t0\t0\n\toldpos\t0\t0\t0\n\trotation\t4.371139183945160766597837e-08\t1\t4.371139183945160766597837e-08\t0\n\tvelocity\t0\t0\t0\n\tangvel\t0\t0\t0\n\tscale\t0.2816932\t0.2816932\t0.2816932\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t80\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t16\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\tscale_x\t1\n\t\t\tscale_y\t1\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t1\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t6\n\t{\n\t\timageid\t89556747-24cb-43ed-920b-47caed15465f\n\t\tcolors\t1 1 1 1\n\t\tscales\t0.56\n\t\tscalet\t0.56\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\t89556747-24cb-43ed-920b-47caed15465f\n\t\tcolors\t1 1 1 1\n\t\tscales\t0.56\n\t\tscalet\t0.56\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\t89556747-24cb-43ed-920b-47caed15465f\n\t\tcolors\t1 1 1 1\n\t\tscales\t0.56\n\t\tscalet\t0.56\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\t89556747-24cb-43ed-920b-47caed15465f\n\t\tcolors\t1 1 1 1\n\t\tscales\t0.56\n\t\tscalet\t0.56\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\t89556747-24cb-43ed-920b-47caed15465f\n\t\tcolors\t1 1 1 1\n\t\tscales\t0.56\n\t\tscalet\t0.56\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\t89556747-24cb-43ed-920b-47caed15465f\n\t\tcolors\t1 1 1 1\n\t\tscales\t0.56\n\t\tscalet\t0.56\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t1132625972249870\n\tbirthtime\t1132625953120694\n\treztime\t1132625953120694\n\tparceltime\t1132625953120694\n\ttax_rate\t1.01615\n\tnamevalue\tAttachmentOrientation VEC3 RW DS -3.141593, 0.000000, -3.141593\n\tnamevalue\tAttachmentOffset VEC3 RW DS 0.000000, 0.000000, 0.000000\n\tnamevalue\tAttachPt U32 RW S 5\n\tnamevalue\tAttachItemID STRING RW SV 1f9975c0-2951-1b93-dd83-46e2b932fcc8\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\torig_asset_id\t52019cdd-b464-ba19-e66d-3da751fef9da\n\torig_item_id\t1f9975c0-2951-1b93-dd83-46e2b932fcc8\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n' +#endif + +namespace tut +{ + struct mem_data + { + }; + typedef test_group mem_test; + typedef mem_test::object mem_object; + tut::mem_test mem_stream("memory_stream"); + + template<> template<> + void mem_object::test<1>() + { + const char HELLO_WORLD[] = "hello world"; + LLMemoryStream mem((U8*)&HELLO_WORLD[0], strlen(HELLO_WORLD)); /* Flawfinder: ignore */ + std::string hello; + std::string world; + mem >> hello >> world; + ensure_equals("first word", hello, std::string("hello")); + ensure_equals("second word", world, std::string("world")); + } +} + +namespace tut +{ + struct U64_data + { + }; + typedef test_group U64_test; + typedef U64_test::object U64_object; + tut::U64_test U64_testcase("U64_conversion"); + + // U64_to_str + template<> template<> + void U64_object::test<1>() + { + U64 val; + std::string val_str; + char result[256]; + std::string result_str; + + val = U64L(18446744073709551610); // slightly less than MAX_U64 + val_str = "18446744073709551610"; + + U64_to_str(val, result, sizeof(result)); + result_str = (const char*) result; + ensure_equals("U64_to_str converted 1.1", val_str, result_str); + + val = 0; + val_str = "0"; + U64_to_str(val, result, sizeof(result)); + result_str = (const char*) result; + ensure_equals("U64_to_str converted 1.2", val_str, result_str); + + val = U64L(18446744073709551615); // 0xFFFFFFFFFFFFFFFF + val_str = "18446744073709551615"; + U64_to_str(val, result, sizeof(result)); + result_str = (const char*) result; + ensure_equals("U64_to_str converted 1.3", val_str, result_str); + + // overflow - will result in warning at compile time + val = U64L(18446744073709551615) + 1; // overflow 0xFFFFFFFFFFFFFFFF + 1 == 0 + val_str = "0"; + U64_to_str(val, result, sizeof(result)); + result_str = (const char*) result; + ensure_equals("U64_to_str converted 1.4", val_str, result_str); + + val = U64L(-1); // 0xFFFFFFFFFFFFFFFF == 18446744073709551615 + val_str = "18446744073709551615"; + U64_to_str(val, result, sizeof(result)); + result_str = (const char*) result; + ensure_equals("U64_to_str converted 1.5", val_str, result_str); + + val = U64L(10000000000000000000); // testing preserving of 0s + val_str = "10000000000000000000"; + U64_to_str(val, result, sizeof(result)); + result_str = (const char*) result; + ensure_equals("U64_to_str converted 1.6", val_str, result_str); + + val = 1; // testing no leading 0s + val_str = "1"; + U64_to_str(val, result, sizeof(result)); + result_str = (const char*) result; + ensure_equals("U64_to_str converted 1.7", val_str, result_str); + + val = U64L(18446744073709551615); // testing exact sized buffer for result + val_str = "18446744073709551615"; + memset(result, 'A', sizeof(result)); // initialize buffer with all 'A' + U64_to_str(val, result, sizeof("18446744073709551615")); //pass in the exact size + result_str = (const char*) result; + ensure_equals("U64_to_str converted 1.8", val_str, result_str); + + val = U64L(18446744073709551615); // testing smaller sized buffer for result + val_str = "1844"; + memset(result, 'A', sizeof(result)); // initialize buffer with all 'A' + U64_to_str(val, result, 5); //pass in a size of 5. should only copy first 4 integers and add a null terminator + result_str = (const char*) result; + ensure_equals("U64_to_str converted 1.9", val_str, result_str); + } + + // str_to_U64 + template<> template<> + void U64_object::test<2>() + { + U64 val; + U64 result; + + val = U64L(18446744073709551610); // slightly less than MAX_U64 + result = str_to_U64("18446744073709551610"); + ensure_equals("str_to_U64 converted 2.1", val, result); + + val = U64L(0); // empty string + result = str_to_U64(LLStringUtil::null); + ensure_equals("str_to_U64 converted 2.2", val, result); + + val = U64L(0); // 0 + result = str_to_U64("0"); + ensure_equals("str_to_U64 converted 2.3", val, result); + + val = U64L(18446744073709551615); // 0xFFFFFFFFFFFFFFFF + result = str_to_U64("18446744073709551615"); + ensure_equals("str_to_U64 converted 2.4", val, result); + + // overflow - will result in warning at compile time + val = U64L(18446744073709551615) + 1; // overflow 0xFFFFFFFFFFFFFFFF + 1 == 0 + result = str_to_U64("18446744073709551616"); + ensure_equals("str_to_U64 converted 2.5", val, result); + + val = U64L(1234); // process till first non-integral character + result = str_to_U64("1234A5678"); + ensure_equals("str_to_U64 converted 2.6", val, result); + + val = U64L(5678); // skip all non-integral characters + result = str_to_U64("ABCD5678"); + ensure_equals("str_to_U64 converted 2.7", val, result); + + // should it skip negative sign and process + // rest of string or return 0 + val = U64L(1234); // skip initial negative sign + result = str_to_U64("-1234"); + ensure_equals("str_to_U64 converted 2.8", val, result); + + val = U64L(5678); // stop at negative sign in the middle + result = str_to_U64("5678-1234"); + ensure_equals("str_to_U64 converted 2.9", val, result); + + val = U64L(0); // no integers + result = str_to_U64("AaCD"); + ensure_equals("str_to_U64 converted 2.10", val, result); + } + + // U64_to_F64 + template<> template<> + void U64_object::test<3>() + { + F64 val; + F64 result; + + result = 18446744073709551610.0; + val = U64_to_F64(U64L(18446744073709551610)); + ensure_equals("U64_to_F64 converted 3.1", val, result); + + result = 18446744073709551615.0; // 0xFFFFFFFFFFFFFFFF + val = U64_to_F64(U64L(18446744073709551615)); + ensure_equals("U64_to_F64 converted 3.2", val, result); + + result = 0.0; // overflow 0xFFFFFFFFFFFFFFFF + 1 == 0 + // overflow - will result in warning at compile time + val = U64_to_F64(U64L(18446744073709551615)+1); + ensure_equals("U64_to_F64 converted 3.3", val, result); + + result = 0.0; // 0 + val = U64_to_F64(U64L(0)); + ensure_equals("U64_to_F64 converted 3.4", val, result); + + result = 1.0; // odd + val = U64_to_F64(U64L(1)); + ensure_equals("U64_to_F64 converted 3.5", val, result); + + result = 2.0; // even + val = U64_to_F64(U64L(2)); + ensure_equals("U64_to_F64 converted 3.6", val, result); + + result = U64L(0x7FFFFFFFFFFFFFFF) * 1.0L; // 0x7FFFFFFFFFFFFFFF + val = U64_to_F64(U64L(0x7FFFFFFFFFFFFFFF)); + ensure_equals("U64_to_F64 converted 3.7", val, result); + } + + // llstrtou64 + // seems to be deprecated - could not find it being used + // anywhere in the tarball - skipping unit tests for now +} + + +namespace tut +{ + struct hash_data + { + }; + typedef test_group hash_test; + typedef hash_test::object hash_object; + tut::hash_test hash_tester("hash_test"); + + template<> template<> + void hash_object::test<1>() + { + const char * str1 = "test string one"; + const char * same_as_str1 = "test string one"; + + size_t hash1 = llhash(str1); + size_t same_as_hash1 = llhash(same_as_str1); + + + ensure("Hashes from identical strings should be equal", hash1 == same_as_hash1); + + char str[100]; + strcpy( str, "Another test" ); + + size_t hash2 = llhash(str); + + strcpy( str, "Different string, same pointer" ); + + size_t hash3 = llhash(str); + + ensure("Hashes from same pointer but different string should not be equal", hash2 != hash3); + } +} diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt index bb33f0956d..f513efdffe 100644 --- a/indra/test/CMakeLists.txt +++ b/indra/test/CMakeLists.txt @@ -27,7 +27,6 @@ include_directories( ) set(test_SOURCE_FILES - common.cpp inventory.cpp io.cpp # llapp_tut.cpp # Temporarily removed until thread issues can be solved -- cgit v1.3 From 2a99e18ea152ef8843a12d7056436ee01dff5964 Mon Sep 17 00:00:00 2001 From: Adam Moss Date: Mon, 12 Oct 2009 14:56:03 +0000 Subject: DEV-41178 convert lldate legacy monolithic tut test into a llcommon integration test. --- indra/llcommon/CMakeLists.txt | 9 +- indra/llcommon/tests/lldate_test.cpp | 219 +++++++++++++++++++++++++++++++++++ indra/test/CMakeLists.txt | 1 - 3 files changed, 224 insertions(+), 5 deletions(-) create mode 100644 indra/llcommon/tests/lldate_test.cpp (limited to 'indra/llcommon') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 8e562ad5e0..48e053b8ee 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -242,10 +242,11 @@ LL_ADD_PROJECT_UNIT_TESTS(llcommon "${llcommon_TEST_SOURCE_FILES}") #set(TEST_DEBUG on) set(test_libs llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES}) LL_ADD_INTEGRATION_TEST(commonmisc "" "${test_libs}") -LL_ADD_INTEGRATION_TEST(lllazy "lllazy.cpp" "${test_libs}") -LL_ADD_INTEGRATION_TEST(llrand "llrand.cpp" "${test_libs}") -LL_ADD_INTEGRATION_TEST(llsdserialize "llsdserialize.cpp" "${test_libs}") -LL_ADD_INTEGRATION_TEST(llstring "llstring.cpp" "${test_libs}") +LL_ADD_INTEGRATION_TEST(lldate "" "${test_libs}") +LL_ADD_INTEGRATION_TEST(lllazy "" "${test_libs}") +LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}") +LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}") +LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}") # *TODO - reenable these once tcmalloc libs no longer break the build. #ADD_BUILD_TEST(llallocator llcommon) diff --git a/indra/llcommon/tests/lldate_test.cpp b/indra/llcommon/tests/lldate_test.cpp new file mode 100644 index 0000000000..1e36fdd119 --- /dev/null +++ b/indra/llcommon/tests/lldate_test.cpp @@ -0,0 +1,219 @@ +/** + * @file lldate_tut.cpp + * @author Adroit + * @date 2007-02 + * @brief LLDate test cases. + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-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 "../llstring.h" +#include "../lldate.h" + +#include "../test/lltut.h" + + +#define VALID_DATE "2003-04-30T04:00:00Z" +#define VALID_DATE_LEAP "2004-02-29T04:00:00Z" +#define VALID_DATE_HOUR_BOUNDARY "2003-04-30T23:59:59Z" +#define VALID_DATE_FRACTIONAL_SECS "2007-09-26T20:31:33.70Z" + +// invalid format +#define INVALID_DATE_MISSING_YEAR "-04-30T22:59:59Z" +#define INVALID_DATE_MISSING_MONTH "1900-0430T22:59:59Z" +#define INVALID_DATE_MISSING_DATE "1900-0430-T22:59:59Z" +#define INVALID_DATE_MISSING_T "1900-04-30-22:59:59Z" +#define INVALID_DATE_MISSING_HOUR "1900-04-30T:59:59Z" +#define INVALID_DATE_MISSING_MIN "1900-04-30T01::59Z" +#define INVALID_DATE_MISSING_SEC "1900-04-30T01:59Z" +#define INVALID_DATE_MISSING_Z "1900-04-30T01:59:23" +#define INVALID_DATE_EMPTY "" + +// invalid values +// apr 1.1.1 seems to not care about constraining the date to valid +// dates. Put these back when the parser checks. +#define LL_DATE_PARSER_CHECKS_BOUNDARY 0 +//#define INVALID_DATE_24HOUR_BOUNDARY "2003-04-30T24:00:00Z" +//#define INVALID_DATE_LEAP "2003-04-29T04:00:00Z" +//#define INVALID_DATE_HOUR "2003-04-30T24:59:59Z" +//#define INVALID_DATE_MIN "2003-04-30T22:69:59Z" +//#define INVALID_DATE_SEC "2003-04-30T22:59:69Z" +//#define INVALID_DATE_YEAR "0-04-30T22:59:59Z" +//#define INVALID_DATE_MONTH "2003-13-30T22:59:59Z" +//#define INVALID_DATE_DAY "2003-04-35T22:59:59Z" + +namespace tut +{ + struct date_test + { + + }; + typedef test_group date_test_t; + typedef date_test_t::object date_test_object_t; + tut::date_test_t tut_date_test("date_test"); + + /* format validation */ + template<> template<> + void date_test_object_t::test<1>() + { + LLDate date(VALID_DATE); + std::string expected_string; + bool result; + expected_string = VALID_DATE; + ensure_equals("Valid Date failed" , expected_string, date.asString()); + + result = date.fromString(VALID_DATE_LEAP); + expected_string = VALID_DATE_LEAP; + ensure_equals("VALID_DATE_LEAP failed" , expected_string, date.asString()); + + result = date.fromString(VALID_DATE_HOUR_BOUNDARY); + expected_string = VALID_DATE_HOUR_BOUNDARY; + ensure_equals("VALID_DATE_HOUR_BOUNDARY failed" , expected_string, date.asString()); + + result = date.fromString(VALID_DATE_FRACTIONAL_SECS); + expected_string = VALID_DATE_FRACTIONAL_SECS; + ensure_equals("VALID_DATE_FRACTIONAL_SECS failed" , expected_string, date.asString()); + + result = date.fromString(INVALID_DATE_MISSING_YEAR); + ensure_equals("INVALID_DATE_MISSING_YEAR should have failed" , result, false); + + result = date.fromString(INVALID_DATE_MISSING_MONTH); + ensure_equals("INVALID_DATE_MISSING_MONTH should have failed" , result, false); + + result = date.fromString(INVALID_DATE_MISSING_DATE); + ensure_equals("INVALID_DATE_MISSING_DATE should have failed" , result, false); + + result = date.fromString(INVALID_DATE_MISSING_T); + ensure_equals("INVALID_DATE_MISSING_T should have failed" , result, false); + + result = date.fromString(INVALID_DATE_MISSING_HOUR); + ensure_equals("INVALID_DATE_MISSING_HOUR should have failed" , result, false); + + result = date.fromString(INVALID_DATE_MISSING_MIN); + ensure_equals("INVALID_DATE_MISSING_MIN should have failed" , result, false); + + result = date.fromString(INVALID_DATE_MISSING_SEC); + ensure_equals("INVALID_DATE_MISSING_SEC should have failed" , result, false); + + result = date.fromString(INVALID_DATE_MISSING_Z); + ensure_equals("INVALID_DATE_MISSING_Z should have failed" , result, false); + + result = date.fromString(INVALID_DATE_EMPTY); + ensure_equals("INVALID_DATE_EMPTY should have failed" , result, false); + } + + /* Invalid Value Handling */ + template<> template<> + void date_test_object_t::test<2>() + { +#if LL_DATE_PARSER_CHECKS_BOUNDARY + LLDate date; + std::string expected_string; + bool result; + + result = date.fromString(INVALID_DATE_24HOUR_BOUNDARY); + ensure_equals("INVALID_DATE_24HOUR_BOUNDARY should have failed" , result, false); + ensure_equals("INVALID_DATE_24HOUR_BOUNDARY date still set to old value on failure!" , date.secondsSinceEpoch(), 0); + + result = date.fromString(INVALID_DATE_LEAP); + ensure_equals("INVALID_DATE_LEAP should have failed" , result, false); + + result = date.fromString(INVALID_DATE_HOUR); + ensure_equals("INVALID_DATE_HOUR should have failed" , result, false); + + result = date.fromString(INVALID_DATE_MIN); + ensure_equals("INVALID_DATE_MIN should have failed" , result, false); + + result = date.fromString(INVALID_DATE_SEC); + ensure_equals("INVALID_DATE_SEC should have failed" , result, false); + + result = date.fromString(INVALID_DATE_YEAR); + ensure_equals("INVALID_DATE_YEAR should have failed" , result, false); + + result = date.fromString(INVALID_DATE_MONTH); + ensure_equals("INVALID_DATE_MONTH should have failed" , result, false); + + result = date.fromString(INVALID_DATE_DAY); + ensure_equals("INVALID_DATE_DAY should have failed" , result, false); +#endif + } + + /* API checks */ + template<> template<> + void date_test_object_t::test<3>() + { + LLDate date; + std::istringstream stream(VALID_DATE); + std::string expected_string = VALID_DATE; + date.fromStream(stream); + ensure_equals("fromStream failed", date.asString(), expected_string); + } + + template<> template<> + void date_test_object_t::test<4>() + { + LLDate date1(VALID_DATE); + LLDate date2(date1); + ensure_equals("LLDate(const LLDate& date) constructor failed", date1.asString(), date2.asString()); + } + + template<> template<> + void date_test_object_t::test<5>() + { + LLDate date1(VALID_DATE); + LLDate date2(date1.secondsSinceEpoch()); + ensure_equals("secondsSinceEpoch not equal",date1.secondsSinceEpoch(), date2.secondsSinceEpoch()); + ensure_equals("LLDate created using secondsSinceEpoch not equal", date1.asString(), date2.asString()); + } + + template<> template<> + void date_test_object_t::test<6>() + { + LLDate date(VALID_DATE); + std::ostringstream stream; + stream << date; + std::string expected_str = VALID_DATE; + ensure_equals("ostringstream failed", expected_str, stream.str()); + } + + template<> template<> + void date_test_object_t::test<7>() + { + LLDate date; + std::istringstream stream(VALID_DATE); + stream >> date; + std::string expected_str = VALID_DATE; + std::ostringstream out_stream; + out_stream << date; + + ensure_equals("<< failed", date.asString(),expected_str); + ensure_equals("<< to >> failed", stream.str(),out_stream.str()); + } +} diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt index 25f24573b9..a5df23860c 100644 --- a/indra/test/CMakeLists.txt +++ b/indra/test/CMakeLists.txt @@ -32,7 +32,6 @@ set(test_SOURCE_FILES llbase64_tut.cpp llblowfish_tut.cpp llbuffer_tut.cpp - lldate_tut.cpp lldependencies_tut.cpp lldoubledispatch_tut.cpp llerror_tut.cpp -- cgit v1.3 From 406927f6293efa416b174cfa1c88689aab9615f7 Mon Sep 17 00:00:00 2001 From: Adam Moss Date: Wed, 14 Oct 2009 10:40:56 +0000 Subject: Merge a big bunch of fixes from maint-viewer. Hooray. svn merge -r136066:136073 svn+ssh://svn.lindenlab.com/svn/linden/branches/maint-viewer/maint-viewer-24-qa-9 DEV-8553 New Server Tools - Prep Land For Sale DEV-32942 (QAR-1521) Bad border crossings or TP / Ruthing issues DEV-32942 (QAR-1521) Bad border crossings or TP / Ruthing issues DEV-33239 VWR-13816: Resizing the Search Window Causes the Results to Refresh back to First Page DEV-27746 Running a dev build of Second Life will make console window show up on non-dev builds (Windows) DEV-33209 Linux 1.24.0.120778 client fails to run DEV-29123 SVC-3871: Crash of viewer when clicking on ghost objects at (0,0,0) on a sim DEV-35433 Attempting to upload wrong file type crashes viewer DEV-33499 viewer2009 is not using KDU DEV-33912 Griefing viewer crashes others' viewers with malformed sound files DEV-3784 VWR-138: Animation Priority not working correctly, Can't create new AOs DEV-20678 VWR-9069: Region variable says 'Region Name' in AR if no object is selected DEV-19934 Help->About Second Life doesn't differentiate between 32- and 64-bit Vista DEV-6604 Restored folders have 'Purge Item' and 'Restore Item' options DEV-12867 VWR-5717: Selected Text is not replaced by Input text when Japanese IME is on DEV-11894 Notecards/Texture windows don't open completely when opened from inventory DEV-10641 VWR-4955: Local Chat doesn't show end of last conversation DEV-30039 VWR-12620: Viewer build fails on Linux when compiled with -O2 (--type=Release) DEV-20944 VWR-9065: (intermittent) Right Click >profile on avatar does not display profile DEV-24828 Menu accelerator prefixes shouldn't be hard-coded DEV-34529 VWR-14267: Clicking send in an IM window does not add the sent text to the line editor history DEV-34124 Invite to group, search by name will not show resident if their first name is two characters DEV-20930 VWR-9248: On Mac: the "--url" option causes a command line parsing error DEV-35306 Adult keyword filter triggers multiple warnings DEV-35503 VWR-3595: "Second Life requires True Color (32-bit) to run in a window" message is incorrect DEV-35656 VWR-12995: FTBFS: error: format '%-3d' expects type 'int', but argument 3 has type 'size_t' DEV-30043 VWR-12533: Linux viewer build for OpenAL fails during packaging unless FMOD library is available DEV-31898 VWR-13202: Right clicking mouse triggers arrow key control events DEV-32610 Keyboard shortcuts on OSX viewer overridden by OSX DEV-27067 Coverity Prevent: EVALUATION_ORDER defects DEV-26188 VWR-2242: Specially formatted .BVH file can cause avatar distortion DEV-25475 About Land dialog no longer shows Area: field DEV-19897 OSX Viewer Installer (for an RC) opens with poor positioning DEV-22837 Inventory> Search Recent Items highlighting incorrect characters DEV-21709 VWR-9377: Mapping will default to leave exact sim name listing first. (Searching Gar forces Gar to come up and not Garden of Dreams) DEV-23079 implement volume serial for linux client DEV-13930 VWR-6432: Space Navigator operation with vehicles is broken DEV-27666 VWR-10829: Linux Viewer: CLICK_ACTION_PAY shows CLICK_ACTION_PLAY icon DEV-23670 Viewer crashes on startup if installed into a custom folder with Korean, Japanese or Chinese characters in path DEV-19313 VWR-8454: PARCEL_FLAG_ALLOW_CREATE_GROUP_OBJECTS not highlighted in script editor DEV-19918 VWR-8885: Move character/*.xml files to source bundle DEV-25555 VWR-11172: A source coding mistake prevents number-pad keys from specifying Ctrl+digit shortcuts on Windows DEV-8536 VWR-4057: Multi-line chat display bug - first character in line missing DEV-29592 Mac LLFastTimer uses wall clock instead of Intel PMU DEV-29644 VWR-12587: Cmake install target has a hard coded secondlife-bin reference remaining DEV-25320 VWR-11128: Python not always detected by develop.py DEV-30040 VWR-12617: Poor type name that violates Coding Standard breaks compatibility with system header files DEV-30380 indra/newview/res-sdl/toolpay.BMP is modified during ./develop.py configure DEV-31247 VWR-12763: non-portable printf specifier used with size_t causes FTBFS on 64bit (due to -Werror) DEV-29565 VWR-12569: A comment in lluistring.h contains undefined UTF-8 code sequences DEV-22100 VWR-9620: send_parcel_select_objects in newview/llfloaterland.cpp uses the wrong datatype for the ReturnType field causing a warning DEV-31911 Selected objects / primitives should be greyed out when nothing is selected DEV-3667 Windows: Accelerator keys should be "Ctrl+X" rather than "Ctrl-X" DEV-27223 disable gstreamer on 64-bit linux DEV-8172 We Need a Linden Sale Option to Sell Land to Anyone DEV-25511 VWR-10311: Enable LipSync by default DEV-20443 Revamp group creation confirmation dialog to be more communicative DEV-20132 VWR-7800: Joystick / SpaceNavigator. Camera should remain in position when exiting flycam mode into avatar mode. DEV-18420 VWR-8393: Have build scripts copy fmod from an external location DEV-24841 VWR-10717: Right Space Navigator button should toggle fly in avatar movment, not jump/flyup. DEV-28457 change auto-populate value in buy L$ window from 1000 to 2000 DEV-15545 VWR-3725: Please add resize option to the SEARCH window UI --- doc/contributions.txt | 56 ++-- indra/cmake/00-Common.cmake | 2 + indra/cmake/LLWindow.cmake | 2 +- indra/cmake/Python.cmake | 4 + indra/linux_crash_logger/CMakeLists.txt | 2 +- indra/llaudio/llaudiodecodemgr.cpp | 35 ++- indra/llaudio/llvorbisencode.cpp | 6 +- indra/llaudio/llvorbisencode.h | 11 + indra/llcharacter/llbvhloader.cpp | 13 + indra/llcharacter/llbvhloader.h | 7 +- indra/llcharacter/llgesture.cpp | 2 +- indra/llcharacter/lljointsolverrp3.cpp | 2 +- indra/llcommon/llerror.h | 4 +- indra/llcommon/llstring.h | 1 + indra/llcommon/llsys.cpp | 39 ++- indra/llimage/llimage.cpp | 2 +- indra/llinventory/llparcel.cpp | 1 - indra/llmath/llvolume.cpp | 2 +- indra/llmessage/lltemplatemessagebuilder.cpp | 4 +- indra/llmessage/lltemplatemessagereader.cpp | 7 +- indra/llrender/CMakeLists.txt | 2 + indra/llrender/llcubemap.cpp | 2 +- indra/llrender/llfontfreetype.cpp | 5 +- indra/llrender/llfontgl.cpp | 1 + indra/llrender/llglheaders.h | 4 - indra/llrender/llimagegl.cpp | 2 +- indra/llui/lllineeditor.cpp | 64 +++-- indra/llui/lllineeditor.h | 5 +- indra/llui/llmenugl.cpp | 42 +-- indra/llui/llresmgr.cpp | 8 + indra/llui/lluistring.h | 4 +- indra/llvfs/CMakeLists.txt | 1 + indra/llvfs/lldir.cpp | 16 +- indra/llvfs/lldir.h | 1 + indra/llvfs/lldir_mac.cpp | 3 +- indra/llvfs/lldir_win32.cpp | 21 +- indra/llvfs/lldirguard.h | 78 ++++++ indra/llwindow/llkeyboard.cpp | 69 ++++- indra/llwindow/llkeyboard.h | 9 +- indra/llwindow/llkeyboardwin32.cpp | 2 +- indra/llwindow/llwindowmacosx.cpp | 6 +- indra/llwindow/llwindowsdl.cpp | 18 +- indra/llxuixml/lltrans.h | 5 + indra/newview/CMakeLists.txt | 11 +- indra/newview/app_settings/keywords.ini | 1 + indra/newview/app_settings/settings.xml | 15 +- .../installers/darwin/firstlook-dmg/_DS_Store | Bin 12292 -> 12292 bytes .../installers/darwin/publicnightly-dmg/_DS_Store | Bin 12292 -> 12292 bytes .../darwin/releasecandidate-dmg/_DS_Store | Bin 12292 -> 12292 bytes indra/newview/llagent.cpp | 21 +- indra/newview/llagent.h | 4 +- indra/newview/llappviewer.cpp | 20 +- indra/newview/llappviewerlinux.cpp | 26 +- indra/newview/llappviewerlinux.h | 5 +- indra/newview/llappviewerlinux_api_dbus.cpp | 6 +- indra/newview/llappviewermacosx.cpp | 19 +- indra/newview/lldrawpoolwater.cpp | 2 +- indra/newview/llfloateranimpreview.cpp | 10 +- indra/newview/llfloaterauction.cpp | 293 ++++++++++++++++++++- indra/newview/llfloaterauction.h | 16 +- indra/newview/llfloateravatarpicker.cpp | 11 +- indra/newview/llfloateravatarpicker.h | 2 +- indra/newview/llfloatergesture.cpp | 25 +- indra/newview/llfloaterland.cpp | 4 +- indra/newview/llfloaterreporter.cpp | 1 + indra/newview/llfloatersellland.cpp | 2 +- indra/newview/llfloatertools.cpp | 5 + indra/newview/llfloaterworldmap.cpp | 40 +-- indra/newview/llfloaterworldmap.h | 1 - indra/newview/llimpanel.cpp | 2 + indra/newview/llinventorybridge.cpp | 2 + indra/newview/llinventoryfilter.cpp | 7 + indra/newview/llmaniprotate.cpp | 4 +- indra/newview/llpanelgroup.cpp | 8 +- indra/newview/llpanelgroupgeneral.cpp | 2 +- indra/newview/llpreviewgesture.cpp | 2 +- indra/newview/llpreviewscript.cpp | 4 +- indra/newview/llpreviewtexture.cpp | 113 +++++++- indra/newview/llpreviewtexture.h | 6 +- indra/newview/llselectmgr.cpp | 2 +- indra/newview/llsky.cpp | 3 + indra/newview/llsky.h | 6 +- indra/newview/llstartup.cpp | 7 + indra/newview/lltexturefetch.cpp | 2 +- indra/newview/llviewercamera.cpp | 5 +- indra/newview/llviewercontrol.cpp | 2 +- indra/newview/llviewerjoystick.cpp | 87 ++++-- indra/newview/llviewerjoystick.h | 5 +- indra/newview/llviewermedia.cpp | 1 + indra/newview/llviewermenu.cpp | 92 +++++++ indra/newview/llviewermenufile.cpp | 2 +- indra/newview/llviewerobjectlist.cpp | 99 ++++--- indra/newview/llviewerwindow.cpp | 5 - indra/newview/llvoiceclient.cpp | 28 +- indra/newview/llvosky.cpp | 2 +- indra/newview/llvosky.h | 2 +- indra/newview/llwaterparammanager.cpp | 2 +- indra/newview/llwlparammanager.cpp | 2 +- indra/newview/llxmlrpctransaction.cpp | 10 +- indra/newview/llxmlrpctransaction.h | 6 +- indra/newview/pipeline.cpp | 6 +- indra/newview/res-sdl/arrow.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/arrowcop.BMP | Bin 0 -> 3126 bytes indra/newview/res-sdl/arrowcopmulti.BMP | Bin 0 -> 3126 bytes indra/newview/res-sdl/arrowdrag.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/circleandline.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/cross.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/hand.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/ibeam.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/ll_icon.BMP | Bin 0 -> 5174 bytes indra/newview/res-sdl/llarrow.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/llarrowdrag.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/llarrowdragmulti.BMP | Bin 0 -> 3126 bytes indra/newview/res-sdl/llarrowlocked.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/llgrablocked.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/llno.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/llnolocked.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/lltoolcamera.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/lltoolcreate.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/lltoolfocus.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/lltoolgrab.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/lltoolland.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/lltoolpan.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/lltoolpipette.BMP | Bin 0 -> 3126 bytes indra/newview/res-sdl/lltoolrotate.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/lltoolscale.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/lltooltranslate.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/lltoolzoomin.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/lltoolzoomout.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/sizenesw.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/sizens.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/sizenwse.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/sizewe.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/toolmediaopen.BMP | Bin 0 -> 3128 bytes indra/newview/res-sdl/toolpause.BMP | Bin 0 -> 3128 bytes indra/newview/res-sdl/toolpickobject.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/toolpickobject2.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/toolpickobject3.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/toolplay.BMP | Bin 0 -> 3128 bytes indra/newview/res-sdl/wait.BMP | Bin 0 -> 2102 bytes indra/newview/res-sdl/working.BMP | Bin 0 -> 2102 bytes .../skins/default/xui/en/floater_auction.xml | 42 ++- .../default/xui/en/floater_preview_texture.xml | 62 ++++- .../newview/skins/default/xui/en/floater_tools.xml | 2 - .../skins/default/xui/en/floater_world_map.xml | 3 +- indra/newview/skins/default/xui/en/menu_viewer.xml | 69 ++++- .../newview/skins/default/xui/en/notifications.xml | 30 +-- .../skins/default/xui/en/panel_group_general.xml | 2 +- .../default/xui/en/panel_preferences_advanced.xml | 29 +- indra/newview/skins/default/xui/en/strings.xml | 16 +- indra/newview/viewer_manifest.py | 16 +- indra/test/lltut.h | 2 +- install.xml | 18 +- 153 files changed, 1468 insertions(+), 459 deletions(-) create mode 100644 indra/llvfs/lldirguard.h create mode 100644 indra/newview/res-sdl/arrow.BMP create mode 100644 indra/newview/res-sdl/arrowcop.BMP create mode 100644 indra/newview/res-sdl/arrowcopmulti.BMP create mode 100644 indra/newview/res-sdl/arrowdrag.BMP create mode 100644 indra/newview/res-sdl/circleandline.BMP create mode 100644 indra/newview/res-sdl/cross.BMP create mode 100644 indra/newview/res-sdl/hand.BMP create mode 100644 indra/newview/res-sdl/ibeam.BMP create mode 100644 indra/newview/res-sdl/ll_icon.BMP create mode 100644 indra/newview/res-sdl/llarrow.BMP create mode 100644 indra/newview/res-sdl/llarrowdrag.BMP create mode 100644 indra/newview/res-sdl/llarrowdragmulti.BMP create mode 100644 indra/newview/res-sdl/llarrowlocked.BMP create mode 100644 indra/newview/res-sdl/llgrablocked.BMP create mode 100644 indra/newview/res-sdl/llno.BMP create mode 100644 indra/newview/res-sdl/llnolocked.BMP create mode 100644 indra/newview/res-sdl/lltoolcamera.BMP create mode 100644 indra/newview/res-sdl/lltoolcreate.BMP create mode 100644 indra/newview/res-sdl/lltoolfocus.BMP create mode 100644 indra/newview/res-sdl/lltoolgrab.BMP create mode 100644 indra/newview/res-sdl/lltoolland.BMP create mode 100644 indra/newview/res-sdl/lltoolpan.BMP create mode 100644 indra/newview/res-sdl/lltoolpipette.BMP create mode 100644 indra/newview/res-sdl/lltoolrotate.BMP create mode 100644 indra/newview/res-sdl/lltoolscale.BMP create mode 100644 indra/newview/res-sdl/lltooltranslate.BMP create mode 100644 indra/newview/res-sdl/lltoolzoomin.BMP create mode 100644 indra/newview/res-sdl/lltoolzoomout.BMP create mode 100644 indra/newview/res-sdl/sizenesw.BMP create mode 100644 indra/newview/res-sdl/sizens.BMP create mode 100644 indra/newview/res-sdl/sizenwse.BMP create mode 100644 indra/newview/res-sdl/sizewe.BMP create mode 100644 indra/newview/res-sdl/toolmediaopen.BMP create mode 100644 indra/newview/res-sdl/toolpause.BMP create mode 100644 indra/newview/res-sdl/toolpickobject.BMP create mode 100644 indra/newview/res-sdl/toolpickobject2.BMP create mode 100644 indra/newview/res-sdl/toolpickobject3.BMP create mode 100644 indra/newview/res-sdl/toolplay.BMP create mode 100644 indra/newview/res-sdl/wait.BMP create mode 100644 indra/newview/res-sdl/working.BMP (limited to 'indra/llcommon') diff --git a/doc/contributions.txt b/doc/contributions.txt index 9b3087a0ac..6b51e2649e 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -1,7 +1,7 @@ Linden Lab would like to acknowledge source code contributions from the -following residents. The Second Life resident name is given below, +following residents. The Second Life resident name is given below, along with the issue identifier corresponding to the patches we've -received from them. To see more about these contributions, visit the +received from them. To see more about these contributions, visit the browsable version: http://wiki.secondlife.com/wiki/Source_contributions Able Whitman @@ -25,19 +25,25 @@ Aimee Trescothick VWR-6348 VWR-6358 VWR-6360 + VWR-6432 VWR-6550 VWR-6583 VWR-6482 VWR-7109 VWR-7383 + VWR-7800 + VWR-8008 VWR-8341 VWR-8430 VWR-8482 VWR-9255 + VWR-10717 VWR-10990 VWR-11100 VWR-11111 - VWR-11844 + VWR-11844 + VWR-14267 + VWR-14278 VWR-14087 Alejandro Rosenthal VWR-1184 @@ -45,9 +51,11 @@ Aleric Inglewood VWR-10001 VWR-10759 VWR-10837 + VWR-12691 VWR-13996 + VWR-14426 Ales Beaumont - VWR-9352 + VWR-9352 Alissa Sabre VWR-81 VWR-83 @@ -69,7 +77,7 @@ Alissa Sabre VWR-1351 VWR-1353 VWR-1410 - VWR-1843 + VWR-1843 VWR-2116 VWR-2826 VWR-3290 @@ -77,19 +85,25 @@ Alissa Sabre VWR-3857 VWR-4010 VWR-5575 - VWR-5929 - VWR-6384 - VWR-6385 + VWR-5717 + VWR-5929 + VWR-6384 + VWR-6385 VWR-6386 - VWR-6430 + VWR-6430 VWR-6858 - VWR-6668 - VWR-7086 - VWR-7087 - VWR-7153 - VWR-7168 + VWR-6668 + VWR-7086 + VWR-7087 + VWR-7153 + VWR-7168 VWR-9190 VWR-10728 + VWR-11172 + VWR-12569 + VWR-12617 + VWR-12620 + VWR-12789 Angus Boyd VWR-592 Ann Congrejo @@ -147,6 +161,7 @@ Carjay McGinnis VWR-4212 VWR-6154 VWR-9400 + VWR-9620 Catherine Pfeffer VWR-1282 VWR-8624 @@ -294,6 +309,7 @@ Kerutsen Sellery VWR-1350 Khyota Wulluf VWR-2085 + VWR-8885 VWR-9256 VWR-9966 Kunnis Basiat @@ -336,6 +352,7 @@ McCabe Maxsted VWR-7877 VWR-7893 VWR-8080 + VWR-8454 VWR-8689 VWR-9007 Michelle2 Zenovka @@ -350,6 +367,7 @@ Michelle2 Zenovka VWR-5082 VWR-5659 VWR-7831 + VWR-8885 VWR-8889 VWR-8310 VWR-9499 @@ -464,7 +482,7 @@ Pf Shan CT-321 princess niven VWR-5733 - CT-85 + CT-85 CT-320 CT-352 Renault Clio @@ -481,7 +499,11 @@ Ringo Tuxing Robin Cornelius VWR-2488 VWR-9557 + VWR-11128 + VWR-12533 VWR-12587 + VWR-12763 + VWR-12995 Ryozu Kojima VWR-53 VWR-287 @@ -564,12 +586,16 @@ TBBle Kurosawa VWR-1892 Teardrops Fall VWR-5366 +Techwolf Lupindo + SNOW-92 + VWR-12385 tenebrous pau VWR-247 Tharax Ferraris VWR-605 Thickbrick Sleaford VWR-7109 + VWR-9287 VWR-13947 Thraxis Epsilon SVC-371 diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index 2a70263446..b168c08552 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -170,6 +170,8 @@ if (LINUX) if (NOT STANDALONE) # this stops us requiring a really recent glibc at runtime add_definitions(-fno-stack-protector) + # linking can be so slow - give us a chance to figure out why + set(CMAKE_CXX_LINK_FLAGS "-Wl,--stats,--no-keep-memory") endif (NOT STANDALONE) endif (VIEWER) diff --git a/indra/cmake/LLWindow.cmake b/indra/cmake/LLWindow.cmake index c0efa27f6e..a5b9cf47a4 100644 --- a/indra/cmake/LLWindow.cmake +++ b/indra/cmake/LLWindow.cmake @@ -13,9 +13,9 @@ if (STANDALONE) SDL_LIBRARY ) else (STANDALONE) - use_prebuilt_binary(SDL) use_prebuilt_binary(mesa) if (LINUX AND VIEWER) + use_prebuilt_binary(SDL) set (SDL_FOUND TRUE) set (SDL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/i686-linux) set (SDL_LIBRARY SDL) diff --git a/indra/cmake/Python.cmake b/indra/cmake/Python.cmake index 4f86d3234e..0901c1b7a2 100644 --- a/indra/cmake/Python.cmake +++ b/indra/cmake/Python.cmake @@ -13,6 +13,10 @@ if (WINDOWS) [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath] [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath] [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.3\\InstallPath] + [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.6\\InstallPath] + [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath] + [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath] + [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.3\\InstallPath] ) elseif (EXISTS /etc/debian_version) # On Debian and Ubuntu, avoid Python 2.4 if possible. diff --git a/indra/linux_crash_logger/CMakeLists.txt b/indra/linux_crash_logger/CMakeLists.txt index 6f6754ed7a..4b19e28066 100644 --- a/indra/linux_crash_logger/CMakeLists.txt +++ b/indra/linux_crash_logger/CMakeLists.txt @@ -38,7 +38,7 @@ list(APPEND linux_crash_logger_SOURCE_FILES ${linux_crash_logger_HEADER_FILES} ) -list(APPEND CMAKE_EXE_LINKER_FLAGS -Wl,--as-needed) +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed") add_executable(linux-crash-logger ${linux_crash_logger_SOURCE_FILES}) diff --git a/indra/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp index 099c4eba40..ae959eaa81 100644 --- a/indra/llaudio/llaudiodecodemgr.cpp +++ b/indra/llaudio/llaudiodecodemgr.cpp @@ -43,6 +43,8 @@ #include "llassetstorage.h" #include "llrefcount.h" +#include "llvorbisencode.h" + #include "vorbis/codec.h" #include "vorbis/vorbisfile.h" @@ -218,11 +220,42 @@ BOOL LLVorbisDecodeState::initDecode() return(FALSE); } - size_t size_guess = (size_t)ov_pcm_total(&mVF, -1); + S32 sample_count = ov_pcm_total(&mVF, -1); + size_t size_guess = (size_t)sample_count; vorbis_info* vi = ov_info(&mVF, -1); size_guess *= vi->channels; size_guess *= 2; size_guess += 2048; + + bool abort_decode = false; + + if( vi->channels < 1 || vi->channels > LLVORBIS_CLIP_MAX_CHANNELS ) + { + abort_decode = true; + llwarns << "Bad channel count: " << vi->channels << llendl; + } + + if( (size_t)sample_count > LLVORBIS_CLIP_REJECT_SAMPLES ) + { + abort_decode = true; + llwarns << "Illegal sample count: " << sample_count << llendl; + } + + if( size_guess > LLVORBIS_CLIP_REJECT_SIZE ) + { + abort_decode = true; + llwarns << "Illegal sample size: " << size_guess << llendl; + } + + if( abort_decode ) + { + llwarns << "Canceling initDecode. Bad asset: " << mUUID << llendl; + llwarns << "Bad asset encoded by: " << ov_comment(&mVF,-1)->vendor << llendl; + delete mInFilep; + mInFilep = NULL; + return FALSE; + } + mWAVBuffer.reserve(size_guess); mWAVBuffer.resize(WAV_HEADER_SIZE); diff --git a/indra/llaudio/llvorbisencode.cpp b/indra/llaudio/llvorbisencode.cpp index 8ee082a245..0c1ad8191c 100644 --- a/indra/llaudio/llvorbisencode.cpp +++ b/indra/llaudio/llvorbisencode.cpp @@ -162,13 +162,13 @@ S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& erro return(LLVORBISENC_PCM_FORMAT_ERR); } - if ((num_channels < 1) || (num_channels > 2)) + if ((num_channels < 1) || (num_channels > LLVORBIS_CLIP_MAX_CHANNELS)) { error_msg = "SoundFileInvalidChannelCount"; return(LLVORBISENC_MULTICHANNEL_ERR); } - if (sample_rate != 44100) + if (sample_rate != LLVORBIS_CLIP_SAMPLE_RATE) { error_msg = "SoundFileInvalidSampleRate"; return(LLVORBISENC_UNSUPPORTED_SAMPLE_RATE); @@ -188,7 +188,7 @@ S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& erro F32 clip_length = (F32)raw_data_length/(F32)bytes_per_sec; - if (clip_length > 10.0f) + if (clip_length > LLVORBIS_CLIP_MAX_TIME) { error_msg = "SoundFileInvalidTooLong"; return(LLVORBISENC_CLIP_TOO_LONG); diff --git a/indra/llaudio/llvorbisencode.h b/indra/llaudio/llvorbisencode.h index ff5ce3a053..6531c1919e 100644 --- a/indra/llaudio/llvorbisencode.h +++ b/indra/llaudio/llvorbisencode.h @@ -45,6 +45,17 @@ const S32 LLVORBISENC_UNSUPPORTED_SAMPLE_RATE = 8; // unsupported sample ra const S32 LLVORBISENC_UNSUPPORTED_WORD_SIZE = 9; // unsupported word size const S32 LLVORBISENC_CLIP_TOO_LONG = 10; // source file is too long +const F32 LLVORBIS_CLIP_MAX_TIME = 10.0f; +const U8 LLVORBIS_CLIP_MAX_CHANNELS = 2; +const U32 LLVORBIS_CLIP_SAMPLE_RATE = 44100; +const U32 LLVORBIS_CLIP_MAX_SAMPLES_PER_CHANNEL = (U32)(LLVORBIS_CLIP_MAX_TIME * LLVORBIS_CLIP_SAMPLE_RATE); +const U32 LLVORBIS_CLIP_MAX_SAMPLES = LLVORBIS_CLIP_MAX_SAMPLES_PER_CHANNEL * LLVORBIS_CLIP_MAX_CHANNELS; +const size_t LLVORBIS_CLIP_MAX_SAMPLE_DATA = LLVORBIS_CLIP_MAX_SAMPLES * 2; // 2 = 16-bit + +// Treat anything this long as a bad asset. A little fudge factor at the end: +// Make that a lot of fudge factor. We're allowing 30 sec for now - 3x legal upload +const size_t LLVORBIS_CLIP_REJECT_SAMPLES = LLVORBIS_CLIP_MAX_SAMPLES * 3; +const size_t LLVORBIS_CLIP_REJECT_SIZE = LLVORBIS_CLIP_MAX_SAMPLE_DATA * 3; S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& error_msg); S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname); diff --git a/indra/llcharacter/llbvhloader.cpp b/indra/llcharacter/llbvhloader.cpp index 24391eb8f3..3dd54b4760 100644 --- a/indra/llcharacter/llbvhloader.cpp +++ b/indra/llcharacter/llbvhloader.cpp @@ -91,7 +91,9 @@ const char *LLBVHLoader::ST_NO_XLT_EASEIN = "Can't get easeIn values."; const char *LLBVHLoader::ST_NO_XLT_EASEOUT = "Can't get easeOut values."; const char *LLBVHLoader::ST_NO_XLT_HAND = "Can't get hand morph value."; const char *LLBVHLoader::ST_NO_XLT_EMOTE = "Can't read emote name."; +const char *LLBVHLoader::ST_BAD_ROOT = "Illegal ROOT joint."; */ + //------------------------------------------------------------------------ // find_next_whitespace() //------------------------------------------------------------------------ @@ -777,6 +779,17 @@ ELoadStatus LLBVHLoader::loadBVHFile(const char *buffer, char* error_text, S32 & return E_ST_NO_NAME; } + //--------------------------------------------------------------- + // we require the root joint be "hip" - DEV-26188 + //--------------------------------------------------------------- + const char* FORCED_ROOT_NAME = "hip"; + if ( (mJoints.size() == 0 ) && ( !strstr(jointName, FORCED_ROOT_NAME) ) ) + { + strncpy(error_text, line.c_str(), 127); /* Flawfinder: ignore */ + return E_ST_BAD_ROOT; + } + + //---------------------------------------------------------------- // add a set of keyframes for this joint //---------------------------------------------------------------- diff --git a/indra/llcharacter/llbvhloader.h b/indra/llcharacter/llbvhloader.h index ecdfc95478..85ab035e61 100644 --- a/indra/llcharacter/llbvhloader.h +++ b/indra/llcharacter/llbvhloader.h @@ -216,7 +216,8 @@ typedef enum e_load_status E_ST_NO_XLT_EASEIN, E_ST_NO_XLT_EASEOUT, E_ST_NO_XLT_HAND, - E_ST_NO_XLT_EMOTE + E_ST_NO_XLT_EMOTE, + E_ST_BAD_ROOT } ELoadStatus; //------------------------------------------------------------------------ @@ -235,7 +236,7 @@ public: /* // Status Codes - typedef const char *Status; + typedef const char *status_t; static const char *ST_OK; static const char *ST_EOF; static const char *ST_NO_CONSTRAINT; @@ -267,6 +268,7 @@ public: static const char *ST_NO_XLT_EASEOUT; static const char *ST_NO_XLT_HAND; static const char *ST_NO_XLT_EMOTE; + static const char *ST_BAD_ROOT; */ // Loads the specified translation table. ELoadStatus loadTranslationTable(const char *fileName); @@ -325,6 +327,7 @@ protected: BOOL mInitialized; ELoadStatus mStatus; + // computed values F32 mDuration; }; diff --git a/indra/llcharacter/llgesture.cpp b/indra/llcharacter/llgesture.cpp index 4ee29fe100..83e4e35b00 100644 --- a/indra/llcharacter/llgesture.cpp +++ b/indra/llcharacter/llgesture.cpp @@ -304,7 +304,7 @@ BOOL LLGestureList::trigger(KEY key, MASK mask) } else { - llwarns << "NULL gesture in gesture list (" << i << ")" << llendl + llwarns << "NULL gesture in gesture list (" << i << ")" << llendl; } } return FALSE; diff --git a/indra/llcharacter/lljointsolverrp3.cpp b/indra/llcharacter/lljointsolverrp3.cpp index 0ea92a2d77..6599a76b16 100644 --- a/indra/llcharacter/lljointsolverrp3.cpp +++ b/indra/llcharacter/lljointsolverrp3.cpp @@ -211,7 +211,7 @@ void LLJointSolverRP3::solve() //------------------------------------------------------------------------- LLVector3 abacCompOrthoVec = abVec - acVec * ((abVec * acVec)/(acVec * acVec)); -// llinfos << "abacCompOrthoVec : " << abacCompOrthoVec << llendl +// llinfos << "abacCompOrthoVec : " << abacCompOrthoVec << llendl; //------------------------------------------------------------------------- // compute the normal of the original ABC plane (and store for later) diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index 6794be4904..37e922d4b7 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -239,7 +239,7 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG; */ #define lllog(level, broadTag, narrowTag, once) \ - { \ + do { \ static LLError::CallSite _site( \ level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, broadTag, narrowTag, once);\ if (_site.shouldLog()) \ @@ -252,7 +252,7 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG; LLError::End(); \ LLError::Log::flush(_out, _site); \ } \ - } + } while(0) // DEPRECATED: Use the new macros that allow tags and *look* like macros. #define lldebugs lllog(LLError::LEVEL_DEBUG, NULL, NULL, false) diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 8f70726a9e..eca7e922fd 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -34,6 +34,7 @@ #define LL_LLSTRING_H #include +#include #include #include #include "llsd.h" diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index 4d03c4d40d..4737421289 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -124,9 +124,42 @@ LLOSInfo::LLOSInfo() : } else if(osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0) { - if(osvi.wProductType == VER_NT_WORKSTATION) - mOSStringSimple = "Microsoft Windows Vista "; - else mOSStringSimple = "Microsoft Windows Vista Server "; + ///get native system info if available.. + typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO); ///function pointer for loading GetNativeSystemInfo + SYSTEM_INFO si; //System Info object file contains architecture info + PGNSI pGNSI; //pointer object + ZeroMemory(&si, sizeof(SYSTEM_INFO)); //zero out the memory in information + pGNSI = (PGNSI) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo"); //load kernel32 get function + if(NULL != pGNSI) //check if it has failed + pGNSI(&si); //success + else + GetSystemInfo(&si); //if it fails get regular system info + //(Warning: If GetSystemInfo it may result in incorrect information in a WOW64 machine, if the kernel fails to load) + + //msdn microsoft finds 32 bit and 64 bit flavors this way.. + //http://msdn.microsoft.com/en-us/library/ms724429(VS.85).aspx (example code that contains quite a few more flavors + //of windows than this code does (in case it is needed for the future) + if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 ) //check for 64 bit + { + if(osvi.wProductType == VER_NT_WORKSTATION) + mOSStringSimple = "Microsoft Windows Vista 64-bit "; + else + mOSStringSimple = "Microsoft Windows Vista Server 64-bit "; + } + else if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL ) + { + if(osvi.wProductType == VER_NT_WORKSTATION) + mOSStringSimple = "Microsoft Windows Vista 32-bit "; + else + mOSStringSimple = "Microsoft Windows Vista Server 32-bit "; + } + else // PROCESSOR_ARCHITECTURE_IA64 || PROCESSOR_ARCHITECTURE_UNKNOWN not checked + { + if(osvi.wProductType == VER_NT_WORKSTATION) + mOSStringSimple = "Microsoft Windows Vista "; + else + mOSStringSimple = "Microsoft Windows Vista Server "; + } } else // Use the registry on early versions of Windows NT. { diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 488f3bf78d..9bbc55509d 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -159,7 +159,7 @@ U8* LLImageBase::allocateData(S32 size) size = mWidth * mHeight * mComponents; if (size <= 0) { - llerrs << llformat("LLImageBase::allocateData called with bad dimentions: %dx%dx%d",mWidth,mHeight,mComponents) << llendl; + llerrs << llformat("LLImageBase::allocateData called with bad dimensions: %dx%dx%d",mWidth,mHeight,mComponents) << llendl; } } else if (size <= 0 || (size > 4096*4096*16 && sSizeOverride == FALSE)) diff --git a/indra/llinventory/llparcel.cpp b/indra/llinventory/llparcel.cpp index e48690908e..f208d82084 100644 --- a/indra/llinventory/llparcel.cpp +++ b/indra/llinventory/llparcel.cpp @@ -706,7 +706,6 @@ void LLParcel::packMessage(LLSD& msg) msg["category"] = (U8)mCategory; msg["auth_buyer_id"] = mAuthBuyerID; msg["snapshot_id"] = mSnapshotID; - msg["snapshot_id"] = mSnapshotID; msg["user_location"] = ll_sd_from_vector3(mUserLocation); msg["user_look_at"] = ll_sd_from_vector3(mUserLookAt); msg["landing_type"] = (U8)mLandingType; diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 5cc0a596fd..b8ef92f9a9 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -4273,7 +4273,7 @@ LLFaceID LLVolume::generateFaceMask() } break; default: - llerrs << "Unknown profile!" << llendl + llerrs << "Unknown profile!" << llendl; break; } diff --git a/indra/llmessage/lltemplatemessagebuilder.cpp b/indra/llmessage/lltemplatemessagebuilder.cpp index e6419807ff..6400310c46 100644 --- a/indra/llmessage/lltemplatemessagebuilder.cpp +++ b/indra/llmessage/lltemplatemessagebuilder.cpp @@ -728,9 +728,9 @@ static S32 buildBlock(U8* buffer, S32 buffer_size, const LLMessageBlock* templat // out gracefully from this function. XXXTBD llerrs << "buildBlock failed. " << "Attempted to pack " - << result + mvci.getSize() + << (result + mvci.getSize()) << " bytes into a buffer with size " - << buffer_size << "." << llendl + << buffer_size << "." << llendl; } } } diff --git a/indra/llmessage/lltemplatemessagereader.cpp b/indra/llmessage/lltemplatemessagereader.cpp index 8c9eb7ed42..6682575ca5 100644 --- a/indra/llmessage/lltemplatemessagereader.cpp +++ b/indra/llmessage/lltemplatemessagereader.cpp @@ -678,12 +678,7 @@ BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender // default to 0s. U32 size = mvci.getSize(); - std::vector data(size); - if(size) - { - // Nonsense test to get past GCC 4.3.1 bug with -O3 - memset(&(data[0]), 0, size); - } + std::vector data(size, 0); cur_data_block->addData(mvci.getName(), &(data[0]), size, mvci.getType()); } diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt index aac650bec9..5c13df9f81 100644 --- a/indra/llrender/CMakeLists.txt +++ b/indra/llrender/CMakeLists.txt @@ -9,6 +9,7 @@ include(LLCommon) include(LLImage) include(LLMath) include(LLRender) +include(LLVFS) include(LLWindow) include(LLXML) include(LLVFS) @@ -19,6 +20,7 @@ include_directories( ${LLIMAGE_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} ${LLRENDER_INCLUDE_DIRS} + ${LLVFS_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} ${LLVFS_INCLUDE_DIRS} diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp index 754d90c854..08a96b4e31 100644 --- a/indra/llrender/llcubemap.cpp +++ b/indra/llrender/llcubemap.cpp @@ -106,7 +106,7 @@ void LLCubeMap::initGL() } else { - llwarns << "Using cube map without extension!" << llendl + llwarns << "Using cube map without extension!" << llendl; } } diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index 44e997340e..1246cfc44b 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -364,7 +364,7 @@ BOOL LLFontFreetype::addChar(llwchar wch) const glyph_index = FT_Get_Char_Index(mFTFace, wch); if (glyph_index == 0) { - //llinfos << "Trying to add glyph from fallback font!" << llendl + //llinfos << "Trying to add glyph from fallback font!" << llendl; font_vector_t::const_iterator iter; for(iter = mFallbackFonts.begin(); iter != mFallbackFonts.end(); iter++) { @@ -534,11 +534,10 @@ void LLFontFreetype::renderGlyph(U32 glyph_index) const void LLFontFreetype::reset(F32 vert_dpi, F32 horz_dpi) { resetBitmapCache(); + loadFace(mName, mPointSize, vert_dpi ,horz_dpi, mFontBitmapCachep->getNumComponents(), mIsFallback); if (!mIsFallback) { // This is the head of the list - need to rebuild ourself and all fallbacks. - loadFace(mName, mPointSize, vert_dpi ,horz_dpi, mFontBitmapCachep->getNumComponents(), mIsFallback); - if (mFallbackFonts.empty()) { llwarns << "LLFontGL::reset(), no fallback fonts present" << llendl; diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index f7bab3de67..2d7b9760e8 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -44,6 +44,7 @@ #include "llstl.h" #include "v4color.h" #include "lltexture.h" +#include "lldir.h" // Third party library includes #include diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index c7178a5552..f33ae7d8f0 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -53,8 +53,6 @@ # include "GL/glxext.h" //# define GLH_EXT_GET_PROC_ADDRESS(p) glXGetProcAddressARB((const GLubyte*)(p)) # define GLH_EXT_GET_PROC_ADDRESS(p) glXGetProcAddress((const GLubyte*)(p)) -// the X headers define 'Status'. Undefine to avoid confusion. -#undef Status // The __APPLE__ kludge is to make glh_extensions.h not symbol-clash horribly // This header is distributed with SL. You'll find it in linden/libraries/include/GL/ @@ -277,8 +275,6 @@ extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; // Use glXGetProcAddressARB instead of glXGetProcAddress - the ARB symbol // is considered 'legacy' but works on more machines. # define GLH_EXT_GET_PROC_ADDRESS(p) glXGetProcAddressARB((const GLubyte*)(p)) -// Whee, the X headers define 'Status'. Undefine to avoid confusion. -#undef Status #endif // LL_LINUX && !LL_MESA_HEADLESS #if LL_LINUX && defined(WINGDIAPI) diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index dd64d753c7..e5fea5b995 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -428,7 +428,7 @@ void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents) // Check if dimensions are a power of two! if (!checkSize(width,height)) { - llerrs << llformat("Texture has non power of two dimention: %dx%d",width,height) << llendl; + llerrs << llformat("Texture has non power of two dimension: %dx%d",width,height) << llendl; } if (mTexName) diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 693ea5bb45..0db515ab41 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -148,6 +148,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) mBgImage( p.background_image ), mBgImageDisabled( p.background_image_disabled ), mBgImageFocused( p.background_image_focused ), + mHaveHistory(FALSE), mReplaceNewlinesWithSpaces( TRUE ), mLabel(p.label), mCursorColor(p.cursor_color()), @@ -164,13 +165,8 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) mTripleClickTimer.reset(); setText(p.default_text()); - // line history support: - // - initialize line history list - mLineHistory.insert( mLineHistory.end(), "" ); - // - disable line history by default - mHaveHistory = FALSE; - // - reset current history line pointer - mCurrentHistoryLine = 0; + // Initialize current history line iterator + mCurrentHistoryLine = mLineHistory.begin(); LLRect border_rect(getLocalRect()); // adjust for gl line drawing glitch @@ -278,16 +274,31 @@ void LLLineEditor::updateHistory() // reset current history line number. // Be sure only to remember lines that are not empty and that are // different from the last on the list. - if( mHaveHistory && mText.length() && ( mLineHistory.empty() || getText() != mLineHistory.back() ) ) + if( mHaveHistory && getLength() ) { - // discard possible empty line at the end of the history - // inserted by setText() - if( !mLineHistory.back().length() ) + if( !mLineHistory.empty() ) { - mLineHistory.pop_back(); + // When not empty, last line of history should always be blank. + if( mLineHistory.back().empty() ) + { + // discard the empty line + mLineHistory.pop_back(); + } + else + { + LL_WARNS("") << "Last line of history was not blank." << LL_ENDL; + } } - mLineHistory.insert( mLineHistory.end(), getText() ); - mCurrentHistoryLine = mLineHistory.size() - 1; + + // Add text to history, ignoring duplicates + if( mLineHistory.empty() || getText() != mLineHistory.back() ) + { + mLineHistory.push_back( getText() ); + } + + // Restore the blank line and set mCurrentHistoryLine to point at it + mLineHistory.push_back( "" ); + mCurrentHistoryLine = mLineHistory.end() - 1; } } @@ -357,11 +368,8 @@ void LLLineEditor::setText(const LLStringExplicit &new_text) } setCursor(llmin((S32)mText.length(), getCursor())); - // Newly set text goes always in the last line of history. - // Possible empty strings (as with chat line) will be deleted later. - mLineHistory.insert( mLineHistory.end(), new_text ); // Set current history line to end of history. - mCurrentHistoryLine = mLineHistory.size() - 1; + mCurrentHistoryLine = mLineHistory.end() - 1; mPrevText = mText; } @@ -1254,9 +1262,9 @@ BOOL LLLineEditor::handleSpecialKey(KEY key, MASK mask) case KEY_UP: if( mHaveHistory && ( MASK_CONTROL == mask ) ) { - if( mCurrentHistoryLine > 0 ) + if( mCurrentHistoryLine > mLineHistory.begin() ) { - mText.assign( mLineHistory[ --mCurrentHistoryLine ] ); + mText.assign( *(--mCurrentHistoryLine) ); setCursor(llmin((S32)mText.length(), getCursor())); } else @@ -1271,9 +1279,9 @@ BOOL LLLineEditor::handleSpecialKey(KEY key, MASK mask) case KEY_DOWN: if( mHaveHistory && ( MASK_CONTROL == mask ) ) { - if( !mLineHistory.empty() && mCurrentHistoryLine < mLineHistory.size() - 1 ) + if( !mLineHistory.empty() && mCurrentHistoryLine < mLineHistory.end() - 1 ) { - mText.assign( mLineHistory[ ++mCurrentHistoryLine ] ); + mText.assign( *(++mCurrentHistoryLine) ); setCursor(llmin((S32)mText.length(), getCursor())); } else @@ -2291,14 +2299,20 @@ BOOL LLLineEditor::hasPreeditString() const void LLLineEditor::resetPreedit() { - if (hasPreeditString()) + if (hasSelection()) { - if (hasSelection()) + if (hasPreeditString()) { llwarns << "Preedit and selection!" << llendl; deselect(); } - + else + { + deleteSelection(); + } + } + if (hasPreeditString()) + { const S32 preedit_pos = mPreeditPositions.front(); mText.erase(preedit_pos, mPreeditPositions.back() - preedit_pos); mText.insert(preedit_pos, mPreeditOverwrittenWString); diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index 48d68b9935..6e81969f00 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -286,8 +286,9 @@ protected: // line history support: BOOL mHaveHistory; // flag for enabled line history - std::vector mLineHistory; // line history storage - U32 mCurrentHistoryLine; // currently browsed history line + typedef std::vector line_history_t; + line_history_t mLineHistory; // line history storage + line_history_t::iterator mCurrentHistoryLine; // currently browsed history line LLViewBorder* mBorder; const LLFontGL* mGLFont; diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 14bee0465c..cf013efca0 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -279,47 +279,7 @@ BOOL LLMenuItemGL::addToAcceleratorList(std::list *listp) // the current accelerator key and mask to the provided string. void LLMenuItemGL::appendAcceleratorString( std::string& st ) const { - // break early if this is a silly thing to do. - if( KEY_NONE == mAcceleratorKey ) - { - return; - } - - // Append any masks -#ifdef LL_DARWIN - // Standard Mac names for modifier keys in menu equivalents - // We could use the symbol characters, but they only exist in certain fonts. - if( mAcceleratorMask & MASK_CONTROL ) - { - if ( mAcceleratorMask & MASK_MAC_CONTROL ) - { - st.append( "Ctrl-" ); - } - else - { - st.append( "Cmd-" ); // Symbol would be "\xE2\x8C\x98" - } - } - if( mAcceleratorMask & MASK_ALT ) - st.append( "Opt-" ); // Symbol would be "\xE2\x8C\xA5" - if( mAcceleratorMask & MASK_SHIFT ) - st.append( "Shift-" ); // Symbol would be "\xE2\x8C\xA7" -#else - if( mAcceleratorMask & MASK_CONTROL ) - st.append( "Ctrl-" ); - if( mAcceleratorMask & MASK_ALT ) - st.append( "Alt-" ); - if( mAcceleratorMask & MASK_SHIFT ) - st.append( "Shift-" ); -#endif - - std::string keystr = LLKeyboard::stringFromKey( mAcceleratorKey ); - if ((mAcceleratorMask & MASK_NORMALKEYS) && - (keystr[0] == '-' || keystr[0] == '=')) - { - st.append( " " ); - } - st.append( keystr ); + st = LLKeyboard::stringFromAccelerator( mAcceleratorMask, mAcceleratorKey ); LL_DEBUGS("HotKeys") << "appendAcceleratorString: " << st << LL_ENDL; } diff --git a/indra/llui/llresmgr.cpp b/indra/llui/llresmgr.cpp index a4e23a605b..ed870d46d5 100644 --- a/indra/llui/llresmgr.cpp +++ b/indra/llui/llresmgr.cpp @@ -279,6 +279,14 @@ std::string LLResMgr::getMonetaryString( S32 input ) const void LLResMgr::getIntegerString( std::string& output, S32 input ) const { + // handle special case of input value being zero + if (input == 0) + { + output = "0"; + return; + } + + // *NOTE: this method does not handle negative input integers correctly S32 fraction = 0; std::string fraction_string; S32 remaining_count = input; diff --git a/indra/llui/lluistring.h b/indra/llui/lluistring.h index aedeca27cb..195f21a6a7 100644 --- a/indra/llui/lluistring.h +++ b/indra/llui/lluistring.h @@ -51,9 +51,9 @@ // llinfos << mMessage.getString() << llendl; // outputs "Welcome Steve to Second Life" // mMessage.setArg("[USERNAME]", "Joe"); // llinfos << mMessage.getString() << llendl; // outputs "Welcome Joe to Second Life" -// mMessage = "Recepci￳n a la [SECONDLIFE] [USERNAME]" +// mMessage = "Bienvenido a la [SECONDLIFE] [USERNAME]" // mMessage.setArg("[SECONDLIFE]", "Segunda Vida"); -// llinfos << mMessage.getString() << llendl; // outputs "Recepci￳n a la Segunda Vida Joe" +// llinfos << mMessage.getString() << llendl; // outputs "Bienvenido a la Segunda Vida Joe" // Implementation Notes: // Attempting to have operator[](const std::string& s) return mArgs[s] fails because we have diff --git a/indra/llvfs/CMakeLists.txt b/indra/llvfs/CMakeLists.txt index cc0297e3dc..0de3fa33f9 100644 --- a/indra/llvfs/CMakeLists.txt +++ b/indra/llvfs/CMakeLists.txt @@ -23,6 +23,7 @@ set(llvfs_HEADER_FILES CMakeLists.txt lldir.h + lldirguard.h lllfsthread.h llpidlock.h llvfile.h diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index 745e53c980..781321e5e4 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -404,6 +404,12 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd prefix = getExecutableDir(); break; + case LL_PATH_FONTS: + prefix = getAppRODataDir(); + prefix += mDirDelimiter; + prefix += "fonts"; + break; + default: llassert(0); } @@ -419,6 +425,11 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd filename = subdir1 + mDirDelimiter + filename; } + if (prefix.empty()) + { + llwarns << "prefix is empty, possible bad filename" << llendl; + } + std::string expanded_filename; if (!filename.empty()) { @@ -673,11 +684,6 @@ void LLDir::dumpCurrentDirectories() LL_DEBUGS2("AppInit","Directories") << " CAFile: " << getCAFile() << LL_ENDL; LL_DEBUGS2("AppInit","Directories") << " SkinBaseDir: " << getSkinBaseDir() << LL_ENDL; LL_DEBUGS2("AppInit","Directories") << " SkinDir: " << getSkinDir() << LL_ENDL; - -#if LL_LIBXUL_ENABLED - LL_DEBUGS2("AppInit","Directories") << " HTML Path: " << getExpandedFilename( LL_PATH_HTML, "" ) << llendl; - LL_DEBUGS2("AppInit","Directories") << " Mozilla Profile Path: " << getExpandedFilename( LL_PATH_MOZILLA_PROFILE, "" ) << llendl; -#endif } diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h index 6c9fea6b6a..07c814769e 100644 --- a/indra/llvfs/lldir.h +++ b/indra/llvfs/lldir.h @@ -60,6 +60,7 @@ typedef enum ELLPath // LL_PATH_HTML = 16, LL_PATH_EXECUTABLE = 16, LL_PATH_DEFAULT_SKIN = 17, + LL_PATH_FONTS = 18, LL_PATH_LAST } ELLPath; diff --git a/indra/llvfs/lldir_mac.cpp b/indra/llvfs/lldir_mac.cpp index 346f7dd8ed..7bc6f63e1f 100644 --- a/indra/llvfs/lldir_mac.cpp +++ b/indra/llvfs/lldir_mac.cpp @@ -68,7 +68,8 @@ static void CFStringRefToLLString(CFStringRef stringRef, std::string &llString, { if (stringRef) { - long bufferSize = CFStringGetLength(stringRef) + 1; + long stringSize = CFStringGetLength(stringRef) + 1; + long bufferSize = CFStringGetMaximumSizeForEncoding(stringSize,kCFStringEncodingUTF8); char* buffer = new char[bufferSize]; memset(buffer, 0, bufferSize); if (CFStringGetCString(stringRef, buffer, bufferSize, kCFStringEncodingUTF8)) diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp index 3e302764de..4c376f11a5 100644 --- a/indra/llvfs/lldir_win32.cpp +++ b/indra/llvfs/lldir_win32.cpp @@ -121,17 +121,22 @@ LLDir_Win32::LLDir_Win32() GetCurrentDirectory(MAX_PATH, w_str); mExecutableDir = utf16str_to_utf8str(llutf16string(w_str)); #endif - - // When running in a dev tree, app_settings is under indra/newview/ - // but in production it is under Program Files/SecondLife/ - // Attempt to detect which one we're using. JC - if (mExecutableDir.find("indra") != std::string::npos) - mAppRODataDir = getCurPath(); - else - mAppRODataDir = mExecutableDir; + + mAppRODataDir = "."; mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins"; + if (mExecutableDir.find("indra") == std::string::npos) + { + // Running from installed directory. Make sure current + // directory isn't something crazy (e.g. if invoking from + // command line). + SetCurrentDirectory(utf8str_to_utf16str(mExecutableDir).c_str()); + GetCurrentDirectory(MAX_PATH, w_str); + mWorkingDir = utf16str_to_utf8str(llutf16string(w_str)); + } + llinfos << "mAppRODataDir = " << mAppRODataDir << llendl; + // Build the default cache directory mDefaultCacheDir = buildSLOSCacheDir(); diff --git a/indra/llvfs/lldirguard.h b/indra/llvfs/lldirguard.h new file mode 100644 index 0000000000..85366120d8 --- /dev/null +++ b/indra/llvfs/lldirguard.h @@ -0,0 +1,78 @@ +/** + * @file lldirguard.h + * @brief Protect working directory from being changed in scope. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 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$ + */ + +#ifndef LL_DIRGUARD_H +#define LL_DIRGUARD_H + +#include "linden_common.h" +#include "llerror.h" + +#if LL_WINDOWS +class LLDirectoryGuard +{ +public: + LLDirectoryGuard() + { + mOrigDirLen = GetCurrentDirectory(MAX_PATH, mOrigDir); + } + + ~LLDirectoryGuard() + { + mFinalDirLen = GetCurrentDirectory(MAX_PATH, mFinalDir); + if ((mOrigDirLen!=mFinalDirLen) || + (wcsncmp(mOrigDir,mFinalDir,mOrigDirLen)!=0)) + { + // Dir has changed + std::string mOrigDirUtf8 = utf16str_to_utf8str(llutf16string(mOrigDir)); + std::string mFinalDirUtf8 = utf16str_to_utf8str(llutf16string(mFinalDir)); + llinfos << "Resetting working dir from " << mFinalDirUtf8 << " to " << mOrigDirUtf8 << llendl; + SetCurrentDirectory(mOrigDir); + } + } + +private: + TCHAR mOrigDir[MAX_PATH]; + DWORD mOrigDirLen; + TCHAR mFinalDir[MAX_PATH]; + DWORD mFinalDirLen; +}; +#else // No-op outside Windows. +class LLDirectoryGuard +{ +public: + LLDirectoryGuard() {} + ~LLDirectoryGuard() {} +}; +#endif + + +#endif diff --git a/indra/llwindow/llkeyboard.cpp b/indra/llwindow/llkeyboard.cpp index f0f618aef1..16cbf815e0 100644 --- a/indra/llwindow/llkeyboard.cpp +++ b/indra/llwindow/llkeyboard.cpp @@ -36,7 +36,6 @@ #include "llwindowcallbacks.h" - // // Globals // @@ -46,6 +45,8 @@ LLKeyboard *gKeyboard = NULL; //static std::map LLKeyboard::sKeysToNames; std::map LLKeyboard::sNamesToKeys; +LLKeyStringTranslatorFunc* LLKeyboard::mStringTranslator = NULL; // Used for l10n + PC/Mac/Linux accelerator labeling + // // Class Implementation @@ -346,6 +347,65 @@ std::string LLKeyboard::stringFromKey(KEY key) } +//static +std::string LLKeyboard::stringFromAccelerator( MASK accel_mask, KEY key ) +{ + std::string res; + + // break early if this is a silly thing to do. + if( KEY_NONE == key ) + { + return res; + } + + LLKeyStringTranslatorFunc *trans = gKeyboard->mStringTranslator; + + if( trans == NULL ) + { + llerrs << "No mKeyStringTranslator" << llendl; + return res; + } + + // Append any masks +#ifdef LL_DARWIN + // Standard Mac names for modifier keys in menu equivalents + // We could use the symbol characters, but they only exist in certain fonts. + if( accel_mask & MASK_CONTROL ) + { + if ( accel_mask & MASK_MAC_CONTROL ) + { + res.append( trans("accel-mac-control") ); + } + else + { + res.append( trans("accel-mac-command") ); // Symbol would be "\xE2\x8C\x98" + } + } + if( accel_mask & MASK_ALT ) + res.append( trans("accel-mac-option") ); // Symbol would be "\xE2\x8C\xA5" + if( accel_mask & MASK_SHIFT ) + res.append( trans("accel-mac-shift") ); // Symbol would be "\xE2\x8C\xA7" +#else + if( accel_mask & MASK_CONTROL ) + res.append( trans("accel-win-control") ); + if( accel_mask & MASK_ALT ) + res.append( trans("accel-win-alt") ); + if( accel_mask & MASK_SHIFT ) + res.append( trans("accel-win-shift") ); +#endif + std::string key_string = LLKeyboard::stringFromKey(key); + if ((accel_mask & MASK_NORMALKEYS) && + (key_string[0] == '-' || key_string[0] == '=' || key_string[0] == '+')) + { + res.append( " " ); + } + + std::string keystr = stringFromKey( key ); + res.append( keystr ); + + return res; +} + //static BOOL LLKeyboard::maskFromString(const std::string& str, MASK *mask) @@ -396,3 +456,10 @@ BOOL LLKeyboard::maskFromString(const std::string& str, MASK *mask) return FALSE; } } + + +//static +void LLKeyboard::setStringTranslatorFunc( LLKeyStringTranslatorFunc *trans_func ) +{ + mStringTranslator = trans_func; +} diff --git a/indra/llwindow/llkeyboard.h b/indra/llwindow/llkeyboard.h index 0261bcbeb3..d545034070 100644 --- a/indra/llwindow/llkeyboard.h +++ b/indra/llwindow/llkeyboard.h @@ -47,7 +47,8 @@ enum EKeystate }; typedef void (*LLKeyFunc)(EKeystate keystate); - +typedef std::string (LLKeyStringTranslatorFunc)(const char *label); + enum EKeyboardInsertMode { LL_KIM_INSERT, @@ -111,7 +112,7 @@ public: static BOOL maskFromString(const std::string& str, MASK *mask); // False on failure static BOOL keyFromString(const std::string& str, KEY *key); // False on failure static std::string stringFromKey(KEY key); - + static std::string stringFromAccelerator( MASK accel_mask, KEY key ); e_numpad_distinct getNumpadDistinct() { return mNumpadDistinct; } void setNumpadDistinct(e_numpad_distinct val) { mNumpadDistinct = val; } @@ -119,6 +120,8 @@ public: F32 getKeyElapsedTime( KEY key ); // Returns time in seconds since key was pressed. S32 getKeyElapsedFrameCount( KEY key ); // Returns time in frames since key was pressed. + static void setStringTranslatorFunc( LLKeyStringTranslatorFunc *trans_func ); + protected: void addKeyName(KEY key, const std::string& name); @@ -136,6 +139,8 @@ protected: KEY mCurTranslatedKey; KEY mCurScanKey; // Used during the scanKeyboard() + static LLKeyStringTranslatorFunc* mStringTranslator; // Used for l10n + PC/Mac/Linux accelerator labeling + e_numpad_distinct mNumpadDistinct; EKeyboardInsertMode mInsertMode; diff --git a/indra/llwindow/llkeyboardwin32.cpp b/indra/llwindow/llkeyboardwin32.cpp index ea11e0537e..35a3e7621a 100644 --- a/indra/llwindow/llkeyboardwin32.cpp +++ b/indra/llwindow/llkeyboardwin32.cpp @@ -65,7 +65,7 @@ LLKeyboardWin32::LLKeyboardWin32() // numpad number keys for (cur_char = 0x60; cur_char <= 0x69; cur_char++) { - mTranslateKeyMap[cur_char] = (KEY)('0' + (0x60 - cur_char)); + mTranslateKeyMap[cur_char] = (KEY)('0' + (cur_char - 0x60)); } diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 7137c93476..96e5a1b7ca 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -1389,11 +1389,11 @@ void LLWindowMacOSX::setMouseClipping( BOOL b ) if(b) { - // llinfos << "setMouseClipping(TRUE)" << llendl + // llinfos << "setMouseClipping(TRUE)" << llendl; } else { - // llinfos << "setMouseClipping(FALSE)" << llendl + // llinfos << "setMouseClipping(FALSE)" << llendl; } adjustCursorDecouple(); @@ -1411,7 +1411,7 @@ BOOL LLWindowMacOSX::setCursorPosition(const LLCoordWindow position) CGPoint newPosition; - // llinfos << "setCursorPosition(" << screen_pos.mX << ", " << screen_pos.mY << ")" << llendl + // llinfos << "setCursorPosition(" << screen_pos.mX << ", " << screen_pos.mY << ")" << llendl; newPosition.x = screen_pos.mX; newPosition.y = screen_pos.mY; diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index 00a8d429ba..9f03c8f695 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -70,7 +70,7 @@ extern BOOL gDebugWindowProc; const S32 MAX_NUM_RESOLUTIONS = 200; // static variable for ATI mouse cursor crash work-around: -static bool ATIbug = false; +static bool ATIbug = false; // // LLWindowSDL @@ -219,8 +219,7 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks, #endif // LL_X11 #if LL_GTK - // We MUST be the first to initialize GTK, i.e. we have to beat - // our embedded Mozilla to the punch so that GTK doesn't get badly + // We MUST be the first to initialize GTK so that GTK doesn't get badly // initialized with a non-C locale and cause lots of serious random // weirdness. ll_try_gtk_init(); @@ -674,12 +673,12 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B glGetIntegerv(GL_DEPTH_BITS, &depthBits); glGetIntegerv(GL_STENCIL_BITS, &stencilBits); - llinfos << "GL buffer:" << llendl - llinfos << " Red Bits " << S32(redBits) << llendl - llinfos << " Green Bits " << S32(greenBits) << llendl - llinfos << " Blue Bits " << S32(blueBits) << llendl - llinfos << " Alpha Bits " << S32(alphaBits) << llendl - llinfos << " Depth Bits " << S32(depthBits) << llendl + llinfos << "GL buffer:" << llendl; + llinfos << " Red Bits " << S32(redBits) << llendl; + llinfos << " Green Bits " << S32(greenBits) << llendl; + llinfos << " Blue Bits " << S32(blueBits) << llendl; + llinfos << " Alpha Bits " << S32(alphaBits) << llendl; + llinfos << " Depth Bits " << S32(depthBits) << llendl; llinfos << " Stencil Bits " << S32(stencilBits) << llendl; GLint colorBits = redBits + greenBits + blueBits + alphaBits; @@ -2252,6 +2251,7 @@ BOOL LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b) GtkColorSelection *colorsel = GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG(win)->colorsel); GdkColor color, orig_color; + orig_color.pixel = 0; orig_color.red = guint16(65535 * *r); orig_color.green= guint16(65535 * *g); orig_color.blue = guint16(65535 * *b); diff --git a/indra/llxuixml/lltrans.h b/indra/llxuixml/lltrans.h index 79df5802e5..856b9e04fc 100644 --- a/indra/llxuixml/lltrans.h +++ b/indra/llxuixml/lltrans.h @@ -103,6 +103,11 @@ public: return findString(result, xml_desc, empty); } + static std::string getKeyboardString(const char* keystring) + { + // These map directly - no need to specialize + return getString( ll_safe_string(keystring) ); + } // get the default args static const LLStringUtil::format_map_t& getDefaultArgs() diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index b9e5664ff7..c402c3979a 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1025,7 +1025,7 @@ endif (DARWIN) if (LINUX) LIST(APPEND viewer_SOURCE_FILES llappviewerlinux.cpp) LIST(APPEND viewer_SOURCE_FILES llappviewerlinux_api_dbus.cpp) - LIST(APPEND CMAKE_EXE_LINKER_FLAGS -Wl,--as-needed) + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed") set(viewer_LIBRARIES Xinerama @@ -1113,7 +1113,9 @@ if (WINDOWS) SOURCE_GROUP("Resource Files" FILES ${viewer_RESOURCE_FILES}) - list(APPEND viewer_SOURCE_FILES ${viewer_RESOURCE_FILES}) + if (NOT STANDALONE) + list(APPEND viewer_SOURCE_FILES ${viewer_RESOURCE_FILES}) + endif (NOT STANDALONE) find_library(DINPUT_LIBRARY dinput8 ${DIRECTX_LIBRARY_DIR}) find_library(DXGUID_LIBRARY dxguid ${DIRECTX_LIBRARY_DIR}) @@ -1223,8 +1225,9 @@ source_group("Character File" FILES ${viewer_CHARACTER_FILES}) set_source_files_properties(${viewer_CHARACTER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE) - -list(APPEND viewer_SOURCE_FILES ${viewer_CHARACTER_FILES}) +if (NOT STANDALONE) + list(APPEND viewer_SOURCE_FILES ${viewer_CHARACTER_FILES}) +endif (NOT STANDALONE) if (WINDOWS) file(GLOB viewer_INSTALLER_FILES installers/windows/*.nsi) diff --git a/indra/newview/app_settings/keywords.ini b/indra/newview/app_settings/keywords.ini index 5d52158298..544f1c598e 100644 --- a/indra/newview/app_settings/keywords.ini +++ b/indra/newview/app_settings/keywords.ini @@ -459,6 +459,7 @@ PARCEL_FLAG_ALLOW_LANDMARK Used with llGetParcelFlags to find if a parcel allo PARCEL_FLAG_ALLOW_TERRAFORM Used with llGetParcelFlags to find if a parcel allows anyone to terraform the land PARCEL_FLAG_ALLOW_DAMAGE Used with llGetParcelFlags to find if a parcel allows damage PARCEL_FLAG_ALLOW_CREATE_OBJECTS Used with llGetParcelFlags to find if a parcel allows anyone to create objects +PARCEL_FLAG_ALLOW_CREATE_GROUP_OBJECTS Used with llGetParcelFlags to find if a parcel allows group members or objects to create objects PARCEL_FLAG_USE_ACCESS_GROUP Used with llGetParcelFlags to find if a parcel limits access to a group PARCEL_FLAG_USE_ACCESS_LIST Used with llGetParcelFlags to find if a parcel limits access to a list of residents PARCEL_FLAG_USE_BAN_LIST Used with llGetParcelFlags to find if a parcel uses a ban list diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index d05fd955db..467e1e8342 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1599,7 +1599,7 @@ Cursor3D Comment - Tread Joystick values as absolute positions (not deltas). + Treat Joystick values as absolute positions (not deltas). Persist 1 Type @@ -3851,6 +3851,17 @@ Value + JoystickMouselookYaw + + Comment + Pass joystick yaw to scripts in Mouselook. + Persist + 1 + Type + Boolean + Value + 1 + JoystickRunThreshold Comment @@ -4158,7 +4169,7 @@ Type Boolean Value - 0 + 1 LipSyncOoh diff --git a/indra/newview/installers/darwin/firstlook-dmg/_DS_Store b/indra/newview/installers/darwin/firstlook-dmg/_DS_Store index 6c5a3f3452..408a4d4992 100644 Binary files a/indra/newview/installers/darwin/firstlook-dmg/_DS_Store and b/indra/newview/installers/darwin/firstlook-dmg/_DS_Store differ diff --git a/indra/newview/installers/darwin/publicnightly-dmg/_DS_Store b/indra/newview/installers/darwin/publicnightly-dmg/_DS_Store index 6a91b38d6d..b901e46b65 100644 Binary files a/indra/newview/installers/darwin/publicnightly-dmg/_DS_Store and b/indra/newview/installers/darwin/publicnightly-dmg/_DS_Store differ diff --git a/indra/newview/installers/darwin/releasecandidate-dmg/_DS_Store b/indra/newview/installers/darwin/releasecandidate-dmg/_DS_Store index a8b757372e..309c8adaaa 100644 Binary files a/indra/newview/installers/darwin/releasecandidate-dmg/_DS_Store and b/indra/newview/installers/darwin/releasecandidate-dmg/_DS_Store differ diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 08681db6cb..41aeeee82a 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -330,7 +330,7 @@ LLAgent::LLAgent() : mLeftKey(0), mUpKey(0), mYawKey(0.f), - mPitchKey(0), + mPitchKey(0.f), mOrbitLeftKey(0.f), mOrbitRightKey(0.f), @@ -723,15 +723,15 @@ void LLAgent::moveYaw(F32 mag, bool reset_view) //----------------------------------------------------------------------------- // movePitch() //----------------------------------------------------------------------------- -void LLAgent::movePitch(S32 direction) +void LLAgent::movePitch(F32 mag) { - setKey(direction, mPitchKey); + mPitchKey = mag; - if (direction > 0) + if (mag > 0) { - setControlFlags(AGENT_CONTROL_PITCH_POS ); + setControlFlags(AGENT_CONTROL_PITCH_POS); } - else if (direction < 0) + else if (mag < 0) { setControlFlags(AGENT_CONTROL_PITCH_NEG); } @@ -2509,10 +2509,10 @@ void LLAgent::propagate(const F32 dt) // handle rotation based on keyboard levels const F32 YAW_RATE = 90.f * DEG_TO_RAD; // radians per second - yaw( YAW_RATE * mYawKey * dt ); + yaw(YAW_RATE * mYawKey * dt); const F32 PITCH_RATE = 90.f * DEG_TO_RAD; // radians per second - pitch(PITCH_RATE * (F32) mPitchKey * dt); + pitch(PITCH_RATE * mPitchKey * dt); // handle auto-land behavior if (mAvatarObject.notNull()) @@ -2537,7 +2537,7 @@ void LLAgent::propagate(const F32 dt) mLeftKey = 0; mUpKey = 0; mYawKey = 0.f; - mPitchKey = 0; + mPitchKey = 0.f; } //----------------------------------------------------------------------------- @@ -3168,6 +3168,7 @@ void LLAgent::updateCamera() mFollowCam.copyParams(*current_cam); mFollowCam.setSubjectPositionAndRotation( mAvatarObject->getRenderPosition(), avatarRotationForFollowCam ); mFollowCam.update(); + LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true); } else { @@ -4245,7 +4246,7 @@ void LLAgent::changeCameraToCustomizeAvatar(BOOL avatar_animate, BOOL camera_ani { if(avatar_animate) { - // Remove any pitch from the avatar + // Remove any pitch from the avatar LLVector3 at = mFrameAgent.getAtAxis(); at.mV[VZ] = 0.f; at.normalize(); diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 5ca630f8d1..b334874e6e 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -471,7 +471,7 @@ private: S32 mLeftKey; S32 mUpKey; F32 mYawKey; - S32 mPitchKey; + F32 mPitchKey; //-------------------------------------------------------------------- // Movement from user input @@ -486,7 +486,7 @@ public: void moveLeftNudge(S32 direction); void moveUp(S32 direction); void moveYaw(F32 mag, bool reset_view = true); - void movePitch(S32 direction); + void movePitch(F32 mag); //-------------------------------------------------------------------- // Orbit diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index d47b994322..785179f7b3 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -686,8 +686,12 @@ bool LLAppViewer::init() LLUI::setupPaths(); LLTransUtil::parseStrings("strings.xml", default_trans_args); LLTransUtil::parseLanguageStrings("language_settings.xml"); - LLWeb::initClass(); // do this after LLUI + + // LLKeyboard relies on LLUI to know what some accelerator keys are called. + LLKeyboard::setStringTranslatorFunc( LLTrans::getKeyboardString ); + LLWeb::initClass(); // do this after LLUI + // Provide the text fields with callbacks for opening Urls LLUrlAction::setOpenURLCallback(&LLWeb::loadURL); LLUrlAction::setOpenURLInternalCallback(&LLWeb::loadURLInternal); @@ -1802,8 +1806,18 @@ bool LLAppViewer::initConfiguration() gSavedSettings.setString("VersionChannelName", LL_CHANNEL); #ifndef LL_RELEASE_FOR_DOWNLOAD - gSavedSettings.setBOOL("ShowConsoleWindow", TRUE); - gSavedSettings.setBOOL("AllowMultipleViewers", TRUE); + // provide developer build only overrides for these control variables that are not + // persisted to settings.xml + LLControlVariable* c = gSavedSettings.getControl("ShowConsoleWindow"); + if (c) + { + c->setValue(true, false); + } + c = gSavedSettings.getControl("AllowMultipleViewers"); + if (c) + { + c->setValue(true, false); + } #endif //*FIX:Mani - Set default to disabling watchdog mainloop diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp index ed291c16a8..d34bcb4a68 100644 --- a/indra/newview/llappviewerlinux.cpp +++ b/indra/newview/llappviewerlinux.cpp @@ -188,7 +188,7 @@ static inline BOOL do_basic_glibc_backtrace() for (i = 0; i < size; i++) { // the format of the StraceFile is very specific, to allow (kludgy) machine-parsing - fprintf(StraceFile, "%-3d ", i); + fprintf(StraceFile, "%-3lu ", (unsigned long)i); fprintf(StraceFile, "%-32s\t", "unknown"); fprintf(StraceFile, "%p ", stackarray[i]); fprintf(StraceFile, "%s\n", strings[i]); @@ -263,7 +263,7 @@ static inline BOOL do_elfio_glibc_backtrace() for (btpos = 0; btpos < btsize; ++btpos) { // the format of the StraceFile is very specific, to allow (kludgy) machine-parsing - fprintf(StraceFile, "%-3d ", btpos); + fprintf(StraceFile, "%-3ld ", (long)btpos); int symidx; for (symidx = 0; symidx < nSymNo; ++symidx) { @@ -354,7 +354,7 @@ bool LLAppViewerLinux::init() bool LLAppViewerLinux::restoreErrorTrap() { - // *NOTE:Mani there is a case for implementing this or the mac. + // *NOTE:Mani there is a case for implementing this on the mac. // Linux doesn't need it to my knowledge. return true; } @@ -727,8 +727,26 @@ std::string LLAppViewerLinux::generateSerialNumber() { char serial_md5[MD5HEX_STR_SIZE]; serial_md5[0] = 0; + std::string best; + std::string uuiddir("/dev/disk/by-uuid/"); - // TODO + // trawl /dev/disk/by-uuid looking for a good-looking UUID to grab + std::string this_name; + BOOL wrap = FALSE; + while (gDirUtilp->getNextFileInDir(uuiddir, "*", this_name, wrap)) + { + if (this_name.length() > best.length() || + (this_name.length() == best.length() && + this_name > best)) + { + // longest (and secondarily alphabetically last) so far + best = this_name; + } + } + + // we don't return the actual serial number, just a hash of it. + LLMD5 md5( reinterpret_cast(best.c_str()) ); + md5.hex_digest(serial_md5); return serial_md5; } diff --git a/indra/newview/llappviewerlinux.h b/indra/newview/llappviewerlinux.h index 365fcfeb6b..230c0dc24b 100644 --- a/indra/newview/llappviewerlinux.h +++ b/indra/newview/llappviewerlinux.h @@ -33,9 +33,12 @@ #ifndef LL_LLAPPVIEWERLINUX_H #define LL_LLAPPVIEWERLINUX_H -#if LL_DBUS_ENABLED extern "C" { # include +} + +#if LL_DBUS_ENABLED +extern "C" { # include # include } diff --git a/indra/newview/llappviewerlinux_api_dbus.cpp b/indra/newview/llappviewerlinux_api_dbus.cpp index ee160d0151..da67493e67 100644 --- a/indra/newview/llappviewerlinux_api_dbus.cpp +++ b/indra/newview/llappviewerlinux_api_dbus.cpp @@ -41,9 +41,9 @@ extern "C" { #include "apr_dso.h" } -#define DEBUGMSG(...) lldebugs << llformat(__VA_ARGS__) << llendl -#define INFOMSG(...) llinfos << llformat(__VA_ARGS__) << llendl -#define WARNMSG(...) llwarns << llformat(__VA_ARGS__) << llendl +#define DEBUGMSG(...) do { lldebugs << llformat(__VA_ARGS__) << llendl; } while(0) +#define INFOMSG(...) do { llinfos << llformat(__VA_ARGS__) << llendl; } while(0) +#define WARNMSG(...) do { llwarns << llformat(__VA_ARGS__) << llendl; } while(0) #define LL_DBUS_SYM(REQUIRED, DBUSSYM, RTN, ...) RTN (*ll##DBUSSYM)(__VA_ARGS__) = NULL #include "llappviewerlinux_api_dbus_syms_raw.inc" diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index 2b3939d92f..1282e437f2 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -159,15 +159,7 @@ bool LLAppViewerMacOSX::initParseCommandLine(LLCommandLineParser& clp) clp.addOptionDesc("psn", NULL, 1, "MacOSX process serial number"); clp.setCustomParser(parse_psn); - // First parse the command line, not often used on the mac. - if(clp.parseCommandLine(gArgC, gArgV) == false) - { - return false; - } - - // Now read in the args from arguments txt. - // Succesive calls to clp.parse... will NOT override earlier - // options. + // First read in the args from arguments txt. const char* filename = "arguments.txt"; llifstream ifs(filename, llifstream::binary); if (!ifs.is_open()) @@ -180,7 +172,14 @@ bool LLAppViewerMacOSX::initParseCommandLine(LLCommandLineParser& clp) { return false; } - + + // Then parse the user's command line, so that any --url arg can appear last + // Succesive calls to clp.parse... will NOT override earlier options. + if(clp.parseCommandLine(gArgC, gArgV) == false) + { + return false; + } + // Get the user's preferred language string based on the Mac OS localization mechanism. // To add a new localization: // go to the "Resources" section of the project diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index f56359afc3..21e17cc207 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -369,7 +369,7 @@ void LLDrawPoolWater::shade() LLVector3 light_dir; LLColor3 light_color; - if (gSky.getSunDirection().mV[2] > NIGHTTIME_ELEVATION_COS) + if (gSky.getSunDirection().mV[2] > LLSky::NIGHTTIME_ELEVATION_COS) { light_dir = gSky.getSunDirection(); light_dir.normVec(); diff --git a/indra/newview/llfloateranimpreview.cpp b/indra/newview/llfloateranimpreview.cpp index c062e6ccf2..55b7ed0c99 100644 --- a/indra/newview/llfloateranimpreview.cpp +++ b/indra/newview/llfloateranimpreview.cpp @@ -426,8 +426,8 @@ void LLFloaterAnimPreview::resetMotion() LLUUID base_id = mIDList[childGetValue("preview_base_anim").asString()]; avatarp->deactivateAllMotions(); - avatarp->startMotion(base_id, BASE_ANIM_TIME_OFFSET); avatarp->startMotion(mMotionID, 0.0f); + avatarp->startMotion(base_id, BASE_ANIM_TIME_OFFSET); childSetValue("playback_slider", 0.0f); // Set pose @@ -638,10 +638,10 @@ void LLFloaterAnimPreview::onCommitBaseAnim(LLUICtrl* ctrl, void* data) BOOL paused = avatarp->areAnimationsPaused(); // stop all other possible base motions - avatarp->stopMotion(ANIM_AGENT_STAND, TRUE); - avatarp->stopMotion(ANIM_AGENT_WALK, TRUE); - avatarp->stopMotion(ANIM_AGENT_SIT, TRUE); - avatarp->stopMotion(ANIM_AGENT_HOVER, TRUE); + avatarp->stopMotion(previewp->mIDList["Standing"], TRUE); + avatarp->stopMotion(previewp->mIDList["Walking"], TRUE); + avatarp->stopMotion(previewp->mIDList["Sitting"], TRUE); + avatarp->stopMotion(previewp->mIDList["Flying"], TRUE); previewp->resetMotion(); diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp index da2a4d9d93..cb0d304aa0 100644 --- a/indra/newview/llfloaterauction.cpp +++ b/indra/newview/llfloaterauction.cpp @@ -33,6 +33,7 @@ #include "llviewerprecompiledheaders.h" #include "llfloaterauction.h" +#include "llfloaterregioninfo.h" #include "lldir.h" #include "llgl.h" @@ -56,6 +57,7 @@ #include "llviewercontrol.h" #include "llui.h" #include "llrender.h" +#include "llsdutil.h" ///---------------------------------------------------------------------------- /// Local function declarations, constants, enums, and typedefs @@ -77,7 +79,9 @@ LLFloaterAuction::LLFloaterAuction(const LLSD& key) { // LLUICtrlFactory::getInstance()->buildFloater(this, "floater_auction.xml"); mCommitCallbackRegistrar.add("ClickSnapshot", boost::bind(&LLFloaterAuction::onClickSnapshot, this)); - mCommitCallbackRegistrar.add("ClickOK", boost::bind(&LLFloaterAuction::onClickOK, this)); + mCommitCallbackRegistrar.add("ClickSellToAnyone", boost::bind(&LLFloaterAuction::onClickSellToAnyone, this)); + mCommitCallbackRegistrar.add("ClickStartAuction", boost::bind(&LLFloaterAuction::onClickStartAuction, this)); + mCommitCallbackRegistrar.add("ClickResetParcel", boost::bind(&LLFloaterAuction::onClickResetParcel, this)); } // Destroys the object @@ -97,6 +101,8 @@ void LLFloaterAuction::onOpen(const LLSD& key) void LLFloaterAuction::initialize() { + mParcelUpdateCapUrl.clear(); + mParcelp = LLViewerParcelMgr::getInstance()->getParcelSelection(); LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); LLParcel* parcelp = mParcelp->getParcel(); @@ -104,10 +110,23 @@ void LLFloaterAuction::initialize() { mParcelHost = region->getHost(); mParcelID = parcelp->getLocalID(); + mParcelUpdateCapUrl = region->getCapability("ParcelPropertiesUpdate"); childSetText("parcel_text", parcelp->getName()); childEnable("snapshot_btn"); - childEnable("ok_btn"); + childEnable("reset_parcel_btn"); + childEnable("start_auction_btn"); + + LLPanelEstateInfo* panel = LLFloaterRegionInfo::getPanelEstate(); + if (panel) + { // Only enable "Sell to Anyone" on Teen grid or if we don't know the ID yet + U32 estate_id = panel->getEstateID(); + childSetEnabled("sell_to_anyone_btn", (estate_id == ESTATE_TEEN || estate_id == 0)); + } + else + { // Don't have the panel up, so don't know if we're on the teen grid or not. Default to enabling it + childEnable("sell_to_anyone_btn"); + } } else { @@ -122,8 +141,11 @@ void LLFloaterAuction::initialize() } mParcelID = -1; childSetEnabled("snapshot_btn", false); - childSetEnabled("ok_btn", false); + childSetEnabled("reset_parcel_btn", false); + childSetEnabled("sell_to_anyone_btn", false); + childSetEnabled("start_auction_btn", false); } + mImageID.setNull(); mImage = NULL; } @@ -205,7 +227,7 @@ void LLFloaterAuction::onClickSnapshot(void* data) } // static -void LLFloaterAuction::onClickOK(void* data) +void LLFloaterAuction::onClickStartAuction(void* data) { LLFloaterAuction* self = (LLFloaterAuction*)(data); @@ -244,11 +266,264 @@ void LLFloaterAuction::onClickOK(void* data) msg->sendReliable(self->mParcelHost); // clean up floater, and get out - self->mImageID.setNull(); - self->mImage = NULL; - self->mParcelID = -1; - self->mParcelHost.invalidate(); - self->closeFloater(); + self->cleanupAndClose(); +} + + +void LLFloaterAuction::cleanupAndClose() +{ + mImageID.setNull(); + mImage = NULL; + mParcelID = -1; + mParcelHost.invalidate(); + closeFloater(); +} + + + +// static glue +void LLFloaterAuction::onClickResetParcel(void* data) +{ + LLFloaterAuction* self = (LLFloaterAuction*)(data); + if (self) + { + self->doResetParcel(); + } +} + + +// Reset all the values for the parcel in preparation for a sale +void LLFloaterAuction::doResetParcel() +{ + LLParcel* parcelp = mParcelp->getParcel(); + LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); + + if (parcelp + && region + && !mParcelUpdateCapUrl.empty()) + { + LLSD body; + std::string empty; + + // request new properties update from simulator + U32 message_flags = 0x01; + body["flags"] = ll_sd_from_U32(message_flags); + + // Set all the default parcel properties for auction + body["local_id"] = parcelp->getLocalID(); + + U32 parcel_flags = PF_ALLOW_LANDMARK | + PF_ALLOW_FLY | + PF_CREATE_GROUP_OBJECTS | + PF_ALLOW_ALL_OBJECT_ENTRY | + PF_ALLOW_GROUP_OBJECT_ENTRY | + PF_ALLOW_GROUP_SCRIPTS | + PF_RESTRICT_PUSHOBJECT | + PF_SOUND_LOCAL | + PF_ALLOW_VOICE_CHAT | + PF_USE_ESTATE_VOICE_CHAN; + + body["parcel_flags"] = ll_sd_from_U32(parcel_flags); + + // Build a parcel name like "Ahern (128,128) PG 4032m" + std::ostringstream parcel_name; + LLVector3 center_point( parcelp->getCenterpoint() ); + center_point.snap(0); // Get rid of fractions + parcel_name << region->getName() + << " (" + << (S32) center_point.mV[VX] + << "," + << (S32) center_point.mV[VY] + << ") " + << region->getSimAccessString() + << " " + << parcelp->getArea() + << "m"; + + std::string new_name(parcel_name.str().c_str()); + body["name"] = new_name; + childSetText("parcel_text", new_name); // Set name in dialog as well, since it won't get updated otherwise + + body["sale_price"] = (S32) 0; + body["description"] = empty; + body["music_url"] = empty; + body["media_url"] = empty; + body["media_desc"] = empty; + body["media_type"] = std::string("none/none"); + body["media_width"] = (S32) 0; + body["media_height"] = (S32) 0; + body["auto_scale"] = (S32) 0; + body["media_loop"] = (S32) 0; + body["obscure_media"] = (S32) 0; + body["obscure_music"] = (S32) 0; + body["media_id"] = LLUUID::null; + body["group_id"] = MAINTENANCE_GROUP_ID; // Use maintenance group + body["pass_price"] = (S32) 10; // Defaults to $10 + body["pass_hours"] = 0.0f; + body["category"] = (U8) LLParcel::C_NONE; + body["auth_buyer_id"] = LLUUID::null; + body["snapshot_id"] = LLUUID::null; + body["user_location"] = ll_sd_from_vector3( LLVector3::zero ); + body["user_look_at"] = ll_sd_from_vector3( LLVector3::zero ); + body["landing_type"] = (U8) LLParcel::L_DIRECT; + + llinfos << "Sending parcel update to reset for auction via capability to: " + << mParcelUpdateCapUrl << llendl; + LLHTTPClient::post(mParcelUpdateCapUrl, body, new LLHTTPClient::Responder()); + + // Send a message to clear the object return time + LLMessageSystem *msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ParcelSetOtherCleanTime); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_ParcelData); + msg->addS32Fast(_PREHASH_LocalID, parcelp->getLocalID()); + msg->addS32Fast(_PREHASH_OtherCleanTime, 5); // 5 minute object auto-return + + msg->sendReliable(region->getHost()); + + // Clear the access lists + clearParcelAccessLists(parcelp, region); + } +} + + + +void LLFloaterAuction::clearParcelAccessLists(LLParcel* parcel, LLViewerRegion* region) +{ + if (!region || !parcel) return; + + LLUUID transactionUUID; + transactionUUID.generate(); + + LLMessageSystem* msg = gMessageSystem; + + // Clear access list + // parcel->mAccessList.clear(); + + msg->newMessageFast(_PREHASH_ParcelAccessListUpdate); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); + msg->nextBlockFast(_PREHASH_Data); + msg->addU32Fast(_PREHASH_Flags, AL_ACCESS); + msg->addS32(_PREHASH_LocalID, parcel->getLocalID() ); + msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID); + msg->addS32Fast(_PREHASH_SequenceID, 1); // sequence_id + msg->addS32Fast(_PREHASH_Sections, 0); // num_sections + + // pack an empty block since there will be no data + msg->nextBlockFast(_PREHASH_List); + msg->addUUIDFast(_PREHASH_ID, LLUUID::null ); + msg->addS32Fast(_PREHASH_Time, 0 ); + msg->addU32Fast(_PREHASH_Flags, 0 ); + + msg->sendReliable( region->getHost() ); + + // Send message for empty ban list + //parcel->mBanList.clear(); + msg->newMessageFast(_PREHASH_ParcelAccessListUpdate); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); + msg->nextBlockFast(_PREHASH_Data); + msg->addU32Fast(_PREHASH_Flags, AL_BAN); + msg->addS32(_PREHASH_LocalID, parcel->getLocalID() ); + msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID); + msg->addS32Fast(_PREHASH_SequenceID, 1); // sequence_id + msg->addS32Fast(_PREHASH_Sections, 0); // num_sections + + // pack an empty block since there will be no data + msg->nextBlockFast(_PREHASH_List); + msg->addUUIDFast(_PREHASH_ID, LLUUID::null ); + msg->addS32Fast(_PREHASH_Time, 0 ); + msg->addU32Fast(_PREHASH_Flags, 0 ); + + msg->sendReliable( region->getHost() ); +} + + + +// static - 'Sell to Anyone' clicked, throw up a confirmation dialog +void LLFloaterAuction::onClickSellToAnyone(void* data) +{ + LLFloaterAuction* self = (LLFloaterAuction*)(data); + if (self) + { + LLParcel* parcelp = self->mParcelp->getParcel(); + + // Do a confirmation + S32 sale_price = parcelp->getArea(); // Selling for L$1 per meter + S32 area = parcelp->getArea(); + + LLSD args; + args["LAND_SIZE"] = llformat("%d", area); + args["SALE_PRICE"] = llformat("%d", sale_price); + args["NAME"] = "Anyone"; + + LLNotification::Params params("ConfirmLandSaleChange"); // Re-use existing dialog + params.substitutions(args) + .functor.function(boost::bind(&LLFloaterAuction::onSellToAnyoneConfirmed, self, _1, _2)); + + params.name("ConfirmLandSaleToAnyoneChange"); + + // ask away + LLNotifications::instance().add(params); + } +} + + +// Sell confirmation clicked +bool LLFloaterAuction::onSellToAnyoneConfirmed(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + if (option == 0) + { + doSellToAnyone(); + } + + return false; +} + + + +// Reset all the values for the parcel in preparation for a sale +void LLFloaterAuction::doSellToAnyone() +{ + LLParcel* parcelp = mParcelp->getParcel(); + LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); + + if (parcelp + && region + && !mParcelUpdateCapUrl.empty()) + { + LLSD body; + std::string empty; + + // request new properties update from simulator + U32 message_flags = 0x01; + body["flags"] = ll_sd_from_U32(message_flags); + + // Set all the default parcel properties for auction + body["local_id"] = parcelp->getLocalID(); + + // Set 'for sale' flag + U32 parcel_flags = parcelp->getParcelFlags() | PF_FOR_SALE; + // Ensure objects not included + parcel_flags &= ~PF_FOR_SALE_OBJECTS; + body["parcel_flags"] = ll_sd_from_U32(parcel_flags); + + body["sale_price"] = parcelp->getArea(); // Sell for L$1 per square meter + body["auth_buyer_id"] = LLUUID::null; // To anyone + + llinfos << "Sending parcel update to sell to anyone for L$1 via capability to: " + << mParcelUpdateCapUrl << llendl; + LLHTTPClient::post(mParcelUpdateCapUrl, body, new LLHTTPClient::Responder()); + + // clean up floater, and get out + cleanupAndClose(); + } } diff --git a/indra/newview/llfloaterauction.h b/indra/newview/llfloaterauction.h index 1acc08057c..c599af782d 100644 --- a/indra/newview/llfloaterauction.h +++ b/indra/newview/llfloaterauction.h @@ -45,6 +45,8 @@ // Class which holds the functionality to start auctions. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLParcelSelection; +class LLParcel; +class LLViewerRegion; class LLFloaterAuction : public LLFloater { @@ -62,16 +64,28 @@ private: void initialize(); static void onClickSnapshot(void* data); - static void onClickOK(void* data); + static void onClickResetParcel(void* data); + static void onClickSellToAnyone(void* data); // Sell to anyone clicked + bool onSellToAnyoneConfirmed(const LLSD& notification, const LLSD& response); // Sell confirmation clicked + static void onClickStartAuction(void* data); /*virtual*/ BOOL postBuild(); + + void doResetParcel(); + void doSellToAnyone(); + void clearParcelAccessLists( LLParcel* parcel, LLViewerRegion* region ); + void cleanupAndClose(); + private: + LLTransactionID mTransactionID; LLAssetID mImageID; LLPointer mImage; LLSafeHandle mParcelp; S32 mParcelID; LLHost mParcelHost; + + std::string mParcelUpdateCapUrl; // "ParcelPropertiesUpdate" capability }; diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index 890d863db7..ccfe7d4b64 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -69,7 +69,7 @@ LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(callback_t callback, // Default constructor LLFloaterAvatarPicker::LLFloaterAvatarPicker(const LLSD& key) : LLFloater(key), - mResultsReturned(FALSE), + mNumResultsReturned(0), mCallback(NULL), mCallbackUserdata(NULL), mNearMeListComplete(FALSE), @@ -314,7 +314,7 @@ void LLFloaterAvatarPicker::find() getChild("SearchResults")->setCommentText(getString("searching")); childSetEnabled("Select", FALSE); - mResultsReturned = FALSE; + mNumResultsReturned = 0; } void LLFloaterAvatarPicker::setAllowMultiple(BOOL allow_multiple) @@ -349,9 +349,10 @@ void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void* LLScrollListCtrl* search_results = floater->getChild("SearchResults"); // clear "Searching" label on first results - search_results->deleteAllItems(); - - floater->mResultsReturned = TRUE; + if (floater->mNumResultsReturned++ == 0) + { + search_results->deleteAllItems(); + } BOOL found_one = FALSE; S32 num_new_rows = msg->getNumberOfBlocks("Data"); diff --git a/indra/newview/llfloateravatarpicker.h b/indra/newview/llfloateravatarpicker.h index f3b9aefb9c..85aacb68a5 100644 --- a/indra/newview/llfloateravatarpicker.h +++ b/indra/newview/llfloateravatarpicker.h @@ -76,7 +76,7 @@ private: virtual BOOL handleKeyHere(KEY key, MASK mask); LLUUID mQueryID; - BOOL mResultsReturned; + int mNumResultsReturned; BOOL mNearMeListComplete; BOOL mCloseOnSelect; diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp index e0fe87f9ae..1300103423 100644 --- a/indra/newview/llfloatergesture.cpp +++ b/indra/newview/llfloatergesture.cpp @@ -211,25 +211,16 @@ void LLFloaterGesture::buildGestureList() std::string key_string = LLKeyboard::stringFromKey(gesture->mKey); std::string buffer; + if (gesture->mKey == KEY_NONE) { - if (gesture->mKey == KEY_NONE) - { - buffer = "---"; - key_string = "~~~"; // alphabetize to end - } - else - { - if (gesture->mMask & MASK_CONTROL) buffer.append("Ctrl-"); - if (gesture->mMask & MASK_ALT) buffer.append("Alt-"); - if (gesture->mMask & MASK_SHIFT) buffer.append("Shift-"); - if ((gesture->mMask & (MASK_CONTROL|MASK_ALT|MASK_SHIFT)) && - (key_string[0] == '-' || key_string[0] == '=')) - { - buffer.append(" "); - } - buffer.append(key_string); - } + buffer = "---"; + key_string = "~~~"; // alphabetize to end } + else + { + buffer = LLKeyboard::stringFromAccelerator( gesture->mMask, gesture->mKey ); + } + element["columns"][1]["column"] = "shortcut"; element["columns"][1]["value"] = buffer; element["columns"][1]["font"]["name"] = "SANSSERIF"; diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index a378a511b5..c1031ee437 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -105,7 +105,7 @@ public: // LLFloaterLand //--------------------------------------------------------------------------- -void send_parcel_select_objects(S32 parcel_local_id, S32 return_type, +void send_parcel_select_objects(S32 parcel_local_id, U32 return_type, uuid_list_t* return_ids = NULL) { LLMessageSystem *msg = gMessageSystem; @@ -123,7 +123,7 @@ void send_parcel_select_objects(S32 parcel_local_id, S32 return_type, msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID()); msg->nextBlockFast(_PREHASH_ParcelData); msg->addS32Fast(_PREHASH_LocalID, parcel_local_id); - msg->addS32Fast(_PREHASH_ReturnType, return_type); + msg->addU32Fast(_PREHASH_ReturnType, return_type); // Throw all return ids into the packet. // TODO: Check for too many ids. diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 1ec869da73..70a3ad5252 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -143,6 +143,7 @@ BOOL LLFloaterReporter::postBuild() LLViewerRegion *regionp = gAgent.getRegion(); if (regionp) { + childSetText("sim_field", regionp->getName()); pos -= regionp->getOriginGlobal(); } setPosBox(pos); diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp index 43d31aa30a..2d8ccd1aef 100644 --- a/indra/newview/llfloatersellland.cpp +++ b/indra/newview/llfloatersellland.cpp @@ -47,7 +47,7 @@ #include "llviewerwindow.h" // defined in llfloaterland.cpp -void send_parcel_select_objects(S32 parcel_local_id, S32 return_type, +void send_parcel_select_objects(S32 parcel_local_id, U32 return_type, uuid_list_t* return_ids = NULL); enum Badge { BADGE_OK, BADGE_NOTE, BADGE_WARN, BADGE_ERROR }; diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index b64d8ab334..e00b352c9b 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -417,6 +417,11 @@ void LLFloaterTools::refresh() LLResMgr::getInstance()->getIntegerString(prim_count_string, LLSelectMgr::getInstance()->getSelection()->getObjectCount()); childSetTextArg("prim_count", "[COUNT]", prim_count_string); + // disable the object and prim counts if nothing selected + bool have_selection = ! LLSelectMgr::getInstance()->getSelection()->isEmpty(); + childSetEnabled("obj_count", have_selection); + childSetEnabled("prim_count", have_selection); + // Refresh child tabs mPanelPermissions->refresh(); mPanelObject->refresh(); diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index d653d44f8c..b7e8835fb8 100644 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -49,6 +49,7 @@ #include "llfirstuse.h" #include "llfloaterreg.h" // getTypedInstance() #include "llfocusmgr.h" +#include "llinventorymodel.h" #include "lllandmarklist.h" #include "lllineeditor.h" #include "llregionhandle.h" @@ -57,7 +58,7 @@ #include "lltabcontainer.h" #include "lltextbox.h" #include "lltracker.h" -#include "llinventorymodel.h" +#include "lltrans.h" #include "llviewerinventory.h" // LLViewerInventoryItem #include "llviewermenu.h" #include "llviewerregion.h" @@ -151,7 +152,6 @@ LLFloaterWorldMap::LLFloaterWorldMap(const LLSD& key) mFriendObserver(NULL), mCompletingRegionName(""), mWaitingForTracker(FALSE), - mExactMatch(FALSE), mIsClosing(FALSE), mSetToUserPosition(TRUE), mTrackedLocation(0,0,0), @@ -903,7 +903,6 @@ void LLFloaterWorldMap::clearLocationSelection(BOOL clear_ui) } LLWorldMap::getInstance()->mIsTrackingCommit = FALSE; mCompletingRegionName = ""; - mExactMatch = FALSE; } @@ -1163,7 +1162,6 @@ void LLFloaterWorldMap::onLocationCommit() LLStringUtil::toLower(str); mCompletingRegionName = str; LLWorldMap::getInstance()->mIsTrackingCommit = TRUE; - mExactMatch = FALSE; if (str.length() >= 3) { LLWorldMap::getInstance()->sendNamedRegionRequest(str); @@ -1418,11 +1416,10 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim) LLScrollListCtrl *list = getChild("search_results"); list->operateOnAll(LLCtrlListInterface::OP_DELETE); - LLSD selected_value = list->getSelectedValue(); - S32 name_length = mCompletingRegionName.length(); - BOOL match_found = FALSE; + LLSD match; + S32 num_results = 0; std::map::const_iterator it; for (it = LLWorldMap::getInstance()->mSimInfoMap.begin(); it != LLWorldMap::getInstance()->mSimInfoMap.end(); ++it) @@ -1434,15 +1431,11 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim) if (sim_name_lower.substr(0, name_length) == mCompletingRegionName) { - if (LLWorldMap::getInstance()->mIsTrackingCommit) + if (sim_name_lower == mCompletingRegionName) { - if (sim_name_lower == mCompletingRegionName) - { - selected_value = sim_name; - match_found = TRUE; - } + match = sim_name; } - + LLSD value; value["id"] = sim_name; value["columns"][0]["column"] = "sim_name"; @@ -1451,29 +1444,24 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim) num_results++; } } - - list->selectByValue(selected_value); if (found_null_sim) { mCompletingRegionName = ""; } - if (match_found) - { - mExactMatch = TRUE; - childSetFocus("search_results"); - onCommitSearchResult(); - } - else if (!mExactMatch && num_results > 0) + // if match found, highlight it and go + if (!match.isUndefined()) { - list->selectFirstItem(); // select first item by default + list->selectByValue(match); childSetFocus("search_results"); onCommitSearchResult(); } - else if (num_results == 0) + + // if we found nothing, say "none" + if (num_results == 0) { - list->setCommentText(std::string("None found.")); + list->setCommentText(LLTrans::getString("worldmap_results_none_found")); list->operateOnAll(LLCtrlListInterface::OP_DESELECT); } } diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h index 6d5b7543d4..20a8e6d321 100644 --- a/indra/newview/llfloaterworldmap.h +++ b/indra/newview/llfloaterworldmap.h @@ -174,7 +174,6 @@ protected: std::string mCompletingRegionName; std::string mLastRegionName; BOOL mWaitingForTracker; - BOOL mExactMatch; BOOL mIsClosing; BOOL mSetToUserPosition; diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 99f331d087..c2d515f158 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -1654,6 +1654,8 @@ void LLFloaterIMPanel::sendMsg() LLWString text = mInputEditor->getConvertedText(); if(!text.empty()) { + // store sent line in history, duplicates will get filtered + if (mInputEditor) mInputEditor->updateHistory(); // Truncate and convert to UTF8 for transport std::string utf8_text = wstring_to_utf8str(text); utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index d4a9324208..1880a574a7 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -2316,6 +2316,8 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); + mItems.clear(); //adding code to clear out member Items (which means Items should not have other data here at this point) + mDisabledItems.clear(); //adding code to clear out disabled members from previous if (lost_and_found_id == mUUID) { // This is the lost+found folder. diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index b4d3f4575b..7ec8d3d003 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -131,6 +131,13 @@ BOOL LLInventoryFilter::check(LLFolderViewItem* item) && (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos) && ((listener->getPermissionMask() & mFilterOps.mPermissions) == mFilterOps.mPermissions) && (listener->getCreationDate() >= earliest && listener->getCreationDate() <= mFilterOps.mMaxDate); + + BOOL is_folder = (dynamic_cast(item) != NULL); + if (is_folder && mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS) + { + passed = TRUE; + } + return passed; } diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp index 14a8b7cb59..c99e67be3f 100644 --- a/indra/newview/llmaniprotate.cpp +++ b/indra/newview/llmaniprotate.cpp @@ -1234,9 +1234,9 @@ LLVector3 LLManipRotate::getConstraintAxis() else { #ifndef LL_RELEASE_FOR_DOWNLOAD - llerrs << "Got bogus hit part in LLManipRotate::getConstraintAxis():" << mManipPart << llendl + llerrs << "Got bogus hit part in LLManipRotate::getConstraintAxis():" << mManipPart << llendl; #else - llwarns << "Got bogus hit part in LLManipRotate::getConstraintAxis():" << mManipPart << llendl + llwarns << "Got bogus hit part in LLManipRotate::getConstraintAxis():" << mManipPart << llendl; #endif axis.mV[0] = 1.f; } diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp index e2281743c9..206d8428be 100644 --- a/indra/newview/llpanelgroup.cpp +++ b/indra/newview/llpanelgroup.cpp @@ -101,14 +101,13 @@ void LLPanelGroupTab::handleClickHelp() } LLPanelGroup::LLPanelGroup() -: LLPanel() - ,LLGroupMgrObserver( LLUUID() ) - ,mAllowEdit(TRUE) +: LLPanel(), + LLGroupMgrObserver( LLUUID() ), + mAllowEdit( TRUE ) { // Set up the factory callbacks. // Roles sub tabs LLGroupMgr::getInstance()->addObserver(this); - } @@ -247,6 +246,7 @@ void LLPanelGroup::onBackBtnClick() } } + void LLPanelGroup::onBtnCreate() { LLPanelGroupGeneral* panel_general = findChild("group_general_tab_panel"); diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index 0331fad60c..a6b67d668a 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -186,7 +186,7 @@ BOOL LLPanelGroupGeneral::postBuild() } mIncompleteMemberDataStr = getString("incomplete_member_data_str"); - + // If the group_id is null, then we are creating a new group if (mGroupID.isNull()) { diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp index 32ed20bd56..ab2afb8056 100644 --- a/indra/newview/llpreviewgesture.cpp +++ b/indra/newview/llpreviewgesture.cpp @@ -1178,7 +1178,7 @@ void LLPreviewGesture::onSaveComplete(const LLUUID& asset_uuid, void* user_data, else { llwarns << "Inventory item for gesture " << info->mItemUUID - << " is no longer in agent inventory." << llendl + << " is no longer in agent inventory." << llendl; } } else diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 19bb60b237..ac7abf1448 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -1260,7 +1260,7 @@ void LLPreviewLSL::onSaveComplete(const LLUUID& asset_uuid, void* user_data, S32 else { llwarns << "Inventory item for script " << info->mItemUUID - << " is no longer in agent inventory." << llendl + << " is no longer in agent inventory." << llendl; } // Find our window and close it if requested. @@ -1383,6 +1383,7 @@ void LLPreviewLSL::onLoadComplete( LLVFS *vfs, const LLUUID& asset_uuid, LLAsset delete item_uuid; } + /// --------------------------------------------------------------------------- /// LLLiveLSLEditor /// --------------------------------------------------------------------------- @@ -2145,6 +2146,7 @@ void LLLiveLSLEditor::processScriptRunningReply(LLMessageSystem* msg, void**) } } + void LLLiveLSLEditor::onMonoCheckboxClicked(LLUICtrl*, void* userdata) { LLLiveLSLEditor* self = static_cast(userdata); diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index 9d7338c111..9c21faa3be 100644 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -38,6 +38,7 @@ #include "llagent.h" #include "llbutton.h" +#include "llcombobox.h" #include "llfilepicker.h" #include "llfloaterreg.h" #include "llimagetga.h" @@ -57,6 +58,10 @@ const S32 CLIENT_RECT_VPAD = 4; const F32 SECONDS_TO_SHOW_FILE_SAVED_MSG = 8.f; +const F32 PREVIEW_TEXTURE_MAX_ASPECT = 200.f; +const F32 PREVIEW_TEXTURE_MIN_ASPECT = 0.005f; + + LLPreviewTexture::LLPreviewTexture(const LLSD& key) : LLPreview( key ), mLoadingFullImage( FALSE ), @@ -65,7 +70,8 @@ LLPreviewTexture::LLPreviewTexture(const LLSD& key) mIsCopyable(FALSE), mUpdateDimensions(TRUE), mLastHeight(0), - mLastWidth(0) + mLastWidth(0), + mAspectRatio(0.f) { const LLInventoryItem *item = getItem(); if(item) @@ -144,6 +150,10 @@ BOOL LLPreviewTexture::postBuild() } } + childSetCommitCallback("combo_aspect_ratio", onAspectRatioCommit, this); + LLComboBox* combo = getChild("combo_aspect_ratio"); + combo->setCurrentByIndex(0); + return LLPreview::postBuild(); } @@ -369,8 +379,13 @@ void LLPreviewTexture::updateDimensions() S32 max_client_width = gViewerWindow->getWindowWidth() - horiz_pad; S32 max_client_height = gViewerWindow->getWindowHeight() - vert_pad; + if (mAspectRatio > 0.f) + { + client_height = llceil((F32)client_width / mAspectRatio); + } + while ((client_width > max_client_width) || - (client_height > max_client_height ) ) + (client_height > max_client_height )) { client_width /= 2; client_height /= 2; @@ -383,12 +398,12 @@ void LLPreviewTexture::updateDimensions() childSetTextArg("dimensions", "[WIDTH]", llformat("%d", mImage->getFullWidth())); childSetTextArg("dimensions", "[HEIGHT]", llformat("%d", mImage->getFullHeight())); - // add space for dimensions + // add space for dimensions and aspect ratio S32 info_height = 0; - LLRect dim_rect; - childGetRect("dimensions", dim_rect); - S32 dim_height = dim_rect.getHeight(); - info_height += dim_height + CLIENT_RECT_VPAD; + LLRect aspect_rect; + childGetRect("combo_aspect_ratio", aspect_rect); + S32 aspect_height = aspect_rect.getHeight(); + info_height += aspect_height + CLIENT_RECT_VPAD; view_height += info_height; S32 button_height = 0; @@ -445,24 +460,96 @@ void LLPreviewTexture::updateDimensions() else { client_width = getRect().getWidth() - horiz_pad; - client_height = getRect().getHeight() - vert_pad; + if (mAspectRatio > 0) + { + client_height = llround(client_width / mAspectRatio); + } + else + { + client_height = getRect().getHeight() - vert_pad; + } } - S32 max_height = getRect().getHeight() - PREVIEW_BORDER - button_height + S32 max_height = getRect().getHeight() - PREVIEW_BORDER - button_height - CLIENT_RECT_VPAD - info_height - CLIENT_RECT_VPAD - PREVIEW_HEADER_SIZE; - S32 max_width = getRect().getWidth() - horiz_pad; - client_height = llclamp(client_height, 1, max_height); - client_width = llclamp(client_width, 1, max_width); + if (mAspectRatio > 0.f) + { + max_height = llmax(max_height, 1); + + if (client_height > max_height) + { + client_height = max_height; + client_width = llround(client_height * mAspectRatio); + } + } + else + { + S32 max_width = getRect().getWidth() - horiz_pad; + + client_height = llclamp(client_height, 1, max_height); + client_width = llclamp(client_width, 1, max_width); + } LLRect window_rect(0, getRect().getHeight(), getRect().getWidth(), 0); window_rect.mTop -= (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD); window_rect.mBottom += PREVIEW_BORDER + button_height + CLIENT_RECT_VPAD + info_height + CLIENT_RECT_VPAD; - mClientRect.setLeftTopAndSize(window_rect.getCenterX() - (client_width / 2), window_rect.mTop, client_width, client_height); + mClientRect.setLeftTopAndSize(window_rect.getCenterX() - (client_width / 2), window_rect.mTop, client_width, client_height); + + // Hide the aspect ratio label if the window is too narrow + // Assumes the label should be to the right of the dimensions + LLRect dim_rect, aspect_label_rect; + childGetRect("aspect_ratio", aspect_label_rect); + childGetRect("dimensions", dim_rect); + childSetVisible("aspect_ratio", dim_rect.mRight < aspect_label_rect.mLeft); +} + + +// Return true if everything went fine, false if we somewhat modified the ratio as we bumped on border values +bool LLPreviewTexture::setAspectRatio(const F32 width, const F32 height) +{ + mUpdateDimensions = TRUE; + + // We don't allow negative width or height. Also, if height is positive but too small, we reset to default + // A default 0.f value for mAspectRatio means "unconstrained" in the rest of the code + if ((width <= 0.f) || (height <= F_APPROXIMATELY_ZERO)) + { + mAspectRatio = 0.f; + return false; + } + + // Compute and store the ratio + F32 ratio = width / height; + mAspectRatio = llclamp(ratio, PREVIEW_TEXTURE_MIN_ASPECT, PREVIEW_TEXTURE_MAX_ASPECT); + + // Return false if we clamped the value, true otherwise + return (ratio == mAspectRatio); } +void LLPreviewTexture::onAspectRatioCommit(LLUICtrl* ctrl, void* userdata) +{ + LLPreviewTexture* self = (LLPreviewTexture*) userdata; + + std::string ratio(ctrl->getValue().asString()); + std::string::size_type separator(ratio.find_first_of(":/\\")); + + if (std::string::npos == separator) { + // If there's no separator assume we want an unconstrained ratio + self->setAspectRatio( 0.f, 0.f ); + return; + } + + F32 width, height; + std::istringstream numerator(ratio.substr(0, separator)); + std::istringstream denominator(ratio.substr(separator + 1)); + numerator >> width; + denominator >> height; + + self->setAspectRatio( width, height ); +} + void LLPreviewTexture::loadAsset() { mImage = LLViewerTextureManager::getFetchedTexture(mImageID, MIPMAP_TRUE, FALSE, LLViewerTexture::LOD_TEXTURE); diff --git a/indra/newview/llpreviewtexture.h b/indra/newview/llpreviewtexture.h index 9ace304fa6..520626b49f 100644 --- a/indra/newview/llpreviewtexture.h +++ b/indra/newview/llpreviewtexture.h @@ -38,6 +38,7 @@ #include "llframetimer.h" #include "llviewertexture.h" +class LLComboBox; class LLImageRaw; class LLPreviewTexture : public LLPreview @@ -71,7 +72,9 @@ public: protected: void init(); /* virtual */ BOOL postBuild(); - + bool setAspectRatio(const F32 width, const F32 height); + static void onAspectRatioCommit(LLUICtrl*,void* userdata); + private: void updateDimensions(); LLUUID mImageID; @@ -88,6 +91,7 @@ private: S32 mLastHeight; S32 mLastWidth; + F32 mAspectRatio; BOOL mUpdateDimensions; }; diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index d163ceb30e..288cf728b9 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -545,7 +545,7 @@ BOOL LLSelectMgr::removeObjectFromSelections(const LLUUID &id) object_found = TRUE; break; // must break here, may have removed multiple objects from list } - else if (object->isAvatar()) + else if (object->isAvatar() && object->getParent() && ((LLViewerObject*)object->getParent())->mID == id) { // It's possible the item being removed has an avatar sitting on it // So remove the avatar that is sitting on the object. diff --git a/indra/newview/llsky.cpp b/indra/newview/llsky.cpp index a49b07c5d9..de99cb86fa 100644 --- a/indra/newview/llsky.cpp +++ b/indra/newview/llsky.cpp @@ -66,6 +66,9 @@ F32 elevation_from_vector(const LLVector3 &v); LLSky gSky; // ---------------- LLSky ---------------- +const F32 LLSky::NIGHTTIME_ELEVATION = -8.0f; // degrees +const F32 LLSky::NIGHTTIME_ELEVATION_COS = (F32)sin(NIGHTTIME_ELEVATION*DEG_TO_RAD); + ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llsky.h b/indra/newview/llsky.h index abd4205e6c..d7796dea83 100644 --- a/indra/newview/llsky.h +++ b/indra/newview/llsky.h @@ -42,9 +42,6 @@ #include "llvosky.h" #include "llvoground.h" -const F32 NIGHTTIME_ELEVATION = -8.0f; // degrees -const F32 NIGHTTIME_ELEVATION_COS = (F32)sin(NIGHTTIME_ELEVATION*DEG_TO_RAD); - class LLViewerCamera; class LLVOWLSky; @@ -111,6 +108,9 @@ public: // Legacy stuff LLVector3 mSunDefaultPosition; + static const F32 NIGHTTIME_ELEVATION; // degrees + static const F32 NIGHTTIME_ELEVATION_COS; + protected: BOOL mOverrideSimSunPosition; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 62435c6288..9cd3acf13e 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -977,6 +977,13 @@ bool idle_startup() LLFile::mkdir(gDirUtilp->getChatLogsDir()); LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir()); + // chat history must be loaded AFTER chat directories are defined. + if (!gNoRender && gSavedPerAccountSettings.getBOOL("LogShowHistory")) + { + LLFloaterChat::loadHistory(); + } + + //good as place as any to create user windlight directories std::string user_windlight_path_name(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight", "")); LLFile::mkdir(user_windlight_path_name.c_str()); diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 63af170fa9..88fc7f98c0 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -1371,7 +1371,7 @@ bool LLTextureFetch::createRequest(const std::string& filename, const LLUUID& id } else if (w*h*c > 0) { - // If the requester knows the dimentions of the image, + // If the requester knows the dimensions of the image, // this will calculate how much data we need without having to parse the header desired_size = LLImageJ2C::calcDataSizeJ2C(w, h, c, desired_discard); diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp index ee6ef6ffee..f65baea6ca 100644 --- a/indra/newview/llviewercamera.cpp +++ b/indra/newview/llviewercamera.cpp @@ -120,9 +120,8 @@ void LLViewerCamera::updateCameraLocation(const LLVector3 ¢er, const LLVector3 &up_direction, const LLVector3 &point_of_interest) { - // do not update if we are in build mode AND avatar didn't move - if (LLToolMgr::getInstance()->inBuildMode() - && !LLViewerJoystick::getInstance()->getCameraNeedsUpdate()) + // do not update if avatar didn't move + if (!LLViewerJoystick::getInstance()->getCameraNeedsUpdate()) { return; } diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index fa82612114..b71291f834 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -688,7 +688,7 @@ static LLCachedControl test_BrowserHomePage("BrowserHomePage", "hah void test_cached_control() { -#define TEST_LLCC(T, V) if((T)mySetting_##T != V) llerrs << "Fail "#T << llendl +#define do { TEST_LLCC(T, V) if((T)mySetting_##T != V) llerrs << "Fail "#T << llendl; } while(0) TEST_LLCC(U32, 666); TEST_LLCC(S32, (S32)-666); TEST_LLCC(F32, (F32)-666.666); diff --git a/indra/newview/llviewerjoystick.cpp b/indra/newview/llviewerjoystick.cpp index b919e3d1c1..b593fbfb00 100644 --- a/indra/newview/llviewerjoystick.cpp +++ b/indra/newview/llviewerjoystick.cpp @@ -414,14 +414,41 @@ void LLViewerJoystick::agentFly(F32 inc) } // ----------------------------------------------------------------------------- -void LLViewerJoystick::agentRotate(F32 pitch_inc, F32 yaw_inc) +void LLViewerJoystick::agentPitch(F32 pitch_inc) { - LLQuaternion new_rot; - pitch_inc = gAgent.clampPitchToLimits(-pitch_inc); - const LLQuaternion qx(pitch_inc, gAgent.getLeftAxis()); - const LLQuaternion qy(-yaw_inc, gAgent.getReferenceUpVector()); - new_rot.setQuat(qx * qy); - gAgent.rotate(new_rot); + if (pitch_inc < 0) + { + gAgent.setControlFlags(AGENT_CONTROL_PITCH_POS); + } + else if (pitch_inc > 0) + { + gAgent.setControlFlags(AGENT_CONTROL_PITCH_NEG); + } + + gAgent.pitch(-pitch_inc); +} + +// ----------------------------------------------------------------------------- +void LLViewerJoystick::agentYaw(F32 yaw_inc) +{ + // Cannot steer some vehicles in mouselook if the script grabs the controls + if (gAgent.cameraMouselook() && !gSavedSettings.getBOOL("JoystickMouselookYaw")) + { + gAgent.rotate(-yaw_inc, gAgent.getReferenceUpVector()); + } + else + { + if (yaw_inc < 0) + { + gAgent.setControlFlags(AGENT_CONTROL_YAW_POS); + } + else if (yaw_inc > 0) + { + gAgent.setControlFlags(AGENT_CONTROL_YAW_NEG); + } + + gAgent.yaw(-yaw_inc); + } } // ----------------------------------------------------------------------------- @@ -595,12 +622,38 @@ void LLViewerJoystick::moveAvatar(bool reset) } bool is_zero = true; + static bool button_held = false; if (mBtn[1] == 1) { - agentJump(); + // If AutomaticFly is enabled, then button1 merely causes a + // jump (as the up/down axis already controls flying) if on the + // ground, or cease flight if already flying. + // If AutomaticFly is disabled, then button1 toggles flying. + if (gSavedSettings.getBOOL("AutomaticFly")) + { + if (!gAgent.getFlying()) + { + gAgent.moveUp(1); + } + else if (!button_held) + { + button_held = true; + gAgent.setFlying(FALSE); + } + } + else if (!button_held) + { + button_held = true; + gAgent.setFlying(!gAgent.getFlying()); + } + is_zero = false; } + else + { + button_held = false; + } F32 axis_scale[] = { @@ -758,11 +811,13 @@ void LLViewerJoystick::moveAvatar(bool reset) { if (gAgent.getFlying()) { - agentRotate(eff_rx, eff_ry); + agentPitch(eff_rx); + agentYaw(eff_ry); } else { - agentRotate(eff_rx, 2.f * eff_ry); + agentPitch(eff_rx); + agentYaw(2.f * eff_ry); } } } @@ -771,7 +826,8 @@ void LLViewerJoystick::moveAvatar(bool reset) agentSlide(sDelta[X_I]); // move sideways agentFly(sDelta[Y_I]); // up/down & crouch agentPush(sDelta[Z_I]); // forward/back - agentRotate(sDelta[RX_I], sDelta[RY_I]); // pitch & turn + agentPitch(sDelta[RX_I]); // pitch + agentYaw(sDelta[RY_I]); // turn } } @@ -963,15 +1019,10 @@ bool LLViewerJoystick::toggleFlycam() moveFlycam(true); } - else if (!LLToolMgr::getInstance()->inBuildMode()) - { - moveAvatar(true); - } else { - // we are in build mode, exiting from the flycam mode: since we are - // going to keep the flycam POV for the main camera until the avatar - // moves, we need to track this situation. + // Exiting from the flycam mode: since we are going to keep the flycam POV for + // the main camera until the avatar moves, we need to track this situation. setCameraNeedsUpdate(false); setNeedsReset(true); } diff --git a/indra/newview/llviewerjoystick.h b/indra/newview/llviewerjoystick.h index b565ed5696..a3904bd2c3 100644 --- a/indra/newview/llviewerjoystick.h +++ b/indra/newview/llviewerjoystick.h @@ -82,8 +82,9 @@ protected: void agentSlide(F32 inc); void agentPush(F32 inc); void agentFly(F32 inc); - void agentRotate(F32 pitch_inc, F32 turn_inc); - void agentJump(); + void agentPitch(F32 pitch_inc); + void agentYaw(F32 yaw_inc); + void agentJump(); void resetDeltas(S32 axis[]); #if LIB_NDOF static NDOF_HotPlugResult HotPlugAddCallback(NDOF_Device *dev); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 2b972614f1..b8e945a7b8 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -1000,6 +1000,7 @@ BOOL LLViewerMediaImpl::handleMouseUp(S32 x, S32 y, MASK mask) return TRUE; } + ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::navigateHome() { diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index b4e0d88e79..c2def610dc 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -4733,6 +4733,96 @@ class LLToolsSnapObjectXY : public view_listener_t } }; +// Determine if the option to cycle between linked prims is shown +class LLToolsEnableSelectNextPart : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + bool new_value = (gSavedSettings.getBOOL("EditLinkedParts") && + !LLSelectMgr::getInstance()->getSelection()->isEmpty()); + return new_value; + } +}; + +// Cycle selection through linked children in selected object. +// FIXME: Order of children list is not always the same as sim's idea of link order. This may confuse +// resis. Need link position added to sim messages to address this. +class LLToolsSelectNextPart : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + S32 object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); + if (gSavedSettings.getBOOL("EditLinkedParts") && object_count) + { + LLViewerObject* selected = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + if (selected && selected->getRootEdit()) + { + bool fwd = (userdata.asString() == "next"); + bool prev = (userdata.asString() == "previous"); + bool ifwd = (userdata.asString() == "includenext"); + bool iprev = (userdata.asString() == "includeprevious"); + LLViewerObject* to_select = NULL; + LLViewerObject::child_list_t children = selected->getRootEdit()->getChildren(); + children.push_front(selected->getRootEdit()); // need root in the list too + + for (LLViewerObject::child_list_t::iterator iter = children.begin(); iter != children.end(); ++iter) + { + if ((*iter)->isSelected()) + { + if (object_count > 1 && (fwd || prev)) // multiple selection, find first or last selected if not include + { + to_select = *iter; + if (fwd) + { + // stop searching if going forward; repeat to get last hit if backward + break; + } + } + else if ((object_count == 1) || (ifwd || iprev)) // single selection or include + { + if (fwd || ifwd) + { + ++iter; + while (iter != children.end() && ((*iter)->isAvatar() || (ifwd && (*iter)->isSelected()))) + { + ++iter; // skip sitting avatars and selected if include + } + } + else // backward + { + iter = (iter == children.begin() ? children.end() : iter); + --iter; + while (iter != children.begin() && ((*iter)->isAvatar() || (iprev && (*iter)->isSelected()))) + { + --iter; // skip sitting avatars and selected if include + } + } + iter = (iter == children.end() ? children.begin() : iter); + to_select = *iter; + break; + } + } + } + + if (to_select) + { + if (gFocusMgr.childHasKeyboardFocus(gFloaterTools)) + { + gFocusMgr.setKeyboardFocus(NULL); // force edit toolbox to commit any changes + } + if (fwd || prev) + { + LLSelectMgr::getInstance()->deselectAll(); + } + LLSelectMgr::getInstance()->selectObjectOnly(to_select); + return true; + } + } + } + return true; + } +}; + // in order to link, all objects must have the same owner, and the // agent must have the ability to modify all of the objects. However, // we're not answering that question with this method. The question @@ -7729,6 +7819,7 @@ void initialize_menus() view_listener_t::addMenu(new LLToolsEditLinkedParts(), "Tools.EditLinkedParts"); view_listener_t::addMenu(new LLToolsSnapObjectXY(), "Tools.SnapObjectXY"); view_listener_t::addMenu(new LLToolsUseSelectionForGrid(), "Tools.UseSelectionForGrid"); + view_listener_t::addMenu(new LLToolsSelectNextPart(), "Tools.SelectNextPart"); view_listener_t::addMenu(new LLToolsLink(), "Tools.Link"); view_listener_t::addMenu(new LLToolsUnlink(), "Tools.Unlink"); view_listener_t::addMenu(new LLToolsStopAllAnimations(), "Tools.StopAllAnimations"); @@ -7742,6 +7833,7 @@ void initialize_menus() view_listener_t::addMenu(new LLToolsSelectedScriptAction(), "Tools.SelectedScriptAction"); view_listener_t::addMenu(new LLToolsEnableToolNotPie(), "Tools.EnableToolNotPie"); + view_listener_t::addMenu(new LLToolsEnableSelectNextPart(), "Tools.EnableSelectNextPart"); view_listener_t::addMenu(new LLToolsEnableLink(), "Tools.EnableLink"); view_listener_t::addMenu(new LLToolsEnableUnlink(), "Tools.EnableUnlink"); view_listener_t::addMenu(new LLToolsEnableBuyOrTake(), "Tools.EnableBuyOrTake"); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 1cfeec5627..d3a9e1cef8 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -219,7 +219,7 @@ const std::string upload_pick(void* data) args["EXTENSION"] = ext; args["VALIDS"] = valid_extensions; LLNotifications::instance().add("InvalidFileExtension", args); - return NULL; + return std::string(); } }//end else (non-null extension) diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index acdc2c2513..1d982265ca 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -174,11 +174,28 @@ BOOL LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject &object) U32 port = region_host.getPort(); U64 ipport = (((U64)ip) << 32) | (U64)port; U32 index = sIPAndPortToIndex[ipport]; - + + // llinfos << "Removing object from table, local ID " << local_id << ", ip " << ip << ":" << port << llendl; + U64 indexid = (((U64)index) << 32) | (U64)local_id; - return sIndexAndLocalIDToUUID.erase(indexid) > 0 ? TRUE : FALSE; + + std::map::iterator iter = sIndexAndLocalIDToUUID.find(indexid); + if (iter == sIndexAndLocalIDToUUID.end()) + { + return FALSE; + } + + // Found existing entry + if (iter->second == object.getID()) + { // Full UUIDs match, so remove the entry + sIndexAndLocalIDToUUID.erase(iter); + return TRUE; + } + // UUIDs did not match - this would zap a valid entry, so don't erase it + //llinfos << "Tried to erase entry where id in table (" + // << iter->second << ") did not match object " << object.getID() << llendl; } - + return FALSE ; } @@ -200,6 +217,9 @@ void LLViewerObjectList::setUUIDAndLocal(const LLUUID &id, U64 indexid = (((U64)index) << 32) | (U64)local_id; sIndexAndLocalIDToUUID[indexid] = id; + + //llinfos << "Adding object to table, full ID " << id + // << ", local ID " << local_id << ", ip " << ip << ":" << port << llendl; } S32 gFullObjectUpdates = 0; @@ -246,8 +266,8 @@ void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp, { if ( LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance() ) { - //llinfos << "DEBUG selecting " << objectp->mID << " " - // << objectp->mLocalID << llendl; + // llinfos << "DEBUG selecting " << objectp->mID << " " + // << objectp->mLocalID << llendl; LLSelectMgr::getInstance()->selectObjectAndFamily(objectp); dialog_refresh_all(); } @@ -294,7 +314,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, { size = mesgsys->getReceiveSize(); } -// llinfos << "Received terse " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl; + // llinfos << "Received terse " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl; } else { @@ -308,7 +328,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, size = mesgsys->getReceiveSize(); } -// llinfos << "Received " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl; + // llinfos << "Received " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl; gFullObjectUpdates += num_objects; } @@ -318,7 +338,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, if (!regionp) { - llwarns << "Object update from unknown region!" << llendl; + llwarns << "Object update from unknown region! " << region_handle << llendl; return; } @@ -357,7 +377,6 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, U8 compbuffer[2048]; S32 uncompressed_length = 2048; S32 compressed_length; - compressed_dp.reset(); U32 flags = 0; @@ -398,7 +417,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, gMessageSystem->getSenderPort()); if (fullid.isNull()) { - //llwarns << "update for unknown localid " << local_id << " host " << gMessageSystem->getSender() << llendl; + // llwarns << "update for unknown localid " << local_id << " host " << gMessageSystem->getSender() << ":" << gMessageSystem->getSenderPort() << llendl; mNumUnknownUpdates++; } } @@ -412,7 +431,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, gMessageSystem->getSenderPort()); if (fullid.isNull()) { - //llwarns << "update for unknown localid " << local_id << " host " << gMessageSystem->getSender() << llendl; + // llwarns << "update for unknown localid " << local_id << " host " << gMessageSystem->getSender() << llendl; mNumUnknownUpdates++; } } @@ -420,19 +439,43 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, { mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FullID, fullid, i); mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i); - // llinfos << "Full Update, obj " << local_id << ", global ID" << fullid << "from " << mesgsys->getSender() << llendl; + // llinfos << "Full Update, obj " << local_id << ", global ID" << fullid << "from " << mesgsys->getSender() << llendl; } objectp = findObject(fullid); // This looks like it will break if the local_id of the object doesn't change // upon boundary crossing, but we check for region id matching later... - if (objectp && (objectp->mLocalID != local_id)) + // Reset object local id and region pointer if things have changed + if (objectp && + ((objectp->mLocalID != local_id) || + (objectp->getRegion() != regionp))) { + //if (objectp->getRegion()) + //{ + // llinfos << "Local ID change: Removing object from table, local ID " << objectp->mLocalID + // << ", id from message " << local_id << ", from " + // << LLHost(objectp->getRegion()->getHost().getAddress(), objectp->getRegion()->getHost().getPort()) + // << ", full id " << fullid + // << ", objects id " << objectp->getID() + // << ", regionp " << (U32) regionp << ", object region " << (U32) objectp->getRegion() + // << llendl; + //} removeFromLocalIDTable(*objectp); setUUIDAndLocal(fullid, local_id, gMessageSystem->getSenderIP(), gMessageSystem->getSenderPort()); + + if (objectp->mLocalID != local_id) + { // Update local ID in object with the one sent from the region + objectp->mLocalID = local_id; + } + + if (objectp->getRegion() != regionp) + { // Object changed region, so update it + objectp->setRegion(regionp); + objectp->updateRegion(regionp); // for LLVOAvatar + } } if (!objectp) @@ -441,7 +484,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, { if (update_type == OUT_TERSE_IMPROVED) { - // llinfos << "terse update for an unknown object:" << fullid << llendl; + // llinfos << "terse update for an unknown object:" << fullid << llendl; continue; } } @@ -452,7 +495,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, { if (update_type != OUT_FULL) { -// llinfos << "terse update for an unknown object:" << fullid << llendl; + // llinfos << "terse update for an unknown object:" << fullid << llendl; continue; } @@ -462,7 +505,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, if (mDeadObjects.find(fullid) != mDeadObjects.end()) { mNumDeadObjectUpdates++; - //llinfos << "update for a dead object:" << fullid << llendl; + // llinfos << "update for a dead object:" << fullid << llendl; continue; } #endif @@ -475,20 +518,6 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, justCreated = TRUE; mNumNewObjects++; } - else - { - if (objectp->getRegion() != regionp) - { - // Object has changed region! Update lookup tables, set region pointer. - removeFromLocalIDTable(*objectp); - setUUIDAndLocal(fullid, - local_id, - gMessageSystem->getSenderIP(), - gMessageSystem->getSenderPort()); - objectp->setRegion(regionp); - } - objectp->updateRegion(regionp); // for LLVOAvatar - } if (objectp->isDead()) @@ -623,7 +652,7 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent) mCurLazyUpdateIndex = 0; } - mCurBin = (++mCurBin) % NUM_BINS; + mCurBin = (mCurBin + 1) % NUM_BINS; LLVOAvatar::cullAvatarsByPixelArea(); } @@ -808,6 +837,14 @@ void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp) // Remove from object map so noone can look it up. mUUIDObjectMap.erase(objectp->mID); + + //if (objectp->getRegion()) + //{ + // llinfos << "cleanupReferences removing object from table, local ID " << objectp->mLocalID << ", ip " + // << objectp->getRegion()->getHost().getAddress() << ":" + // << objectp->getRegion()->getHost().getPort() << llendl; + //} + removeFromLocalIDTable(*objectp); if (objectp->onActiveList()) diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 3cc379821a..273ca8bd1a 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1502,11 +1502,6 @@ void LLViewerWindow::initWorldUI() // currently needs to happen before initializing chat or IM LLFloaterReg::getInstance("communicate"); - if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") ) - { - LLFloaterChat::loadHistory(); - } - LLRect morph_view_rect = full_window; morph_view_rect.stretch( -STATUS_BAR_HEIGHT ); morph_view_rect.mTop = full_window.mTop - 32; diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 6401389c8f..ca028269fe 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -1664,7 +1664,6 @@ void LLVoiceClient::stateMachine() // SLIM SDK: these arguments are no longer necessary. // std::string args = " -p tcp -h -c"; std::string args; - std::string cmd; std::string loglevel = gSavedSettings.getString("VivoxDebugLevel"); if(loglevel.empty()) @@ -1679,17 +1678,18 @@ void LLVoiceClient::stateMachine() #if LL_WINDOWS PROCESS_INFORMATION pinfo; - STARTUPINFOA sinfo; + STARTUPINFOW sinfo; memset(&sinfo, 0, sizeof(sinfo)); - std::string exe_dir = gDirUtilp->getAppRODataDir(); - cmd = "SLVoice.exe"; - cmd += args; - - // So retarded. Windows requires that the second parameter to CreateProcessA be a writable (non-const) string... - char *args2 = new char[args.size() + 1]; - strcpy(args2, args.c_str()); - if(!CreateProcessA(exe_path.c_str(), args2, NULL, NULL, FALSE, 0, NULL, exe_dir.c_str(), &sinfo, &pinfo)) + std::string exe_dir = gDirUtilp->getExecutableDir(); + + llutf16string exe_path16 = utf8str_to_utf16str(exe_path); + llutf16string exe_dir16 = utf8str_to_utf16str(exe_dir); + llutf16string args16 = utf8str_to_utf16str(args); + // Create a writeable copy to keep Windows happy. + U16 *argscpy_16 = new U16[args16.size() + 1]; + wcscpy_s(argscpy_16,args16.size()+1,args16.c_str()); + if(!CreateProcessW(exe_path16.c_str(), argscpy_16, NULL, NULL, FALSE, 0, NULL, exe_dir16.c_str(), &sinfo, &pinfo)) { // DWORD dwErr = GetLastError(); } @@ -1701,7 +1701,7 @@ void LLVoiceClient::stateMachine() CloseHandle(pinfo.hThread); // stops leaks - nothing else } - delete[] args2; + delete[] argscpy_16; #else // LL_WINDOWS // This should be the same for mac and linux { @@ -4972,7 +4972,7 @@ void LLVoiceClient::sessionState::removeAllParticipants() if(!mParticipantsByUUID.empty()) { - LL_ERRS("Voice") << "Internal error: empty URI map, non-empty UUID map" << LL_ENDL + LL_ERRS("Voice") << "Internal error: empty URI map, non-empty UUID map" << LL_ENDL; } } @@ -6488,7 +6488,7 @@ void LLVoiceClient::deleteSession(sessionState *session) { if(iter->second != session) { - LL_ERRS("Voice") << "Internal error: session mismatch" << LL_ENDL + LL_ERRS("Voice") << "Internal error: session mismatch" << LL_ENDL; } mSessionsByHandle.erase(iter); } @@ -6528,7 +6528,7 @@ void LLVoiceClient::deleteAllSessions() if(!mSessionsByHandle.empty()) { - LL_ERRS("Voice") << "Internal error: empty session map, non-empty handle map" << LL_ENDL + LL_ERRS("Voice") << "Internal error: empty session map, non-empty handle map" << LL_ENDL; } } diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index 33b86660fa..d44c543266 100644 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -965,7 +965,7 @@ void LLVOSky::calcAtmospherics(void) // and vary_sunlight will work properly with moon light F32 lighty = unclamped_lightnorm[1]; - if(lighty < NIGHTTIME_ELEVATION_COS) + if(lighty < LLSky::NIGHTTIME_ELEVATION_COS) { lighty = -lighty; } diff --git a/indra/newview/llvosky.h b/indra/newview/llvosky.h index 466cdfdcd0..62c934fb41 100644 --- a/indra/newview/llvosky.h +++ b/indra/newview/llvosky.h @@ -147,7 +147,7 @@ protected: static S32 getResolution() { return sResolution; } static S32 getCurrent() { return sCurrent; } - static S32 stepCurrent() { return (sCurrent = ++sCurrent % 2); } + static S32 stepCurrent() { return (sCurrent = (sCurrent + 1) % 2); } static S32 getNext() { return ((sCurrent+1) % 2); } static S32 getWhich(const BOOL curr) { return curr ? sCurrent : getNext(); } diff --git a/indra/newview/llwaterparammanager.cpp b/indra/newview/llwaterparammanager.cpp index 136ffe607d..c8cc6a3d8e 100644 --- a/indra/newview/llwaterparammanager.cpp +++ b/indra/newview/llwaterparammanager.cpp @@ -304,7 +304,7 @@ void LLWaterParamManager::update(LLViewerCamera * cam) mWaterPlane = LLVector4(enorm.v[0], enorm.v[1], enorm.v[2], -ep.dot(enorm)); LLVector3 sunMoonDir; - if (gSky.getSunDirection().mV[2] > NIGHTTIME_ELEVATION_COS) + if (gSky.getSunDirection().mV[2] > LLSky::NIGHTTIME_ELEVATION_COS) { sunMoonDir = gSky.getSunDirection(); } diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp index 4bf64816c7..1581153c19 100644 --- a/indra/newview/llwlparammanager.cpp +++ b/indra/newview/llwlparammanager.cpp @@ -317,7 +317,7 @@ void LLWLParamManager::propagateParameters(void) { mLightDir = sunDir; } - else if(sunDir.mV[1] < 0 && sunDir.mV[1] > NIGHTTIME_ELEVATION_COS) + else if(sunDir.mV[1] < 0 && sunDir.mV[1] > LLSky::NIGHTTIME_ELEVATION_COS) { // clamp v1 to 0 so sun never points up and causes weirdness on some machines LLVector3 vec(sunDir.mV[0], sunDir.mV[1], sunDir.mV[2]); diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index a2fd0f0d9c..58ff84a8a6 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -150,11 +150,11 @@ XMLRPC_VALUE LLXMLRPCValue::getValue() const class LLXMLRPCTransaction::Impl { public: - typedef LLXMLRPCTransaction::Status Status; + typedef LLXMLRPCTransaction::EStatus EStatus; LLCurlEasyRequest* mCurlRequest; - Status mStatus; + EStatus mStatus; CURLcode mCurlCode; std::string mStatusMessage; std::string mStatusURI; @@ -176,7 +176,7 @@ public: bool process(); - void setStatus(Status code, + void setStatus(EStatus code, const std::string& message = "", const std::string& uri = ""); void setCurlStatus(CURLcode); @@ -385,7 +385,7 @@ bool LLXMLRPCTransaction::Impl::process() return false; } -void LLXMLRPCTransaction::Impl::setStatus(Status status, +void LLXMLRPCTransaction::Impl::setStatus(EStatus status, const std::string& message, const std::string& uri) { mStatus = status; @@ -509,7 +509,7 @@ bool LLXMLRPCTransaction::process() return impl.process(); } -LLXMLRPCTransaction::Status LLXMLRPCTransaction::status(int* curlCode) +LLXMLRPCTransaction::EStatus LLXMLRPCTransaction::status(int* curlCode) { if (curlCode) { diff --git a/indra/newview/llxmlrpctransaction.h b/indra/newview/llxmlrpctransaction.h index 528451fcb2..c835423d67 100644 --- a/indra/newview/llxmlrpctransaction.h +++ b/indra/newview/llxmlrpctransaction.h @@ -100,7 +100,7 @@ public: ~LLXMLRPCTransaction(); - typedef enum { + typedef enum e_status { StatusNotStarted, StatusStarted, StatusDownloading, @@ -108,12 +108,12 @@ public: StatusCURLError, StatusXMLRPCError, StatusOtherError - } Status; + } EStatus; bool process(); // run the request a little, returns true when done - Status status(int* curlCode); + EStatus status(int* curlCode); // return status, and extended CURL code, if code isn't null std::string statusMessage(); // return a message string, suitable for showing the user diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index c736d0ccc8..3800b9223d 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -35,7 +35,7 @@ #include "pipeline.h" // library includes -#include "llaudioengine.h" // For MAX_BUFFERS for debugging. +#include "llaudioengine.h" // For debugging. #include "imageids.h" #include "llerror.h" #include "llviewercontrol.h" @@ -4289,7 +4289,7 @@ void LLPipeline::setupAvatarLights(BOOL for_edit) } } F32 backlight_mag; - if (gSky.getSunDirection().mV[2] >= NIGHTTIME_ELEVATION_COS) + if (gSky.getSunDirection().mV[2] >= LLSky::NIGHTTIME_ELEVATION_COS) { backlight_mag = BACKLIGHT_DAY_MAGNITUDE_OBJECT; } @@ -4475,7 +4475,7 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) // Light 0 = Sun or Moon (All objects) { - if (gSky.getSunDirection().mV[2] >= NIGHTTIME_ELEVATION_COS) + if (gSky.getSunDirection().mV[2] >= LLSky::NIGHTTIME_ELEVATION_COS) { mSunDir.setVec(gSky.getSunDirection()); mSunDiffuse.setVec(gSky.getSunDiffuseColor()); diff --git a/indra/newview/res-sdl/arrow.BMP b/indra/newview/res-sdl/arrow.BMP new file mode 100644 index 0000000000..a8f6da64b5 Binary files /dev/null and b/indra/newview/res-sdl/arrow.BMP differ diff --git a/indra/newview/res-sdl/arrowcop.BMP b/indra/newview/res-sdl/arrowcop.BMP new file mode 100644 index 0000000000..1a26a0df34 Binary files /dev/null and b/indra/newview/res-sdl/arrowcop.BMP differ diff --git a/indra/newview/res-sdl/arrowcopmulti.BMP b/indra/newview/res-sdl/arrowcopmulti.BMP new file mode 100644 index 0000000000..48f153cef6 Binary files /dev/null and b/indra/newview/res-sdl/arrowcopmulti.BMP differ diff --git a/indra/newview/res-sdl/arrowdrag.BMP b/indra/newview/res-sdl/arrowdrag.BMP new file mode 100644 index 0000000000..cd868eec20 Binary files /dev/null and b/indra/newview/res-sdl/arrowdrag.BMP differ diff --git a/indra/newview/res-sdl/circleandline.BMP b/indra/newview/res-sdl/circleandline.BMP new file mode 100644 index 0000000000..284ae8b7d5 Binary files /dev/null and b/indra/newview/res-sdl/circleandline.BMP differ diff --git a/indra/newview/res-sdl/cross.BMP b/indra/newview/res-sdl/cross.BMP new file mode 100644 index 0000000000..0b4672d4d6 Binary files /dev/null and b/indra/newview/res-sdl/cross.BMP differ diff --git a/indra/newview/res-sdl/hand.BMP b/indra/newview/res-sdl/hand.BMP new file mode 100644 index 0000000000..2a092fbb7f Binary files /dev/null and b/indra/newview/res-sdl/hand.BMP differ diff --git a/indra/newview/res-sdl/ibeam.BMP b/indra/newview/res-sdl/ibeam.BMP new file mode 100644 index 0000000000..820904a228 Binary files /dev/null and b/indra/newview/res-sdl/ibeam.BMP differ diff --git a/indra/newview/res-sdl/ll_icon.BMP b/indra/newview/res-sdl/ll_icon.BMP new file mode 100644 index 0000000000..4a44aafbfa Binary files /dev/null and b/indra/newview/res-sdl/ll_icon.BMP differ diff --git a/indra/newview/res-sdl/llarrow.BMP b/indra/newview/res-sdl/llarrow.BMP new file mode 100644 index 0000000000..a8f6da64b5 Binary files /dev/null and b/indra/newview/res-sdl/llarrow.BMP differ diff --git a/indra/newview/res-sdl/llarrowdrag.BMP b/indra/newview/res-sdl/llarrowdrag.BMP new file mode 100644 index 0000000000..cd868eec20 Binary files /dev/null and b/indra/newview/res-sdl/llarrowdrag.BMP differ diff --git a/indra/newview/res-sdl/llarrowdragmulti.BMP b/indra/newview/res-sdl/llarrowdragmulti.BMP new file mode 100644 index 0000000000..fb528bc92d Binary files /dev/null and b/indra/newview/res-sdl/llarrowdragmulti.BMP differ diff --git a/indra/newview/res-sdl/llarrowlocked.BMP b/indra/newview/res-sdl/llarrowlocked.BMP new file mode 100644 index 0000000000..0aaa441ab1 Binary files /dev/null and b/indra/newview/res-sdl/llarrowlocked.BMP differ diff --git a/indra/newview/res-sdl/llgrablocked.BMP b/indra/newview/res-sdl/llgrablocked.BMP new file mode 100644 index 0000000000..847439670f Binary files /dev/null and b/indra/newview/res-sdl/llgrablocked.BMP differ diff --git a/indra/newview/res-sdl/llno.BMP b/indra/newview/res-sdl/llno.BMP new file mode 100644 index 0000000000..284ae8b7d5 Binary files /dev/null and b/indra/newview/res-sdl/llno.BMP differ diff --git a/indra/newview/res-sdl/llnolocked.BMP b/indra/newview/res-sdl/llnolocked.BMP new file mode 100644 index 0000000000..61f0170cb3 Binary files /dev/null and b/indra/newview/res-sdl/llnolocked.BMP differ diff --git a/indra/newview/res-sdl/lltoolcamera.BMP b/indra/newview/res-sdl/lltoolcamera.BMP new file mode 100644 index 0000000000..c961d7a49c Binary files /dev/null and b/indra/newview/res-sdl/lltoolcamera.BMP differ diff --git a/indra/newview/res-sdl/lltoolcreate.BMP b/indra/newview/res-sdl/lltoolcreate.BMP new file mode 100644 index 0000000000..08a4a9322d Binary files /dev/null and b/indra/newview/res-sdl/lltoolcreate.BMP differ diff --git a/indra/newview/res-sdl/lltoolfocus.BMP b/indra/newview/res-sdl/lltoolfocus.BMP new file mode 100644 index 0000000000..afb90a95e3 Binary files /dev/null and b/indra/newview/res-sdl/lltoolfocus.BMP differ diff --git a/indra/newview/res-sdl/lltoolgrab.BMP b/indra/newview/res-sdl/lltoolgrab.BMP new file mode 100644 index 0000000000..f2ac68bf3c Binary files /dev/null and b/indra/newview/res-sdl/lltoolgrab.BMP differ diff --git a/indra/newview/res-sdl/lltoolland.BMP b/indra/newview/res-sdl/lltoolland.BMP new file mode 100644 index 0000000000..64e6365625 Binary files /dev/null and b/indra/newview/res-sdl/lltoolland.BMP differ diff --git a/indra/newview/res-sdl/lltoolpan.BMP b/indra/newview/res-sdl/lltoolpan.BMP new file mode 100644 index 0000000000..ffbef21ec7 Binary files /dev/null and b/indra/newview/res-sdl/lltoolpan.BMP differ diff --git a/indra/newview/res-sdl/lltoolpipette.BMP b/indra/newview/res-sdl/lltoolpipette.BMP new file mode 100644 index 0000000000..2d27118289 Binary files /dev/null and b/indra/newview/res-sdl/lltoolpipette.BMP differ diff --git a/indra/newview/res-sdl/lltoolrotate.BMP b/indra/newview/res-sdl/lltoolrotate.BMP new file mode 100644 index 0000000000..dd84673018 Binary files /dev/null and b/indra/newview/res-sdl/lltoolrotate.BMP differ diff --git a/indra/newview/res-sdl/lltoolscale.BMP b/indra/newview/res-sdl/lltoolscale.BMP new file mode 100644 index 0000000000..882515e5e3 Binary files /dev/null and b/indra/newview/res-sdl/lltoolscale.BMP differ diff --git a/indra/newview/res-sdl/lltooltranslate.BMP b/indra/newview/res-sdl/lltooltranslate.BMP new file mode 100644 index 0000000000..d084f6a026 Binary files /dev/null and b/indra/newview/res-sdl/lltooltranslate.BMP differ diff --git a/indra/newview/res-sdl/lltoolzoomin.BMP b/indra/newview/res-sdl/lltoolzoomin.BMP new file mode 100644 index 0000000000..e4e46cc702 Binary files /dev/null and b/indra/newview/res-sdl/lltoolzoomin.BMP differ diff --git a/indra/newview/res-sdl/lltoolzoomout.BMP b/indra/newview/res-sdl/lltoolzoomout.BMP new file mode 100644 index 0000000000..7f958383ab Binary files /dev/null and b/indra/newview/res-sdl/lltoolzoomout.BMP differ diff --git a/indra/newview/res-sdl/sizenesw.BMP b/indra/newview/res-sdl/sizenesw.BMP new file mode 100644 index 0000000000..559579f40e Binary files /dev/null and b/indra/newview/res-sdl/sizenesw.BMP differ diff --git a/indra/newview/res-sdl/sizens.BMP b/indra/newview/res-sdl/sizens.BMP new file mode 100644 index 0000000000..8373077dff Binary files /dev/null and b/indra/newview/res-sdl/sizens.BMP differ diff --git a/indra/newview/res-sdl/sizenwse.BMP b/indra/newview/res-sdl/sizenwse.BMP new file mode 100644 index 0000000000..6d069fa765 Binary files /dev/null and b/indra/newview/res-sdl/sizenwse.BMP differ diff --git a/indra/newview/res-sdl/sizewe.BMP b/indra/newview/res-sdl/sizewe.BMP new file mode 100644 index 0000000000..878df453a4 Binary files /dev/null and b/indra/newview/res-sdl/sizewe.BMP differ diff --git a/indra/newview/res-sdl/toolmediaopen.BMP b/indra/newview/res-sdl/toolmediaopen.BMP new file mode 100644 index 0000000000..ac4b231994 Binary files /dev/null and b/indra/newview/res-sdl/toolmediaopen.BMP differ diff --git a/indra/newview/res-sdl/toolpause.BMP b/indra/newview/res-sdl/toolpause.BMP new file mode 100644 index 0000000000..dd2c6857d2 Binary files /dev/null and b/indra/newview/res-sdl/toolpause.BMP differ diff --git a/indra/newview/res-sdl/toolpickobject.BMP b/indra/newview/res-sdl/toolpickobject.BMP new file mode 100644 index 0000000000..25469fc3a8 Binary files /dev/null and b/indra/newview/res-sdl/toolpickobject.BMP differ diff --git a/indra/newview/res-sdl/toolpickobject2.BMP b/indra/newview/res-sdl/toolpickobject2.BMP new file mode 100644 index 0000000000..09df69e675 Binary files /dev/null and b/indra/newview/res-sdl/toolpickobject2.BMP differ diff --git a/indra/newview/res-sdl/toolpickobject3.BMP b/indra/newview/res-sdl/toolpickobject3.BMP new file mode 100644 index 0000000000..fc28698050 Binary files /dev/null and b/indra/newview/res-sdl/toolpickobject3.BMP differ diff --git a/indra/newview/res-sdl/toolplay.BMP b/indra/newview/res-sdl/toolplay.BMP new file mode 100644 index 0000000000..9c40d7dbec Binary files /dev/null and b/indra/newview/res-sdl/toolplay.BMP differ diff --git a/indra/newview/res-sdl/wait.BMP b/indra/newview/res-sdl/wait.BMP new file mode 100644 index 0000000000..26dec59afe Binary files /dev/null and b/indra/newview/res-sdl/wait.BMP differ diff --git a/indra/newview/res-sdl/working.BMP b/indra/newview/res-sdl/working.BMP new file mode 100644 index 0000000000..26dec59afe Binary files /dev/null and b/indra/newview/res-sdl/working.BMP differ diff --git a/indra/newview/skins/default/xui/en/floater_auction.xml b/indra/newview/skins/default/xui/en/floater_auction.xml index 29f8b49794..fb0994b4cd 100644 --- a/indra/newview/skins/default/xui/en/floater_auction.xml +++ b/indra/newview/skins/default/xui/en/floater_auction.xml @@ -1,9 +1,9 @@ + width="150"> + + diff --git a/indra/newview/skins/default/xui/en/floater_preview_texture.xml b/indra/newview/skins/default/xui/en/floater_preview_texture.xml index a243cb399e..5ee136c422 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_texture.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_texture.xml @@ -49,7 +49,7 @@ layout="topleft" left="80" name="Discard" - top="302" + top="283" width="100" /> + width="222" + sort_column="1"> + shortcut="control|M" + use_mac_ctrl="true"> @@ -981,6 +982,57 @@ + + + + + + + + + + + + + + + + + + + shortcut="control|shift|3" + use_mac_ctrl="true"> @@ -1615,7 +1668,8 @@ label="Debug Console" layout="topleft" name="Debug Console" - shortcut="control|shift|4"> + shortcut="control|shift|4" + use_mac_ctrl="true"> @@ -1627,7 +1681,8 @@ label="Fast Timers" layout="topleft" name="Fast Timers" - shortcut="control|shift|9"> + shortcut="control|shift|9" + use_mac_ctrl="true"> @@ -1639,7 +1694,8 @@ label="Memory" layout="topleft" name="Memory" - shortcut="control|shift|0"> + shortcut="control|shift|0" + use_mac_ctrl="true"> @@ -1651,7 +1707,8 @@ label="Notifications Console" layout="topleft" name="Notifications" - shortcut="control|shift|5"> + shortcut="control|shift|5" + use_mac_ctrl="true"> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 91c19badfa..217178a5ef 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -483,6 +483,20 @@ Joining this group costs L$[COST]. You do not have enough L$ to join this group. + +Creating this group will cost L$100. +Groups need more than one member, or they are deleted forever. +Please invite members within 48 hours. + + + - + - - -Creating this group will cost L$100. -Groups need more than one member, or they are deleted forever. -Please invite members within 48 hours. - - diff --git a/indra/newview/skins/default/xui/en/panel_group_general.xml b/indra/newview/skins/default/xui/en/panel_group_general.xml index 9a4480127d..6f01202680 100644 --- a/indra/newview/skins/default/xui/en/panel_group_general.xml +++ b/indra/newview/skins/default/xui/en/panel_group_general.xml @@ -212,4 +212,4 @@ Hover your mouse over the options for more help. value="Not Mature" /> - \ No newline at end of file + diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml index 06ecfdc995..f7d7d52b68 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml @@ -217,7 +217,7 @@ My Avatar: width="237" top_pad="0"/> - - - \ No newline at end of file + diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index f620e8f2d7..360fd3c2db 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -230,8 +230,10 @@ Yes (Happy) Yes + Loading... Offline + None found. OK @@ -2110,6 +2112,15 @@ Expected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh Add Landmark... Edit Landmark... + + Ctrl- + Cmd- + Opt- + Shift- + Ctrl+ + Alt+ + Shift+ + File Saved Receiving @@ -2225,9 +2236,8 @@ Running in window. Can't find suitable pixel format Can't get pixel format description - [APP_NAME] requires True Color (32-bit) to run in a window. -Please go to Control Panels > Display > Settings and set the screen to 32-bit color. -Alternately, if you choose to run fullscreen, [APP_NAME] will automatically adjust the screen each time it runs. + [APP_NAME] requires True Color (32-bit) to run. +Please go to your computer's display settings and set the color mode to 32-bit. [APP_NAME] is unable to run because it can't get an 8 bit alpha channel. Usually this is due to video card driver issues. diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 545fa29675..89f916937b 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -696,20 +696,30 @@ class Linux_i686Manifest(LinuxManifest): #self.path("secondlife-i686.supp") if self.prefix("../../libraries/i686-linux/lib_release_client", dst="lib"): - #self.path("libkdu_v42R.so", "libkdu.so") - self.path("libfmod-3.75.so") self.path("libapr-1.so.0") self.path("libaprutil-1.so.0") self.path("libdb-4.2.so") self.path("libcrypto.so.0.9.7") self.path("libexpat.so.1") self.path("libssl.so.0.9.7") - self.path("libuuid.so", "libuuid.so.1") + self.path("libuuid.so.1") self.path("libSDL-1.2.so.0") self.path("libELFIO.so") self.path("libopenjpeg.so.1.3.0", "libopenjpeg.so.1.3") self.path("libalut.so") self.path("libopenal.so", "libopenal.so.1") + try: + self.path("libkdu_v42R.so", "libkdu.so") + pass + except: + print "Skipping libkdu_v42R.so - not found" + pass + try: + self.path("libfmod-3.75.so") + pass + except: + print "Skipping libkdu_v42R.so - not found" + pass self.end_prefix("lib") # Vivox runtimes diff --git a/indra/test/lltut.h b/indra/test/lltut.h index 47ea9d3f9e..bbb437c3f9 100644 --- a/indra/test/lltut.h +++ b/indra/test/lltut.h @@ -74,7 +74,7 @@ namespace tut inline void ensure_memory_matches(const char* msg,const void* actual, U32 actual_len, const void* expected,U32 expected_len) { if((expected_len != actual_len) || - (memcmp(actual, expected, actual_len) != 0)) + (std::memcmp(actual, expected, actual_len) != 0)) { std::stringstream ss; ss << (msg?msg:"") << (msg?": ":"") << "not equal"; diff --git a/install.xml b/install.xml index e7a7648345..44224664ca 100644 --- a/install.xml +++ b/install.xml @@ -53,26 +53,12 @@ lgpl packages - darwin - - md5sum - 40b8a63b553d91304588fba6796d7cc1 - url - http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/SDL-1.2.5-darwin-20091006.tar.bz2 - linux md5sum - 298fd8a3351f6a8d757d205a1e9ad82f - url - http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/SDL-1.2.12-linux-20091006.tar.bz2 - - windows - - md5sum - 33bb17ecbef6cdadff533d97135f3a56 + fce0ff7d2cdf0f36c1647e6a3916e29e url - http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/SDL-1.2.5-windows-20091006.tar.bz2 + http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/SDL-1.2.12-linux-20090218.tar.bz2 -- cgit v1.3 From e3cb3e9e8d25f52d3127ab959e563b6287d17cdb Mon Sep 17 00:00:00 2001 From: Richard Nelson Date: Wed, 14 Oct 2009 23:13:16 +0000 Subject: fixed a bug in LLFastTimer data gathering, and made them even faster (122 cycles on my 2.5Ghz Xeon) can call LLFastTimer::nextFrame with timers still on the stack...first step towards more flexible data gathering LLInstanceTracker works with statically allocated instances now reviewed by Brad --- indra/llcommon/llfasttimer.h | 139 +++++++++++++++++++++++++++---------- indra/llcommon/llinstancetracker.h | 15 +--- 2 files changed, 105 insertions(+), 49 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index c2f23f6ff6..b900be925b 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -37,7 +37,75 @@ #define FAST_TIMER_ON 1 -U64 get_cpu_clock_count(); +#if LL_WINDOWS + +// shift off lower 8 bits for lower resolution but longer term timing +// on 1Ghz machine, a 32-bit word will hold ~1000 seconds of timing +inline U32 get_cpu_clock_count_32() +{ + U32 ret_val; + __asm + { + _emit 0x0f + _emit 0x31 + shr eax,8 + shl edx,24 + or eax, edx + mov dword ptr [ret_val], eax + } + return ret_val; +} + +// return full timer value, still shifted by 8 bits +inline U64 get_cpu_clock_count_64() +{ + U64 ret_val; + __asm + { + _emit 0x0f + _emit 0x31 + mov eax,eax + mov edx,edx + mov dword ptr [ret_val+4], edx + mov dword ptr [ret_val], eax + } + return ret_val >> 8; +} + +#endif // LL_WINDOWS + +#if (LL_LINUX || LL_SOLARIS || LL_DARWIN) && (defined(__i386__) || defined(__amd64__)) +inline U32 get_cpu_clock_count_32() +{ + U64 x; + __asm__ volatile (".byte 0x0f, 0x31": "=A"(x)); + return (U32)x; +} + +inline U32 get_cpu_clock_count_64() +{ + U64 x; + __asm__ volatile (".byte 0x0f, 0x31": "=A"(x)); + return x; +} +#endif + +#if ( LL_DARWIN && !(defined(__i386__) || defined(__amd64__))) || (LL_SOLARIS && defined(__sparc__)) +// +// Mac PPC (deprecated) & Solaris SPARC implementation of CPU clock +// +// Just use gettimeofday implementation for now + +inline U32 get_cpu_clock_count_32() +{ + return (U32)get_clock_count(); +} + +inline U32 get_cpu_clock_count_64() +{ + return get_clock_count(); +} +#endif class LLMutex; @@ -52,13 +120,14 @@ public: class NamedTimer : public LLInstanceTracker { + friend class DeclareTimer; public: ~NamedTimer(); enum { HISTORY_NUM = 60 }; - const std::string& getName() { return mName; } - NamedTimer* getParent() { return mParent; } + const std::string& getName() const { return mName; } + NamedTimer* getParent() const { return mParent; } void setParent(NamedTimer* parent); S32 getDepth(); std::string getToolTip(S32 history_index = -1); @@ -71,11 +140,11 @@ public: void setCollapsed(bool collapsed) { mCollapsed = collapsed; } bool getCollapsed() const { return mCollapsed; } - U64 getCountAverage() const { return mCountAverage; } - U64 getCallAverage() const { return mCallAverage; } + U32 getCountAverage() const { return mCountAverage; } + U32 getCallAverage() const { return mCallAverage; } - U64 getHistoricalCount(S32 history_index = 0) const; - U64 getHistoricalCalls(S32 history_index = 0) const; + U32 getHistoricalCount(S32 history_index = 0) const; + U32 getHistoricalCalls(S32 history_index = 0) const; static NamedTimer& getRootNamedTimer(); @@ -83,8 +152,7 @@ public: { FrameState(NamedTimer* timerp); - U64 mSelfTimeCounter; - U64 mLastStartTime; // most recent time when this timer was started + U32 mSelfTimeCounter; U32 mCalls; FrameState* mParent; // info for caller timer FrameState* mLastCaller; // used to bootstrap tree construction @@ -93,11 +161,6 @@ public: bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame }; - FrameState& getFrameStateFast() const - { - return (*sTimerInfos)[mFrameStateIndex]; - } - S32 getFrameStateIndex() const { return mFrameStateIndex; } FrameState& getFrameState() const; @@ -122,10 +185,7 @@ public: static void resetFrame(); static void reset(); - typedef std::vector info_list_t; - static info_list_t& getFrameStateList(); - static void createFrameStateList(); // must call before any call to getFrameStateList() - + // // members // @@ -133,13 +193,13 @@ public: std::string mName; - U64 mTotalTimeCounter; + U32 mTotalTimeCounter; - U64 mCountAverage; - U64 mCallAverage; + U32 mCountAverage; + U32 mCallAverage; - U64* mCountHistory; - U64* mCallHistory; + U32* mCountHistory; + U32* mCallHistory; // tree structure NamedTimer* mParent; // NamedTimer of caller(parent) @@ -147,41 +207,46 @@ public: bool mCollapsed; // don't show children bool mNeedsSorting; // sort children whenever child added - static info_list_t* sTimerInfos; }; // used to statically declare a new named timer - class DeclareTimer + class DeclareTimer + : public LLInstanceTracker { public: DeclareTimer(const std::string& name, bool open); DeclareTimer(const std::string& name); + static void updateCachedPointers(); + // convertable to NamedTimer::FrameState for convenient usage of LLFastTimer(declared_timer) - operator NamedTimer::FrameState&() { return mNamedTimer.getFrameStateFast(); } + operator NamedTimer::FrameState&() { return *mFrameState; } private: - NamedTimer& mNamedTimer; + NamedTimer& mTimer; + NamedTimer::FrameState* mFrameState; }; public: - enum RootTimerMarker { ROOT }; - static LLMutex* sLogLock; static std::queue sLogQueue; static BOOL sLog; static BOOL sMetricLog; + typedef std::vector info_list_t; + static info_list_t& getFrameStateList(); + + enum RootTimerMarker { ROOT }; LLFastTimer(RootTimerMarker); LLFastTimer(NamedTimer::FrameState& timer) : mFrameState(&timer) { #if FAST_TIMER_ON - NamedTimer::FrameState* frame_state = mFrameState; - U64 cur_time = get_cpu_clock_count(); - frame_state->mLastStartTime = cur_time; + NamedTimer::FrameState* frame_state = &timer; + U32 cur_time = get_cpu_clock_count_32(); mStartSelfTime = cur_time; + mStartTotalTime = cur_time; frame_state->mActiveCount++; frame_state->mCalls++; @@ -197,7 +262,7 @@ public: { #if FAST_TIMER_ON NamedTimer::FrameState* frame_state = mFrameState; - U64 cur_time = get_cpu_clock_count(); + U32 cur_time = get_cpu_clock_count_32(); frame_state->mSelfTimeCounter += cur_time - mStartSelfTime; frame_state->mActiveCount--; @@ -208,7 +273,7 @@ public: frame_state->mLastCaller = last_timer->mFrameState; // we are only tracking self time, so subtract our total time delta from parents - U64 total_time = cur_time - frame_state->mLastStartTime; + U32 total_time = cur_time - mStartTotalTime; last_timer->mStartSelfTime += total_time; #endif } @@ -240,9 +305,11 @@ private: static LLFastTimer* sCurTimer; static S32 sCurFrameIndex; static S32 sLastFrameIndex; + static U64 sLastFrameTime; + static info_list_t* sTimerInfos; - static F64 sCPUClockFrequency; - U64 mStartSelfTime; // start time + time of all child timers + U32 mStartSelfTime; // start time + time of all child timers + U32 mStartTotalTime; // start time + time of all child timers NamedTimer::FrameState* mFrameState; LLFastTimer* mLastTimer; }; diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index ea50acbbc5..de25e364fa 100644 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -71,17 +71,13 @@ private: static std::map& getMap() { - if (! sInstances) - { - sInstances = new std::map; - } + static std::map* sInstances = new std::map(); return *sInstances; } private: KEY mKey; - static std::map* sInstances; }; // explicit specialization for default case where KEY is T* @@ -105,17 +101,10 @@ protected: static std::set& getSet() // called after getReady() but before go() { - if (! sInstances) - { - sInstances = new std::set; - } + static std::set* sInstances = new std::set(); return *sInstances; } - - static std::set* sInstances; }; -template std::map* LLInstanceTracker::sInstances = NULL; -template std::set* LLInstanceTracker::sInstances = NULL; #endif -- cgit v1.3 From 0051f6bc6d421b8f973d801189b9495c311a647b Mon Sep 17 00:00:00 2001 From: Richard Nelson Date: Thu, 15 Oct 2009 02:31:50 +0000 Subject: forgot to shift timing values by 8 bits on mac fixed fast timer values being multiplied by 256 --- indra/llcommon/llfasttimer.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index b900be925b..576e45d2ae 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -79,14 +79,14 @@ inline U32 get_cpu_clock_count_32() { U64 x; __asm__ volatile (".byte 0x0f, 0x31": "=A"(x)); - return (U32)x; + return (U32)x >> 8; } inline U32 get_cpu_clock_count_64() { U64 x; __asm__ volatile (".byte 0x0f, 0x31": "=A"(x)); - return x; + return x >> 8; } #endif -- cgit v1.3 From 423f5b0078d813a14759f9671c11aedadc3a2d78 Mon Sep 17 00:00:00 2001 From: Adam Moss Date: Thu, 15 Oct 2009 16:32:56 +0000 Subject: DEV-41341 tut lltiming test -> llframetimer integration test --- indra/llcommon/CMakeLists.txt | 2 + indra/llcommon/tests/llframetimer_test.cpp | 118 +++++++++++++++++++++++++++++ indra/test/CMakeLists.txt | 1 - 3 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 indra/llcommon/tests/llframetimer_test.cpp (limited to 'indra/llcommon') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 48e053b8ee..10c145e17b 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -247,8 +247,10 @@ LL_ADD_INTEGRATION_TEST(lllazy "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}") +LL_ADD_INTEGRATION_TEST(llframetimer "" "${test_libs}") # *TODO - reenable these once tcmalloc libs no longer break the build. #ADD_BUILD_TEST(llallocator llcommon) #ADD_BUILD_TEST(llallocator_heap_profile llcommon) #ADD_BUILD_TEST(llmemtype llcommon) + diff --git a/indra/llcommon/tests/llframetimer_test.cpp b/indra/llcommon/tests/llframetimer_test.cpp new file mode 100644 index 0000000000..737c996d0f --- /dev/null +++ b/indra/llcommon/tests/llframetimer_test.cpp @@ -0,0 +1,118 @@ +/** + * @file lltiming_tut.cpp + * @date 2006-07-23 + * @brief Tests the timers. + * + * $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 "../llframetimer.h" +#include "../llsd.h" + +#include "../test/lltut.h" + +namespace tut +{ + struct frametimer_test + { + frametimer_test() + { + LLFrameTimer::updateFrameTime(); + } + }; + typedef test_group frametimer_group_t; + typedef frametimer_group_t::object frametimer_object_t; + tut::frametimer_group_t frametimer_instance("frametimer"); + + template<> template<> + void frametimer_object_t::test<1>() + { + F64 seconds_since_epoch = LLFrameTimer::getTotalSeconds(); + LLFrameTimer timer; + timer.setExpiryAt(seconds_since_epoch); + F64 expires_at = timer.expiresAt(); + ensure_distance( + "set expiry matches get expiry", + expires_at, + seconds_since_epoch, + 0.001); + } + + template<> template<> + void frametimer_object_t::test<2>() + { + F64 seconds_since_epoch = LLFrameTimer::getTotalSeconds(); + seconds_since_epoch += 10.0; + LLFrameTimer timer; + timer.setExpiryAt(seconds_since_epoch); + F64 expires_at = timer.expiresAt(); + ensure_distance( + "set expiry matches get expiry 1", + expires_at, + seconds_since_epoch, + 0.001); + seconds_since_epoch += 10.0; + timer.setExpiryAt(seconds_since_epoch); + expires_at = timer.expiresAt(); + ensure_distance( + "set expiry matches get expiry 2", + expires_at, + seconds_since_epoch, + 0.001); + } + template<> template<> + void frametimer_object_t::test<3>() + { + F64 seconds_since_epoch = LLFrameTimer::getTotalSeconds(); + seconds_since_epoch += 2.0; + LLFrameTimer timer; + timer.setExpiryAt(seconds_since_epoch); + ensure("timer not expired on create", !timer.hasExpired()); + int ii; + for(ii = 0; ii < 10; ++ii) + { + ms_sleep(150); + LLFrameTimer::updateFrameTime(); + } + ensure("timer not expired after a bit", !timer.hasExpired()); + for(ii = 0; ii < 10; ++ii) + { + ms_sleep(100); + LLFrameTimer::updateFrameTime(); + } + ensure("timer expired", timer.hasExpired()); + } +/* + template<> template<> + void frametimer_object_t::test<4>() + { + } +*/ +} diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt index a5df23860c..52b370873f 100644 --- a/indra/test/CMakeLists.txt +++ b/indra/test/CMakeLists.txt @@ -58,7 +58,6 @@ set(test_SOURCE_FILES llstreamtools_tut.cpp lltemplatemessagebuilder_tut.cpp lltimestampcache_tut.cpp - lltiming_tut.cpp lltranscode_tut.cpp lltreeiterators_tut.cpp lltut.cpp -- cgit v1.3 From c7df37b5312d60ef5b8b6d41b6c14065cffdb976 Mon Sep 17 00:00:00 2001 From: Adam Moss Date: Thu, 15 Oct 2009 16:49:08 +0000 Subject: DEV-41344 convert monolithic tut lltreeiterators test to a llcommon integration test. --- indra/llcommon/CMakeLists.txt | 3 +- indra/llcommon/tests/lltreeiterators_test.cpp | 1222 +++++++++++++++++++++++++ indra/test/CMakeLists.txt | 1 - 3 files changed, 1224 insertions(+), 2 deletions(-) create mode 100644 indra/llcommon/tests/lltreeiterators_test.cpp (limited to 'indra/llcommon') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 10c145e17b..c8e030623b 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -243,11 +243,12 @@ LL_ADD_PROJECT_UNIT_TESTS(llcommon "${llcommon_TEST_SOURCE_FILES}") set(test_libs llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES}) LL_ADD_INTEGRATION_TEST(commonmisc "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lldate "" "${test_libs}") +LL_ADD_INTEGRATION_TEST(llframetimer "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lllazy "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}") -LL_ADD_INTEGRATION_TEST(llframetimer "" "${test_libs}") +LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}") # *TODO - reenable these once tcmalloc libs no longer break the build. #ADD_BUILD_TEST(llallocator llcommon) diff --git a/indra/llcommon/tests/lltreeiterators_test.cpp b/indra/llcommon/tests/lltreeiterators_test.cpp new file mode 100644 index 0000000000..d6d9f68110 --- /dev/null +++ b/indra/llcommon/tests/lltreeiterators_test.cpp @@ -0,0 +1,1222 @@ +/** + * @file lltreeiterators.cpp + * @author Nat Goodspeed + * @date 2008-08-20 + * @brief Test of lltreeiterators.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$ + */ + +// Precompiled header +#include "linden_common.h" + +#if LL_WINDOWS +#pragma warning (disable : 4180) // qualifier applied to function type has no meaning; ignored +#endif + +// STL headers +// std headers +#include +#include +#include +// external library headers +#include +#include +#include + +// associated header +#include "../lltreeiterators.h" +#include "../llpointer.h" + +#include "../test/lltut.h" + +/***************************************************************************** +* tut test group +*****************************************************************************/ +namespace tut +{ + struct iter_data + { + }; + typedef test_group iter_group; + typedef iter_group::object iter_object; + tut::iter_group ig("lltreeiterators"); +} // namespace tut + +/***************************************************************************** +* boost::get_pointer() specialization for LLPointer<> +*****************************************************************************/ +// This specialization of boost::get_pointer() undoubtedly belongs in +// llmemory.h. It's used by boost::bind() so that you can pass an +// LLPointer as well as a Foo* to a functor such as +// boost::bind(&Foo::method, _1). +//namespace boost +//{ + template + NODE* get_pointer(const LLPointer& ptr) { return ptr.get(); } +//}; + +/***************************************************************************** +* ScopeLabel +*****************************************************************************/ +class ScopeLabel +{ +public: + ScopeLabel(const std::string& label): mLabel(label) + { + std::cout << "Entering " << mLabel << '\n'; + } + ~ScopeLabel() + { + std::cout << "Leaving " << mLabel << '\n'; + } +private: + std::string mLabel; +}; + +/***************************************************************************** +* Cleanup +*****************************************************************************/ +// Yes, we realize this is redundant with auto_ptr and LLPointer and all +// kinds of better mechanisms. But in this particular source file, we need to +// test nodes managed with plain old dumb pointers as well as nodes managed +// with LLPointer, so we introduce this mechanism. +// +// In the general case, when we declare a Cleanup for some pointer, delete the +// pointer when the Cleanup goes out of scope. +template +struct Cleanup +{ + Cleanup(const PTRTYPE& ptr): mPtr(ptr) {} + ~Cleanup() + { + delete mPtr; + } + PTRTYPE mPtr; +}; + +// But when the pointer is an LLPointer, Cleanup is a no-op: +// LLPointer will handle the cleanup automagically. +template +struct Cleanup< LLPointer > +{ + Cleanup(const LLPointer& ptr) {} + ~Cleanup() {} +}; + +/***************************************************************************** +* Expected +*****************************************************************************/ +// Expected is a base class used to capture the expected results -- a sequence +// of string node names -- from one of our traversals of this example data. +// Its subclasses initialize it with a pair of string iterators. It's not +// strictly necessary to customize Expected to model Boost.Range, it's just +// convenient. +struct Expected +{ + template + Expected(ITER begin, ITER end): + strings(begin, end) + {} + /*------ The following are to make Expected work with Boost.Range ------*/ + typedef std::vector container_type; + typedef container_type::iterator iterator; + typedef container_type::const_iterator const_iterator; + typedef container_type::size_type size_type; + container_type strings; + iterator begin() { return strings.begin(); } + iterator end() { return strings.end(); } + size_type size() { return strings.size(); } + const_iterator begin() const { return strings.begin(); } + const_iterator end() const { return strings.end(); } +}; + +// We have a couple of generic Expected template subclasses. This list of +// strings is used for the "else" case when all specializations fail. +const char* bad_strings[] = { "FAIL" }; + +/***************************************************************************** +* verify() +*****************************************************************************/ +// test function: given (an object modeling) a Boost.Range of tree nodes, +// compare the sequence of visited node names with a range of expected name +// strings. Report success both with std::cout output and a bool return. The +// string desc parameter is to identify the different tests. +template +bool verify(const std::string& desc, NODERANGE noderange, STRINGRANGE expected) +{ + typename boost::range_iterator::type + nri = boost::begin(noderange), + nrend = boost::end(noderange); + typename boost::range_iterator::type + sri = boost::begin(expected), + srend = boost::end(expected); + // We choose to loop over both sequences explicitly rather than using + // std::equal() or std::lexicographical_compare(). The latter tells you + // whether one sequence is *less* than the other -- it doesn't tell you + // equality. std::equal() needs you to verify the sequence lengths ahead + // of time. Anyway, comparing explicitly allows us to report much more + // information about any sequence mismatch. + for ( ; nri != nrend && sri != srend; ++nri, ++sri) + { + if ((*nri)->name() != *sri) + { + std::cout << desc << " mismatch: " + << "expected " << *sri << ", got " << (*nri)->name() << "\n"; + return false; + } + } + if (nri != nrend) + { + std::cout << desc << " produced too many items:\n"; + for ( ; nri != nrend; ++nri) + { + std::cout << " " << (*nri)->name() << '\n'; + } + return false; + } + if (sri != srend) + { + std::cout << desc << " produced too few items, omitting:\n"; + for ( ; sri != srend; ++sri) + { + std::cout << " " << *sri << '\n'; + } + return false; + } +// std::cout << desc << " test passed\n"; + return true; +} + +/***************************************************************************** +* PlainNode: LLLinkIter, non-refcounted +*****************************************************************************/ +class PlainNode +{ +public: + PlainNode(const std::string& name, PlainNode* next=NULL): + mName(name), + mNext(next) + {} + ~PlainNode() + { + delete mNext; + } + std::string name() const { return mName; } + PlainNode* next() const { return mNext; } +public: // if this were 'private', couldn't bind mNext + PlainNode* mNext; +private: + std::string mName; +}; + +namespace tut +{ + template<> template<> + void iter_object::test<1>() + { +// set_test_name("LLLinkedIter -- non-refcounted class"); + PlainNode* last(new PlainNode("c")); + PlainNode* second(new PlainNode("b", last)); + PlainNode* first(new PlainNode("a", second)); + Cleanup cleanup(first); + static const char* cseq[] = { "a", "b", "c" }; + Expected seq(boost::begin(cseq), boost::end(cseq)); + std::string desc1("Iterate by public link member"); +// std::cout << desc1 << ":\n"; + // Try instantiating an iterator with NULL. This test is less about + // "did we iterate once?" than "did we avoid blowing up?" + for (LLLinkedIter pni(NULL, boost::bind(&PlainNode::mNext, _1)), end; + pni != end; ++pni) + { +// std::cout << (*pni)->name() << '\n'; + ensure("LLLinkedIter(NULL)", false); + } + ensure(desc1, + verify(desc1, + boost::make_iterator_range(LLLinkedIter(first, + boost::bind(&PlainNode::mNext, _1)), + LLLinkedIter()), + seq)); + std::string desc2("Iterate by next() method"); +// std::cout << desc2 << ":\n"; +// for (LLLinkedIter pni(first, boost::bind(&PlainNode::next, _1)); ! (pni == end); ++pni) +// std::cout << (**pni).name() << '\n'; + ensure(desc2, + verify(desc2, + boost::make_iterator_range(LLLinkedIter(first, + boost::bind(&PlainNode::next, _1)), + LLLinkedIter()), + seq)); + { +// LLLinkedIter pni(first, boost::bind(&PlainNode::next, _1)); +// std::cout << "First is " << (*pni++)->name() << '\n'; +// std::cout << "Second is " << (*pni )->name() << '\n'; + } + { + LLLinkedIter pni(first, boost::bind(&PlainNode::next, _1)); + ensure_equals("first", (*pni++)->name(), "a"); + ensure_equals("second", (*pni )->name(), "b"); + } + } +} // tut + +/***************************************************************************** +* RCNode: LLLinkIter, refcounted +*****************************************************************************/ +class RCNode; +typedef LLPointer RCNodePtr; + +class RCNode: public LLRefCount +{ +public: + RCNode(const std::string& name, const RCNodePtr& next=RCNodePtr()): + mName(name), + mNext(next) + { +// std::cout << "New RCNode(" << mName << ")\n"; + } + RCNode(const RCNode& that): + mName(that.mName), + mNext(that.mNext) + { +// std::cout << "Copy RCNode(" << mName << ")\n"; + } + virtual ~RCNode(); + std::string name() const { return mName; } + RCNodePtr next() const { return mNext; } +public: // if this were 'private', couldn't bind mNext + RCNodePtr mNext; +private: + std::string mName; +}; + +std::ostream& operator<<(std::ostream& out, const RCNode& node) +{ + out << "RCNode(" << node.name() << ')'; + return out; +} + +// This string contains the node name of the last RCNode destroyed. We use it +// to validate that LLLinkedIter in fact contains LLPointer, +// and that therefore an outstanding LLLinkedIter to an instance of a +// refcounted class suffices to keep that instance alive. +std::string last_RCNode_destroyed; + +RCNode::~RCNode() +{ +// std::cout << "Kill " << *this << "\n"; + last_RCNode_destroyed = mName; +} + +namespace tut +{ + template<> template<> + void iter_object::test<2>() + { +// set_test_name("LLLinkedIter -- refcounted class"); + LLLinkedIter rcni, end2; + { +// ScopeLabel label("inner scope"); + RCNodePtr head(new RCNode("x", new RCNode("y", new RCNode("z")))); +// for (rcni = LLLinkedIter(head, boost::bind(&RCNode::mNext, _1)); rcni != end2; ++rcni) +// std::cout << **rcni << '\n'; + rcni = LLLinkedIter(head, boost::bind(&RCNode::next, _1)); + } +// std::cout << "Now the LLLinkedIter is the only remaining reference to RCNode chain\n"; + ensure_equals(last_RCNode_destroyed, ""); + ensure(rcni != end2); + ensure_equals((*rcni)->name(), "x"); + ++rcni; + ensure_equals(last_RCNode_destroyed, "x"); + ensure(rcni != end2); + ensure_equals((*rcni)->name(), "y"); + ++rcni; + ensure_equals(last_RCNode_destroyed, "y"); + ensure(rcni != end2); + ensure_equals((*rcni)->name(), "z"); + ++rcni; + ensure_equals(last_RCNode_destroyed, "z"); + ensure(rcni == end2); + } +} + +/***************************************************************************** +* TreeNode +*****************************************************************************/ +class TreeNode; +typedef LLPointer TreeNodePtr; + +/** + * TreeNode represents a refcounted tree-node class that hasn't (yet) been + * modified to incorporate LLTreeIter methods. This illustrates how you can + * use tree iterators either standalone, or with free functions. + */ +class TreeNode: public LLRefCount +{ +public: + typedef std::vector list_type; + typedef list_type::const_iterator child_iterator; + + // To avoid cycles, use a "weak" raw pointer for the parent link + TreeNode(const std::string& name, TreeNode* parent=0): + mParent(parent), + mName(name) + {} + TreeNodePtr newChild(const std::string& name) + { + TreeNodePtr child(new TreeNode(name, this)); + mChildren.push_back(child); + return child; + } + std::string name() const { return mName; } + TreeNodePtr getParent() const { return mParent; } + child_iterator child_begin() const { return mChildren.begin(); } + child_iterator child_end() const { return mChildren.end(); } +private: + std::string mName; + // To avoid cycles, use a "weak" raw pointer for the parent link + TreeNode* mParent; + list_type mChildren; +}; + +/** + * This is an example of a helper function to facilitate iterating from a + * TreeNode up to the root or down from the root (see LLTreeIter::RootIter). + * + * Example: + * @code + * BOOST_FOREACH(TreeNodePtr node, getRootRange(somenode)) + * { + * std::cout << node->name() << '\n'; + * } + * @endcode + */ +template +boost::iterator_range< LLTreeRootIter > +getRootRange(const TreeNodePtr& node) +{ + typedef LLTreeRootIter iter_type; + typedef boost::iterator_range range_type; + return range_type(iter_type(node, boost::bind(&TreeNode::getParent, _1)), + iter_type()); +} + +/** + * This is an example of a helper function to facilitate walking a given + * TreeNode's subtree in any supported order (see LLTreeIter::WalkIter). + * + * Example: + * @code + * BOOST_FOREACH(TreeNodePtr node, getWalkRange(root)) + * { + * std::cout << node->name() << '\n'; + * } + * @endcode + */ +template +boost::iterator_range< LLTreeWalkIter > +getWalkRange(const TreeNodePtr& node) +{ + typedef LLTreeWalkIter iter_type; + typedef boost::iterator_range range_type; + return range_type(iter_type(node, + boost::bind(&TreeNode::child_begin, _1), + boost::bind(&TreeNode::child_end, _1)), + iter_type()); +} + +/***************************************************************************** +* EnhancedTreeNode +*****************************************************************************/ +class EnhancedTreeNode; +typedef LLPointer EnhancedTreeNodePtr; + +/** + * More typically, you enhance the tree-node class itself with template + * methods like the above. This EnhancedTreeNode class illustrates the + * technique. Normally, of course, you'd simply add these methods to TreeNode; + * we put them in a separate class to preserve the undecorated TreeNode class + * to illustrate (and test) the use of plain tree iterators and standalone + * helper functions. + * + * We originally implemented EnhancedTreeNode as a subclass of TreeNode -- but + * because TreeNode stores and manipulates TreeNodePtrs and TreeNode*s, + * reusing its methods required so much ugly downcast logic that we gave up + * and restated the whole class. Bear in mind that logically these aren't two + * separate classes; logically they're two snapshots of the @em same class at + * different moments in time. + */ +class EnhancedTreeNode: public LLRefCount +{ +public: + /*-------------- The following is restated from TreeNode ---------------*/ + typedef std::vector list_type; + typedef list_type::const_iterator child_iterator; + + // To avoid cycles, use a "weak" raw pointer for the parent link + EnhancedTreeNode(const std::string& name, EnhancedTreeNode* parent=0): + mParent(parent), + mName(name) + {} + EnhancedTreeNodePtr newChild(const std::string& name) + { + EnhancedTreeNodePtr child(new EnhancedTreeNode(name, this)); + mChildren.push_back(child); + return child; + } + std::string name() const { return mName; } + EnhancedTreeNodePtr getParent() const { return mParent; } + child_iterator child_begin() const { return mChildren.begin(); } + child_iterator child_end() const { return mChildren.end(); } + +private: + std::string mName; + // To avoid cycles, use a "weak" raw pointer for the parent link + EnhancedTreeNode* mParent; + list_type mChildren; +public: + /*----- End of TreeNode; what follows is new with EnhancedTreeNode -----*/ + + /** + * Because the type of the iterator range returned by getRootRange() + * depends on the discriminator enum value, instead of a simple typedef we + * use a templated struct. Example usage: + * + * @code + * for (EnhancedTreeNode::root_range::type range = + * somenode->getRootRange(); + * range.first != range.second; ++range.first) + * { + * std::cout << (*range.first)->name() << '\n'; + * } + * @endcode + */ + template + struct root_range + { + typedef boost::iterator_range< LLTreeRootIter > type; + }; + + /** + * Helper method for walking up to (or down from) the tree root. See + * LLTreeIter::RootIter. + * + * Example usage: + * @code + * BOOST_FOREACH(EnhancedTreeNodePtr node, somenode->getRootRange()) + * { + * std::cout << node->name() << '\n'; + * } + * @endcode + */ + template + typename root_range::type getRootRange() const + { + typedef typename root_range::type range_type; + typedef typename range_type::iterator iter_type; + return range_type(iter_type(const_cast(this), + boost::bind(&EnhancedTreeNode::getParent, _1)), + iter_type()); + } + + /** + * Because the type of the iterator range returned by getWalkRange() + * depends on the discriminator enum value, instead of a simple typedef we + * use a templated stuct. Example usage: + * + * @code + * for (EnhancedTreeNode::walk_range::type range = + * somenode->getWalkRange(); + * range.first != range.second; ++range.first) + * { + * std::cout << (*range.first)->name() << '\n'; + * } + * @endcode + */ + template + struct walk_range + { + typedef boost::iterator_range< LLTreeWalkIter > type; + }; + + /** + * Helper method for walking a given node's subtree in any supported + * order (see LLTreeIter::WalkIter). + * + * Example usage: + * @code + * BOOST_FOREACH(EnhancedTreeNodePtr node, somenode->getWalkRange()) + * { + * std::cout << node->name() << '\n'; + * } + * @endcode + */ + template + typename walk_range::type getWalkRange() const + { + typedef typename walk_range::type range_type; + typedef typename range_type::iterator iter_type; + return range_type(iter_type(const_cast(this), + boost::bind(&EnhancedTreeNode::child_begin, _1), + boost::bind(&EnhancedTreeNode::child_end, _1)), + iter_type()); + } +}; + +/***************************************************************************** +* PlainTree +*****************************************************************************/ +struct PlainTree +{ + PlainTree(const std::string& name, PlainTree* parent=0): + mName(name), + mParent(parent), + mNextSibling(0), + mFirstChild(0) + { + mLastChildLink = &mFirstChild; + } + ~PlainTree() + { + delete mNextSibling; + delete mFirstChild; + } + PlainTree* newChild(const std::string& name) + { + PlainTree* child(new PlainTree(name, this)); + *mLastChildLink = child; + mLastChildLink = &child->mNextSibling; + return child; + } + std::string name() const { return mName; } + + std::string mName; + PlainTree* mParent; + PlainTree* mNextSibling; + PlainTree* mFirstChild; + PlainTree** mLastChildLink; +}; + +// This "classic" tree tracks each node's children with a linked list anchored +// at the parent's mFirstChild and linked through each child's mNextSibling. +// LLTreeDFSIter<> and LLTreeBFSIter<> need functors to return begin()/end() +// iterators over a given node's children. But because this tree's children +// aren't stored in an STL container, we can't just export that container's +// begin()/end(). Instead we'll use LLLinkedIter<> to view the hand-maintained +// linked list as an iterator range. The straightforward way to do that would +// be to add child_begin() and child_end() methods. But let's say (for the +// sake of argument) that this struct is so venerable we don't dare modify it +// even to add new methods. Well, we can use free functions (or functors) too. +LLLinkedIter PlainTree_child_begin(PlainTree* node) +{ + return LLLinkedIter(node->mFirstChild, boost::bind(&PlainTree::mNextSibling, _1)); +} + +LLLinkedIter PlainTree_child_end(PlainTree* node) +{ + return LLLinkedIter(); +} + +/** + * This is an example of a helper function to facilitate iterating from a + * PlainTree up to the root or down from the root (see LLTreeIter::RootIter). + * Note that we're simply overloading the same getRootRange() helper function + * name we used for TreeNode. + * + * Example: + * @code + * BOOST_FOREACH(PlainTree* node, getRootRange(somenode)) + * { + * std::cout << node->name() << '\n'; + * } + * @endcode + */ +template +boost::iterator_range< LLTreeRootIter > +getRootRange(PlainTree* node) +{ + typedef LLTreeRootIter iter_type; + typedef boost::iterator_range range_type; + return range_type(iter_type(node, boost::bind(&PlainTree::mParent, _1)), + iter_type()); +} + +/** + * This is an example of a helper function to facilitate walking a given + * PlainTree's subtree in any supported order (see LLTreeIter::WalkIter). Note + * that we're simply overloading the same getWalkRange() helper function name + * we used for TreeNode. + * + * Example: + * @code + * BOOST_FOREACH(PlainTree* node, getWalkRange(root)) + * { + * std::cout << node->name() << '\n'; + * } + * @endcode + */ +template +boost::iterator_range< LLTreeWalkIter > > +getWalkRange(PlainTree* node) +{ + typedef LLTreeWalkIter > iter_type; + typedef boost::iterator_range range_type; + return range_type(iter_type(node, + PlainTree_child_begin, + PlainTree_child_end), + iter_type()); +} + +// We could go through the exercise of writing EnhancedPlainTree containing +// root_range, getRootRange(), walk_range and getWalkRange() members -- but we +// won't. See EnhancedTreeNode for examples. + +/***************************************************************************** +* Generic tree test data +*****************************************************************************/ +template +typename LLPtrTo::type example_tree() +{ + typedef typename LLPtrTo::type NodePtr; + NodePtr root(new NODE("root")); + NodePtr A(root->newChild("A")); + NodePtr A1(A->newChild("A1")); +/* NodePtr A1a*/(A1->newChild("A1a")); +/* NodePtr A1b*/(A1->newChild("A1b")); +/* NodePtr A1c*/(A1->newChild("A1c")); + NodePtr A2(A->newChild("A2")); +/* NodePtr A2a*/(A2->newChild("A2a")); +/* NodePtr A2b*/(A2->newChild("A2b")); +/* NodePtr A2c*/(A2->newChild("A2c")); + NodePtr A3(A->newChild("A3")); +/* NodePtr A3a*/(A3->newChild("A3a")); +/* NodePtr A3b*/(A3->newChild("A3b")); +/* NodePtr A3c*/(A3->newChild("A3c")); + NodePtr B(root->newChild("B")); + NodePtr B1(B->newChild("B1")); +/* NodePtr B1a*/(B1->newChild("B1a")); +/* NodePtr B1b*/(B1->newChild("B1b")); +/* NodePtr B1c*/(B1->newChild("B1c")); + NodePtr B2(B->newChild("B2")); +/* NodePtr B2a*/(B2->newChild("B2a")); +/* NodePtr B2b*/(B2->newChild("B2b")); +/* NodePtr B2c*/(B2->newChild("B2c")); + NodePtr B3(B->newChild("B3")); +/* NodePtr B3a*/(B3->newChild("B3a")); +/* NodePtr B3b*/(B3->newChild("B3b")); +/* NodePtr B3c*/(B3->newChild("B3c")); + NodePtr C(root->newChild("C")); + NodePtr C1(C->newChild("C1")); +/* NodePtr C1a*/(C1->newChild("C1a")); +/* NodePtr C1b*/(C1->newChild("C1b")); +/* NodePtr C1c*/(C1->newChild("C1c")); + NodePtr C2(C->newChild("C2")); +/* NodePtr C2a*/(C2->newChild("C2a")); +/* NodePtr C2b*/(C2->newChild("C2b")); +/* NodePtr C2c*/(C2->newChild("C2c")); + NodePtr C3(C->newChild("C3")); +/* NodePtr C3a*/(C3->newChild("C3a")); +/* NodePtr C3b*/(C3->newChild("C3b")); +/* NodePtr C3c*/(C3->newChild("C3c")); + return root; +} + +// WalkExpected is the list of string node names we expect from a +// WalkIter traversal of our example_tree() data. +template +struct WalkExpected: public Expected +{ + // Initialize with bad_strings: we don't expect to use this generic case, + // only the specializations. Note that for a classic C-style array we must + // pass a pair of iterators rather than extracting boost::begin() and + // boost::end() within the target constructor: a template ctor accepts + // these classic C-style arrays as char** rather than char*[length]. Oh well. + WalkExpected(): Expected(boost::begin(bad_strings), boost::end(bad_strings)) {} +}; + +// list of string node names we expect from traversing example_tree() in +// DFS_PRE order +const char* dfs_pre_strings[] = +{ + "root", + "A", + "A1", + "A1a", + "A1b", + "A1c", + "A2", + "A2a", + "A2b", + "A2c", + "A3", + "A3a", + "A3b", + "A3c", + "B", + "B1", + "B1a", + "B1b", + "B1c", + "B2", + "B2a", + "B2b", + "B2c", + "B3", + "B3a", + "B3b", + "B3c", + "C", + "C1", + "C1a", + "C1b", + "C1c", + "C2", + "C2a", + "C2b", + "C2c", + "C3", + "C3a", + "C3b", + "C3c" +}; + +// specialize WalkExpected with the expected strings +template <> +struct WalkExpected: public Expected +{ + WalkExpected(): Expected(boost::begin(dfs_pre_strings), boost::end(dfs_pre_strings)) {} +}; + +// list of string node names we expect from traversing example_tree() in +// DFS_POST order +const char* dfs_post_strings[] = +{ + "A1a", + "A1b", + "A1c", + "A1", + "A2a", + "A2b", + "A2c", + "A2", + "A3a", + "A3b", + "A3c", + "A3", + "A", + "B1a", + "B1b", + "B1c", + "B1", + "B2a", + "B2b", + "B2c", + "B2", + "B3a", + "B3b", + "B3c", + "B3", + "B", + "C1a", + "C1b", + "C1c", + "C1", + "C2a", + "C2b", + "C2c", + "C2", + "C3a", + "C3b", + "C3c", + "C3", + "C", + "root" +}; + +// specialize WalkExpected with the expected strings +template <> +struct WalkExpected: public Expected +{ + WalkExpected(): Expected(boost::begin(dfs_post_strings), boost::end(dfs_post_strings)) {} +}; + +// list of string node names we expect from traversing example_tree() in BFS order +const char* bfs_strings[] = +{ + "root", + "A", + "B", + "C", + "A1", + "A2", + "A3", + "B1", + "B2", + "B3", + "C1", + "C2", + "C3", + "A1a", + "A1b", + "A1c", + "A2a", + "A2b", + "A2c", + "A3a", + "A3b", + "A3c", + "B1a", + "B1b", + "B1c", + "B2a", + "B2b", + "B2c", + "B3a", + "B3b", + "B3c", + "C1a", + "C1b", + "C1c", + "C2a", + "C2b", + "C2c", + "C3a", + "C3b", + "C3c" +}; + +// specialize WalkExpected with the expected strings +template <> +struct WalkExpected: public Expected +{ + WalkExpected(): Expected(boost::begin(bfs_strings), boost::end(bfs_strings)) {} +}; + +// extract a particular "arbitrary" node from the example_tree() data: the +// second (middle) node at each child level +template +typename LLPtrTo::type +get_B2b(const typename LLPtrTo::type& root, + const boost::function::type&)>& child_begin) +{ + typedef typename LLPtrTo::type NodePtr; + CHILDITER Bi(child_begin(root)); + ++Bi; + NodePtr B(*Bi); + CHILDITER B2i(child_begin(B)); + ++B2i; + NodePtr B2(*B2i); + CHILDITER B2bi(child_begin(B2)); + ++B2bi; + NodePtr B2b(*B2bi); + return B2b; +} + +// RootExpected is the list of string node names we expect from a +// RootIter traversal of our example_tree() data. +template +struct RootExpected: public Expected +{ + // Initialize with bad_strings: we don't expect to use this generic case, + // only the specializations. + RootExpected(): Expected(boost::begin(bad_strings), boost::end(bad_strings)) {} +}; + +// list of string node names we expect from traversing UP from +// example_tree()'s B2b node +const char* up_from_B2b[] = +{ + "B2b", + "B2", + "B", + "root" +}; + +// specialize RootExpected with the expected strings +template <> +struct RootExpected: public Expected +{ + RootExpected(): Expected(boost::begin(up_from_B2b), boost::end(up_from_B2b)) {} +}; + +// list of string node names we expect from traversing DOWN to +// example_tree()'s B2b node +const char* down_to_B2b[] = +{ + "root", + "B", + "B2", + "B2b" +}; + +// specialize RootExpected with the expected strings +template <> +struct RootExpected: public Expected +{ + RootExpected(): Expected(boost::begin(down_to_B2b), boost::end(down_to_B2b)) {} +}; + +/***************************************************************************** +* Generic tree test functions +*****************************************************************************/ +template +bool LLTreeRootIter_test(const std::string& itername, const std::string& nodename, + const typename LLPtrTo::type& node, + PARENTFUNC parentfunc) +{ + std::ostringstream desc; + desc << itername << '<' << nodename << "> from " << node->name(); + if (! verify(desc.str(), + boost::make_iterator_range(LLTreeRootIter(node, parentfunc), + LLTreeRootIter()), + RootExpected())) + return false; +// std::cout << desc.str() << '\n'; + // Try instantiating an iterator with NULL (that is, a default-constructed + // node pointer). This test is less about "did we iterate once?" than "did + // we avoid blowing up?" + for (LLTreeRootIter hri = LLTreeRootIter(typename LLPtrTo::type(), parentfunc), hrend; + hri != hrend; /* ++hri */) // incrementing is moot, and MSVC complains + { +// std::cout << nodename << '(' << (*hri)->name() << ")\n"; + std::cout << itername << '<' << nodename << ">(NULL)\n"; + return false; + } + return true; +} + +template +bool LLTreeUpIter_test(const std::string& nodename, PARENTFUNC parentfunc, CHILDFUNC childfunc) +{ + bool success = true; + typedef typename LLPtrTo::type ptr_type; + ptr_type root(example_tree()); + Cleanup cleanup(root); + ptr_type B2b(get_B2b(root, childfunc)); + if (! LLTreeRootIter_test("LLTreeUpIter", nodename, B2b, parentfunc)) + success = false; + if (! LLTreeRootIter_test("LLTreeDownIter", nodename, B2b, parentfunc)) + success = false; + return success; +} + +template +bool LLTreeWalkIter_test(const std::string& itername, const std::string& nodename, + CHILDBEGINFUNC childbegin, CHILDENDFUNC childend) +{ + typename LLPtrTo::type root(example_tree()); + Cleanup::type> cleanup(root); + std::ostringstream desc; + desc << itername << '<' << nodename << "> from " << root->name(); + if (! verify(desc.str(), + boost::make_iterator_range(LLTreeWalkIter(root, + childbegin, + childend), + LLTreeWalkIter()), + WalkExpected())) + return false; + // Try instantiating an iterator with NULL (that is, a default-constructed + // node pointer). This test is less about "did we iterate once?" than "did + // we avoid blowing up?" + for (LLTreeWalkIter twi = LLTreeWalkIter(typename LLPtrTo::type(), + childbegin, + childend), + twend; + twi != twend; /* ++twi */) // incrementing is moot, and MSVC complains + { + std::cout << itername << '<' << nodename << ">(NULL)\n"; + return false; + } + return true; +} + +template +bool LLTreeIter_tests(const std::string& nodename, + PARENTFUNC parentfunc, CHILDBEGINFUNC childbegin, CHILDENDFUNC childend) +{ + bool success = true; + if (! LLTreeUpIter_test(nodename, parentfunc, childbegin)) + success = false; +/*==========================================================================*| + LLTreeIter_test >("LLTreeDFSIter", nodename, + childbegin, childend); + LLTreeIter_test >("LLTreeDFSPostIter", nodename, + childbegin, childend); + LLTreeIter_test >("LLTreeBFSIter", nodename, + childbegin, childend); +|*==========================================================================*/ + if (! LLTreeWalkIter_test("LLTreeDFSIter", nodename, + childbegin, childend)) + success = false; + if (! LLTreeWalkIter_test("LLTreeDFSPostIter", nodename, + childbegin, childend)) + success = false; + if (! LLTreeWalkIter_test("LLTreeBFSIter", nodename, + childbegin, childend)) + success = false; + return success; +} + +namespace tut +{ + template<> template<> + void iter_object::test<3>() + { +// set_test_name("LLTreeIter tests"); + ensure(LLTreeIter_tests + ("TreeNode", + boost::bind(&TreeNode::getParent, _1), + boost::bind(&TreeNode::child_begin, _1), + boost::bind(&TreeNode::child_end, _1))); + ensure(LLTreeIter_tests > + ("PlainTree", + boost::bind(&PlainTree::mParent, _1), + PlainTree_child_begin, + PlainTree_child_end)); + } + + template<> template<> + void iter_object::test<4>() + { +// set_test_name("getRootRange() tests"); + // This test function illustrates the looping techniques described in the + // comments for the getRootRange() free function, the + // EnhancedTreeNode::root_range template and the + // EnhancedTreeNode::getRootRange() method. Obviously the BOOST_FOREACH() + // forms are more succinct. + TreeNodePtr tnroot(example_tree()); + TreeNodePtr tnB2b(get_B2b + (tnroot, boost::bind(&TreeNode::child_begin, _1))); + + std::string desc1("BOOST_FOREACH(TreeNodePr, getRootRange(tnB2b))"); +// std::cout << desc1 << "\n"; + // Although we've commented out the output statement, ensure that the + // loop construct is still valid, as promised by the getRootRange() + // documentation. + BOOST_FOREACH(TreeNodePtr node, getRootRange(tnB2b)) + { +// std::cout << node->name() << '\n'; + } + ensure(desc1, + verify(desc1, getRootRange(tnB2b), RootExpected())); + + EnhancedTreeNodePtr etnroot(example_tree()); + EnhancedTreeNodePtr etnB2b(get_B2b + (etnroot, boost::bind(&EnhancedTreeNode::child_begin, _1))); + +// std::cout << "EnhancedTreeNode::root_range::type range =\n" +// << " etnB2b->getRootRange();\n" +// << "for (EnhancedTreeNode::root_range::type::iterator ri = range.begin();\n" +// << " ri != range.end(); ++ri)\n"; + EnhancedTreeNode::root_range::type range = + etnB2b->getRootRange(); + for (EnhancedTreeNode::root_range::type::iterator ri = range.begin(); + ri != range.end(); ++ri) + { +// std::cout << (*ri)->name() << '\n'; + } + + std::string desc2("BOOST_FOREACH(EnhancedTreeNodePtr node, etnB2b->getRootRange())"); +// std::cout << desc2 << '\n'; + BOOST_FOREACH(EnhancedTreeNodePtr node, etnB2b->getRootRange()) + { +// std::cout << node->name() << '\n'; + } + ensure(desc2, + verify(desc2, etnB2b->getRootRange(), RootExpected())); + } + + template<> template<> + void iter_object::test<5>() + { +// set_test_name("getWalkRange() tests"); + // This test function doesn't illustrate the looping permutations for + // getWalkRange(); see getRootRange_tests() for such examples. This + // function simply verifies that they all work. + + // TreeNode, using helper function + TreeNodePtr tnroot(example_tree()); + std::string desc_tnpre("getWalkRange(tnroot)"); + ensure(desc_tnpre, + verify(desc_tnpre, + getWalkRange(tnroot), + WalkExpected())); + std::string desc_tnpost("getWalkRange(tnroot)"); + ensure(desc_tnpost, + verify(desc_tnpost, + getWalkRange(tnroot), + WalkExpected())); + std::string desc_tnb("getWalkRange(tnroot)"); + ensure(desc_tnb, + verify(desc_tnb, + getWalkRange(tnroot), + WalkExpected())); + + // EnhancedTreeNode, using method + EnhancedTreeNodePtr etnroot(example_tree()); + std::string desc_etnpre("etnroot->getWalkRange()"); + ensure(desc_etnpre, + verify(desc_etnpre, + etnroot->getWalkRange(), + WalkExpected())); + std::string desc_etnpost("etnroot->getWalkRange()"); + ensure(desc_etnpost, + verify(desc_etnpost, + etnroot->getWalkRange(), + WalkExpected())); + std::string desc_etnb("etnroot->getWalkRange()"); + ensure(desc_etnb, + verify(desc_etnb, + etnroot->getWalkRange(), + WalkExpected())); + + // PlainTree, using helper function + PlainTree* ptroot(example_tree()); + Cleanup cleanup(ptroot); + std::string desc_ptpre("getWalkRange(ptroot)"); + ensure(desc_ptpre, + verify(desc_ptpre, + getWalkRange(ptroot), + WalkExpected())); + std::string desc_ptpost("getWalkRange(ptroot)"); + ensure(desc_ptpost, + verify(desc_ptpost, + getWalkRange(ptroot), + WalkExpected())); + std::string desc_ptb("getWalkRange(ptroot)"); + ensure(desc_ptb, + verify(desc_ptb, + getWalkRange(ptroot), + WalkExpected())); + } +} // tut diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt index ff68b2d68a..dd11a0bc7e 100644 --- a/indra/test/CMakeLists.txt +++ b/indra/test/CMakeLists.txt @@ -58,7 +58,6 @@ set(test_SOURCE_FILES lltemplatemessagebuilder_tut.cpp lltimestampcache_tut.cpp lltranscode_tut.cpp - lltreeiterators_tut.cpp lltut.cpp lluri_tut.cpp lluuidhashmap_tut.cpp -- cgit v1.3 From 986bf99839a79f13a4b16218c221cb123d4bfc15 Mon Sep 17 00:00:00 2001 From: Adam Moss Date: Thu, 15 Oct 2009 18:05:15 +0000 Subject: DEV-41352 convert lluri tut test to a llcommon integration test --- indra/llcommon/CMakeLists.txt | 1 + indra/llcommon/tests/lluri_test.cpp | 370 ++++++++++++++++++++++++++++++++++++ indra/test/CMakeLists.txt | 1 - 3 files changed, 371 insertions(+), 1 deletion(-) create mode 100644 indra/llcommon/tests/lluri_test.cpp (limited to 'indra/llcommon') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index c8e030623b..85447ddd64 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -249,6 +249,7 @@ LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}") 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}") # *TODO - reenable these once tcmalloc libs no longer break the build. #ADD_BUILD_TEST(llallocator llcommon) diff --git a/indra/llcommon/tests/lluri_test.cpp b/indra/llcommon/tests/lluri_test.cpp new file mode 100644 index 0000000000..4e5ad0df58 --- /dev/null +++ b/indra/llcommon/tests/lluri_test.cpp @@ -0,0 +1,370 @@ +/** + * @file lluri_tut.cpp + * @brief LLURI unit tests + * @date September 2006 + * + * $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 "../llsd.h" +#include "../lluri.h" + +#include "../test/lltut.h" + +namespace tut +{ + struct URITestData { + void checkParts(const LLURI& u, + const char* expectedScheme, + const char* expectedOpaque, + const char* expectedAuthority, + const char* expectedPath, + const char* expectedQuery = "") + { + ensure_equals("scheme", u.scheme(), expectedScheme); + ensure_equals("opaque", u.opaque(), expectedOpaque); + ensure_equals("authority", u.authority(), expectedAuthority); + ensure_equals("path", u.path(), expectedPath); + ensure_equals("query", u.query(), expectedQuery); + } + + void escapeRoundTrip(const std::string& uri_raw_1) + { + std::string uri_esc_1(LLURI::escape(uri_raw_1)); + std::string uri_raw_2(LLURI::unescape(uri_esc_1)); + ensure_equals("escape/unescape raw", uri_raw_2, uri_raw_1); + std::string uri_esc_2(LLURI::escape(uri_raw_2)); + ensure_equals("escape/unescape escaped", uri_esc_2, uri_esc_1); + } + }; + + typedef test_group URITestGroup; + typedef URITestGroup::object URITestObject; + + URITestGroup uriTestGroup("LLURI"); + + template<> template<> + void URITestObject::test<1>() + { + LLURI u("http://abc.com/def/ghi?x=37&y=hello"); + + ensure_equals("scheme", u.scheme(), "http"); + ensure_equals("authority", u.authority(), "abc.com"); + ensure_equals("path", u.path(), "/def/ghi"); + ensure_equals("query", u.query(), "x=37&y=hello"); + + ensure_equals("host name", u.hostName(), "abc.com"); + ensure_equals("host port", u.hostPort(), 80); + + LLSD query = u.queryMap(); + ensure_equals("query x", query["x"].asInteger(), 37); + ensure_equals("query y", query["y"].asString(), "hello"); + + query = LLURI::queryMap("x=22.23&y=https://lindenlab.com/"); + ensure_equals("query x", query["x"].asReal(), 22.23); + ensure_equals("query y", query["y"].asURI().asString(), "https://lindenlab.com/"); + } + + template<> template<> + void URITestObject::test<2>() + { + // empty string + checkParts(LLURI(""), "", "", "", ""); + } + + template<> template<> + void URITestObject::test<3>() + { + // no scheme + checkParts(LLURI("foo"), "", "foo", "", ""); + checkParts(LLURI("foo%3A"), "", "foo:", "", ""); + } + + template<> template<> + void URITestObject::test<4>() + { + // scheme w/o paths + checkParts(LLURI("mailto:zero@ll.com"), + "mailto", "zero@ll.com", "", ""); + checkParts(LLURI("silly://abc/def?foo"), + "silly", "//abc/def?foo", "", ""); + } + + template<> template<> + void URITestObject::test<5>() + { + // authority section + checkParts(LLURI("http:///"), + "http", "///", "", "/"); + + checkParts(LLURI("http://abc"), + "http", "//abc", "abc", ""); + + checkParts(LLURI("http://a%2Fb/cd"), + "http", "//a/b/cd", "a/b", "/cd"); + + checkParts(LLURI("http://host?"), + "http", "//host?", "host", ""); + } + + template<> template<> + void URITestObject::test<6>() + { + // path section + checkParts(LLURI("http://host/a/b/"), + "http", "//host/a/b/", "host", "/a/b/"); + + checkParts(LLURI("http://host/a%3Fb/"), + "http", "//host/a?b/", "host", "/a?b/"); + + checkParts(LLURI("http://host/a:b/"), + "http", "//host/a:b/", "host", "/a:b/"); + } + + template<> template<> + void URITestObject::test<7>() + { + // query string + checkParts(LLURI("http://host/?"), + "http", "//host/?", "host", "/", ""); + + checkParts(LLURI("http://host/?x"), + "http", "//host/?x", "host", "/", "x"); + + checkParts(LLURI("http://host/??"), + "http", "//host/??", "host", "/", "?"); + + checkParts(LLURI("http://host/?%3F"), + "http", "//host/??", "host", "/", "?"); + } + + template<> template<> + void URITestObject::test<8>() + { + LLSD path; + path.append("x"); + path.append("123"); + checkParts(LLURI::buildHTTP("host", path), + "http", "//host/x/123", "host", "/x/123"); + + LLSD query; + query["123"] = "12"; + query["abcd"] = "abc"; + checkParts(LLURI::buildHTTP("host", path, query), + "http", "//host/x/123?123=12&abcd=abc", + "host", "/x/123", "123=12&abcd=abc"); + } + + template<> template<> + void URITestObject::test<9>() + { + // test unescaped path components + LLSD path; + path.append("x@*//*$&^"); + path.append("123"); + checkParts(LLURI::buildHTTP("host", path), + "http", "//host/x@*//*$&^/123", "host", "/x@*//*$&^/123"); + } + + template<> template<> + void URITestObject::test<10>() + { + // test unescaped query components + LLSD path; + path.append("x"); + path.append("123"); + LLSD query; + query["123"] = "?&*#//"; + query["**@&?//"] = "abc"; + checkParts(LLURI::buildHTTP("host", path, query), + "http", "//host/x/123?**@&?//=abc&123=?&*#//", + "host", "/x/123", "**@&?//=abc&123=?&*#//"); + } + + template<> template<> + void URITestObject::test<11>() + { + // test unescaped host components + LLSD path; + path.append("x"); + path.append("123"); + LLSD query; + query["123"] = "12"; + query["abcd"] = "abc"; + checkParts(LLURI::buildHTTP("hi123*33--}{:portstuffs", path, query), + "http", "//hi123*33--}{:portstuffs/x/123?123=12&abcd=abc", + "hi123*33--}{:portstuffs", "/x/123", "123=12&abcd=abc"); + } + + template<> template<> + void URITestObject::test<12>() + { + // test funky host_port values that are actually prefixes + + checkParts(LLURI::buildHTTP("http://example.com:8080", LLSD()), + "http", "//example.com:8080", + "example.com:8080", ""); + + checkParts(LLURI::buildHTTP("http://example.com:8080/", LLSD()), + "http", "//example.com:8080/", + "example.com:8080", "/"); + + checkParts(LLURI::buildHTTP("http://example.com:8080/a/b", LLSD()), + "http", "//example.com:8080/a/b", + "example.com:8080", "/a/b"); + } + + template<> template<> + void URITestObject::test<13>() + { + const std::string unreserved = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789" + "-._~"; + // test escape + ensure_equals("escaping", LLURI::escape("abcdefg", "abcdef"), "abcdef%67"); + ensure_equals("escaping", LLURI::escape("|/&\\+-_!@", ""), "%7C%2F%26%5C%2B%2D%5F%21%40"); + ensure_equals("escaping as query variable", + LLURI::escape("http://10.0.1.4:12032/agent/god/agent-id/map/layer/?resume=http://station3.ll.com:12032/agent/203ad6df-b522-491d-ba48-4e24eb57aeff/send-postcard", unreserved + ":@!$'()*+,="), + "http:%2F%2F10.0.1.4:12032%2Fagent%2Fgod%2Fagent-id%2Fmap%2Flayer%2F%3Fresume=http:%2F%2Fstation3.ll.com:12032%2Fagent%2F203ad6df-b522-491d-ba48-4e24eb57aeff%2Fsend-postcard"); + // French cedilla (C with squiggle, like in the word Francais) is UTF-8 C3 A7 + +#if LL_WINDOWS +#pragma warning(disable: 4309) +#endif + + std::string cedilla; + cedilla.push_back( (char)0xC3 ); + cedilla.push_back( (char)0xA7 ); + ensure_equals("escape UTF8", LLURI::escape( cedilla, unreserved), "%C3%A7"); + } + + + template<> template<> + void URITestObject::test<14>() + { + // make sure escape and unescape of empty strings return empty + // strings. + std::string uri_esc(LLURI::escape("")); + ensure("escape string empty", uri_esc.empty()); + std::string uri_raw(LLURI::unescape("")); + ensure("unescape string empty", uri_raw.empty()); + } + + template<> template<> + void URITestObject::test<15>() + { + // do some round-trip tests + escapeRoundTrip("http://secondlife.com"); + escapeRoundTrip("http://secondlife.com/url with spaces"); + escapeRoundTrip("http://bad[domain]name.com/"); + escapeRoundTrip("ftp://bill.gates@ms/micro$oft.com/c:\\autoexec.bat"); + escapeRoundTrip(""); + } + + template<> template<> + void URITestObject::test<16>() + { + // Test the default escaping + // yes -- this mangles the url. This is expected behavior + std::string simple("http://secondlife.com"); + ensure_equals( + "simple http", + LLURI::escape(simple), + "http%3A%2F%2Fsecondlife.com"); + ensure_equals( + "needs escape", + LLURI::escape("http://get.secondlife.com/windows viewer"), + "http%3A%2F%2Fget.secondlife.com%2Fwindows%20viewer"); + } + + template<> template<> + void URITestObject::test<17>() + { + // do some round-trip tests with very long strings. + escapeRoundTrip("Welcome to Second Life.We hope you'll have a richly rewarding experience, filled with creativity, self expression and fun.The goals of the Community Standards are simple: treat each other with respect and without harassment, adhere to local standards as indicated by simulator ratings, and refrain from any hate activity which slurs a real-world individual or real-world community. Behavioral Guidelines - The Big Six"); + escapeRoundTrip( + "'asset_data':b(12100){'task_id':ucc706f2d-0b68-68f8-11a4-f1043ff35ca0}\n{\n\tname\tObject|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreator_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444921\n\ttotal_crc\t323\n\ttype\t2\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.368634403\t0.00781063363\t-0.569040775\n\toldpos\t150.117996\t25.8658009\t8.19664001\n\trotation\t-0.06293071806430816650390625\t-0.6995697021484375\t-0.7002241611480712890625\t0.1277817934751510620117188\n\tchildpos\t-0.00499999989\t-0.0359999985\t0.307999998\n\tchildrot\t-0.515492737293243408203125\t-0.46601200103759765625\t0.529055416584014892578125\t0.4870323240756988525390625\n\tscale" + "\t0.074629\t0.289956\t0.01\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t16\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\tscale_x\t1\n\t\t\tscale_y\t1\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t1\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tf" + "aces\t6\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204" + "\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t-1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061088050622956\n\treztime\t1094866329019785\n\tparceltime\t1133568981980596\n\ttax_rate\t1.00084\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tchild\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n{'task_id':u61fa7364-e151-0597-774c-523312dae31b}\n{\n\tname\tObject|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffff" + "ff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreator_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444922\n\ttotal_crc\t324\n\ttype\t2\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.367110789\t0.00780026987\t-0.566269755\n\toldpos\t150.115005\t25.8479004\t8.18669987\n\trotation\t0.47332942485809326171875\t-0.380102097988128662109375\t-0.5734078884124755859375\t0.550168216228485107421875\n\tchildpos\t-0.00499999989\t-0.0370000005\t0.305000007\n\tchildrot\t-0.736649334430694580078125\t-0.03042060509324073791503906\t-0.02784589119255542755126953\t0.67501628398895263671875\n\tscale\t0.074629\t0.289956\t0.01\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t" + "0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t16\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\tscale_x\t1\n\t\t\tscale_y\t1\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t1\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t6\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t" + "\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t" + "\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t-1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061087839248891\n\treztime\t1094866329020800\n\tparceltime\t1133568981981983\n\ttax_rate\t1.00084\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tchild\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n{'task_id':ub8d68643-7dd8-57af-0d24-8790032aed0c}\n{\n\tname\tObject|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreat" + "or_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444923\n\ttotal_crc\t235\n\ttype\t2\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.120029509\t-0.00284469454\t-0.0302077383\n\toldpos\t150.710999\t25.8584995\t8.19172001\n\trotation\t0.145459949970245361328125\t-0.1646589934825897216796875\t0.659558117389678955078125\t-0.718826770782470703125\n\tchildpos\t0\t-0.182999998\t-0.26699999\n\tchildrot\t0.991444766521453857421875\t3.271923924330621957778931e-05\t-0.0002416197530692443251609802\t0.1305266767740249633789062\n\tscale\t0.0382982\t0.205957\t0.368276\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundra" + "dius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t32\n\t\t\tbegin\t0.3\n\t\t\tend\t0.65\n\t\t\tscale_x\t1\n\t\t\tscale_y\t0.05\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t0\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t3\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0" + "\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061087534454174\n\treztime\t1094866329021741\n\tparceltime\t1133568981982889\n\ttax_rate\t1.00326\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tchild\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n{'task_id':ue4b19200-9d33-962f-c8c5-6f" + "25be3a3fd0}\n{\n\tname\tApotheosis_Immolaine_tail|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreator_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444924\n\ttotal_crc\t675\n\ttype\t1\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.34780401\t-0.00968400016\t-0.260098994\n\toldpos\t0\t0\t0\n\trotation\t0.73164522647857666015625\t-0.67541944980621337890625\t-0.07733880728483200073242188\t0.05022468417882919311523438\n\tvelocity\t0\t0\t0\n\tangvel\t0\t0\t0\n\tscale\t0.0382982\t0.32228\t0.383834\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000" + "000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t32\n\t\t\tbegin\t0.3\n\t\t\tend\t0.65\n\t\t\tscale_x\t1\n\t\t\tscale_y\t0.05\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t0\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t3\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1" + ".57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061087463950186\n\treztime\t1094866329022555\n\tparceltime\t1133568981984359\n\tdescription\t(No Description)|\n\ttax_rate\t1.01736\n\tnamevalue\tAttachPt U32 RW S 10\n\tnamevalue\tAttachmentOrientation VEC3 RW DS -3.110088, -0.182018, 1.493795\n\tnamevalue\tAttachmentOffset VEC3 RW DS -0.347804, -0.009684, -0.260099\n\tnamevalue\tAttachItemI" + "D STRING RW SV 20f36c3a-b44b-9bc7-87f3-018bfdfc8cda\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\torig_asset_id\t8747acbc-d391-1e59-69f1-41d06830e6c0\n\torig_item_id\t20f36c3a-b44b-9bc7-87f3-018bfdfc8cda\n\tfrom_task_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tlinked\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n"); + } + + + template<> template<> + void URITestObject::test<18>() + { + LLURI u("secondlife:///app/login?first_name=Testert4&last_name=Tester&web_login_key=test"); + // if secondlife is the scheme, LLURI should parse /app/login as path, with no authority + ensure_equals("scheme", u.scheme(), "secondlife"); + ensure_equals("authority", u.authority(), ""); + ensure_equals("path", u.path(), "/app/login"); + ensure_equals("pathmap", u.pathArray()[0].asString(), "app"); + ensure_equals("pathmap", u.pathArray()[1].asString(), "login"); + ensure_equals("query", u.query(), "first_name=Testert4&last_name=Tester&web_login_key=test"); + ensure_equals("query map element", u.queryMap()["last_name"].asString(), "Tester"); + + u = LLURI("secondlife://Da Boom/128/128/128"); + // if secondlife is the scheme, LLURI should parse /128/128/128 as path, with Da Boom as authority + ensure_equals("scheme", u.scheme(), "secondlife"); + ensure_equals("authority", u.authority(), "Da Boom"); + ensure_equals("path", u.path(), "/128/128/128"); + ensure_equals("pathmap", u.pathArray()[0].asString(), "128"); + ensure_equals("pathmap", u.pathArray()[1].asString(), "128"); + ensure_equals("pathmap", u.pathArray()[2].asString(), "128"); + ensure_equals("query", u.query(), ""); + } + + template<> template<> + void URITestObject::test<19>() + { + // Parse about: schemes + LLURI u("about:blank?redirect-http-hack=secondlife%3A%2F%2F%2Fapp%2Flogin%3Ffirst_name%3DCallum%26last_name%3DLinden%26location%3Dspecify%26grid%3Dvaak%26region%3D%2FMorris%2F128%2F128%26web_login_key%3Defaa4795-c2aa-4c58-8966-763c27931e78"); + ensure_equals("scheme", u.scheme(), "about"); + ensure_equals("authority", u.authority(), ""); + ensure_equals("path", u.path(), "blank"); + ensure_equals("pathmap", u.pathArray()[0].asString(), "blank"); + ensure_equals("query", u.query(), "redirect-http-hack=secondlife:///app/login?first_name=Callum&last_name=Linden&location=specify&grid=vaak®ion=/Morris/128/128&web_login_key=efaa4795-c2aa-4c58-8966-763c27931e78"); + ensure_equals("query map element", u.queryMap()["redirect-http-hack"].asString(), "secondlife:///app/login?first_name=Callum&last_name=Linden&location=specify&grid=vaak®ion=/Morris/128/128&web_login_key=efaa4795-c2aa-4c58-8966-763c27931e78"); + } +} + + diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt index db78b7b9ec..c40f16e02c 100644 --- a/indra/test/CMakeLists.txt +++ b/indra/test/CMakeLists.txt @@ -58,7 +58,6 @@ set(test_SOURCE_FILES lltimestampcache_tut.cpp lltranscode_tut.cpp lltut.cpp - lluri_tut.cpp lluuidhashmap_tut.cpp llxfer_tut.cpp message_tut.cpp -- cgit v1.3 From db6dff1d1f1a3ba178cd24095a2bc0c56b63f0a9 Mon Sep 17 00:00:00 2001 From: Adam Moss Date: Thu, 15 Oct 2009 18:10:46 +0000 Subject: DEV-41354 convert llerror tut test into a llcommon integration test --- indra/llcommon/CMakeLists.txt | 1 + indra/llcommon/tests/llerror_test.cpp | 767 ++++++++++++++++++++++++++++++++++ indra/test/CMakeLists.txt | 1 - 3 files changed, 768 insertions(+), 1 deletion(-) create mode 100644 indra/llcommon/tests/llerror_test.cpp (limited to 'indra/llcommon') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 85447ddd64..414aaea08b 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -243,6 +243,7 @@ LL_ADD_PROJECT_UNIT_TESTS(llcommon "${llcommon_TEST_SOURCE_FILES}") set(test_libs llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES}) LL_ADD_INTEGRATION_TEST(commonmisc "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lldate "" "${test_libs}") +LL_ADD_INTEGRATION_TEST(llerror "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llframetimer "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lllazy "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}") diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp new file mode 100644 index 0000000000..930047e164 --- /dev/null +++ b/indra/llcommon/tests/llerror_test.cpp @@ -0,0 +1,767 @@ +/** + * @file llerror_tut.cpp + * @date December 2006 + * @brief error 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 "../llerror.h" + +namespace +{ + void test_that_error_h_includes_enough_things_to_compile_a_message() + { + llinfos << "!" << llendl; + } +} + +#include "../test/lltut.h" + +#include + +#include "../llerrorcontrol.h" +#include "../llsd.h" + +namespace +{ + static bool fatalWasCalled; + void fatalCall(const std::string&) { fatalWasCalled = true; } + + class TestRecorder : public LLError::Recorder + { + public: + TestRecorder() : mWantsTime(false) { } + ~TestRecorder() { LLError::removeRecorder(this); } + + void recordMessage(LLError::ELevel level, + const std::string& message) + { + mMessages.push_back(message); + } + + int countMessages() { return (int) mMessages.size(); } + void clearMessages() { mMessages.clear(); } + + void setWantsTime(bool t) { mWantsTime = t; } + bool wantsTime() { return mWantsTime; } + + std::string message(int n) + { + std::ostringstream test_name; + test_name << "testing message " << n << ", not enough messages"; + + tut::ensure(test_name.str(), n < countMessages()); + return mMessages[n]; + } + + private: + typedef std::vector MessageVector; + MessageVector mMessages; + + bool mWantsTime; + }; +} + +namespace tut +{ + struct ErrorTestData + { + TestRecorder mRecorder; + LLError::Settings* mPriorErrorSettings; + + ErrorTestData() + { + fatalWasCalled = false; + + mPriorErrorSettings = LLError::saveAndResetSettings(); + LLError::setDefaultLevel(LLError::LEVEL_DEBUG); + LLError::setFatalFunction(fatalCall); + LLError::addRecorder(&mRecorder); + } + + ~ErrorTestData() + { + LLError::removeRecorder(&mRecorder); + LLError::restoreSettings(mPriorErrorSettings); + } + + void ensure_message_count(int expectedCount) + { + ensure_equals("message count", mRecorder.countMessages(), expectedCount); + } + + void ensure_message_contains(int n, const std::string& expectedText) + { + std::ostringstream test_name; + test_name << "testing message " << n; + + ensure_contains(test_name.str(), mRecorder.message(n), expectedText); + } + + void ensure_message_does_not_contain(int n, const std::string& expectedText) + { + std::ostringstream test_name; + test_name << "testing message " << n; + + ensure_does_not_contain(test_name.str(), mRecorder.message(n), expectedText); + } + }; + + typedef test_group ErrorTestGroup; + typedef ErrorTestGroup::object ErrorTestObject; + + ErrorTestGroup errorTestGroup("error"); + + template<> template<> + void ErrorTestObject::test<1>() + // basic test of output + { + llinfos << "test" << llendl; + llinfos << "bob" << llendl; + + ensure_message_contains(0, "test"); + ensure_message_contains(1, "bob"); + } +} + +namespace +{ + void writeSome() + { + lldebugs << "one" << llendl; + llinfos << "two" << llendl; + llwarns << "three" << llendl; + llerrs << "four" << llendl; + // fatal messages write out and addtional "error" message + } +}; + +namespace tut +{ + template<> template<> + void ErrorTestObject::test<2>() + // messages are filtered based on default level + { + LLError::setDefaultLevel(LLError::LEVEL_DEBUG); + writeSome(); + ensure_message_contains(0, "one"); + ensure_message_contains(1, "two"); + ensure_message_contains(2, "three"); + ensure_message_contains(3, "error"); + ensure_message_contains(4, "four"); + ensure_message_count(5); + + LLError::setDefaultLevel(LLError::LEVEL_INFO); + writeSome(); + ensure_message_contains(5, "two"); + ensure_message_contains(6, "three"); + ensure_message_contains(7, "error"); + ensure_message_contains(8, "four"); + ensure_message_count(9); + + LLError::setDefaultLevel(LLError::LEVEL_WARN); + writeSome(); + ensure_message_contains(9, "three"); + ensure_message_contains(10, "error"); + ensure_message_contains(11, "four"); + ensure_message_count(12); + + LLError::setDefaultLevel(LLError::LEVEL_ERROR); + writeSome(); + ensure_message_contains(12, "error"); + ensure_message_contains(13, "four"); + ensure_message_count(14); + + LLError::setDefaultLevel(LLError::LEVEL_NONE); + writeSome(); + ensure_message_count(14); + } + + template<> template<> + void ErrorTestObject::test<3>() + // error type string in output + { + writeSome(); + ensure_message_contains(0, "DEBUG: "); + ensure_message_contains(1, "INFO: "); + ensure_message_contains(2, "WARNING: "); + ensure_message_does_not_contain(3, "ERROR"); + ensure_message_contains(4, "ERROR: "); + ensure_message_count(5); + } + + template<> template<> + void ErrorTestObject::test<4>() + // file abbreviation + { + std::string thisFile = __FILE__; + std::string abbreviateFile = LLError::abbreviateFile(thisFile); + + ensure_ends_with("file name abbreviation", + abbreviateFile, + "llcommon/tests/llerror_test.cpp" + ); + ensure_does_not_contain("file name abbreviation", + abbreviateFile, "indra"); + + std::string someFile = +#if LL_WINDOWS + "C:/amy/bob/cam.cpp" +#else + "/amy/bob/cam.cpp" +#endif + ; + std::string someAbbreviation = LLError::abbreviateFile(someFile); + + ensure_equals("non-indra file abbreviation", + someAbbreviation, someFile); + } +} + +namespace +{ + std::string locationString(int line) + { + std::ostringstream location; + location << LLError::abbreviateFile(__FILE__) + << "(" << line << ") : "; + + return location.str(); + } + + std::string writeReturningLocation() + { + llinfos << "apple" << llendl; int this_line = __LINE__; + return locationString(this_line); + } + + std::string writeReturningLocationAndFunction() + { + llinfos << "apple" << llendl; int this_line = __LINE__; + return locationString(this_line) + __FUNCTION__; + } + + std::string errorReturningLocation() + { + llerrs << "die" << llendl; int this_line = __LINE__; + return locationString(this_line); + } +} + +namespace tut +{ + template<> template<> + void ErrorTestObject::test<5>() + // file and line information in log messages + { + std::string location = writeReturningLocation(); + // expecting default to not print location information + + LLError::setPrintLocation(true); + writeReturningLocation(); + + LLError::setPrintLocation(false); + writeReturningLocation(); + + ensure_message_does_not_contain(0, location); + ensure_message_contains(1, location); + ensure_message_does_not_contain(2, location); + } +} + +/* The following helper functions and class members all log a simple message + from some particular function scope. Each function takes a bool argument + that indicates if it should log its own name or not (in the manner that + existing log messages often do.) The functions all return their C++ + name so that test can be substantial mechanized. + */ + +std::string logFromGlobal(bool id) +{ + llinfos << (id ? "logFromGlobal: " : "") << "hi" << llendl; + return "logFromGlobal"; +} + +static std::string logFromStatic(bool id) +{ + llinfos << (id ? "logFromStatic: " : "") << "hi" << llendl; + return "logFromStatic"; +} + +namespace +{ + std::string logFromAnon(bool id) + { + llinfos << (id ? "logFromAnon: " : "") << "hi" << llendl; + return "logFromAnon"; + } +} + +namespace Foo { + std::string logFromNamespace(bool id) + { + llinfos << (id ? "Foo::logFromNamespace: " : "") << "hi" << llendl; + //return "Foo::logFromNamespace"; + // there is no standard way to get the namespace name, hence + // we won't be testing for it + return "logFromNamespace"; + } +} + +namespace +{ + class ClassWithNoLogType { + public: + std::string logFromMember(bool id) + { + llinfos << (id ? "ClassWithNoLogType::logFromMember: " : "") << "hi" << llendl; + return "ClassWithNoLogType::logFromMember"; + } + static std::string logFromStatic(bool id) + { + llinfos << (id ? "ClassWithNoLogType::logFromStatic: " : "") << "hi" << llendl; + return "ClassWithNoLogType::logFromStatic"; + } + }; + + class ClassWithLogType { + LOG_CLASS(ClassWithLogType); + public: + std::string logFromMember(bool id) + { + llinfos << (id ? "ClassWithLogType::logFromMember: " : "") << "hi" << llendl; + return "ClassWithLogType::logFromMember"; + } + static std::string logFromStatic(bool id) + { + llinfos << (id ? "ClassWithLogType::logFromStatic: " : "") << "hi" << llendl; + return "ClassWithLogType::logFromStatic"; + } + }; + + std::string logFromNamespace(bool id) { return Foo::logFromNamespace(id); } + std::string logFromClassWithNoLogTypeMember(bool id) { ClassWithNoLogType c; return c.logFromMember(id); } + std::string logFromClassWithNoLogTypeStatic(bool id) { return ClassWithNoLogType::logFromStatic(id); } + std::string logFromClassWithLogTypeMember(bool id) { ClassWithLogType c; return c.logFromMember(id); } + std::string logFromClassWithLogTypeStatic(bool id) { return ClassWithLogType::logFromStatic(id); } + + void ensure_has(const std::string& message, + const std::string& actual, const std::string& expected) + { + std::string::size_type n1 = actual.find(expected); + if (n1 == std::string::npos) + { + std::stringstream ss; + ss << message << ": " << "expected to find a copy of " << expected + << " in actual " << actual; + throw tut::failure(ss.str().c_str()); + } + } + + typedef std::string (*LogFromFunction)(bool); + void testLogName(TestRecorder& recorder, LogFromFunction f, + const std::string& class_name = "") + { + recorder.clearMessages(); + std::string name = f(false); + f(true); + + std::string messageWithoutName = recorder.message(0); + std::string messageWithName = recorder.message(1); + + ensure_has(name + " logged without name", + messageWithoutName, name); + ensure_has(name + " logged with name", + messageWithName, name); + + if (!class_name.empty()) + { + ensure_has(name + "logged without name", + messageWithoutName, class_name); + ensure_has(name + "logged with name", + messageWithName, class_name); + } + } +} + +namespace tut +{ + template<> template<> + // class/function information in output + void ErrorTestObject::test<6>() + { + testLogName(mRecorder, logFromGlobal); + testLogName(mRecorder, logFromStatic); + testLogName(mRecorder, logFromAnon); + testLogName(mRecorder, logFromNamespace); + //testLogName(mRecorder, logFromClassWithNoLogTypeMember, "ClassWithNoLogType"); + //testLogName(mRecorder, logFromClassWithNoLogTypeStatic, "ClassWithNoLogType"); + // XXX: figure out what the exepcted response is for these + testLogName(mRecorder, logFromClassWithLogTypeMember, "ClassWithLogType"); + testLogName(mRecorder, logFromClassWithLogTypeStatic, "ClassWithLogType"); + } +} + +namespace +{ + std::string innerLogger() + { + llinfos << "inside" << llendl; + return "moo"; + } + + std::string outerLogger() + { + llinfos << "outside(" << innerLogger() << ")" << llendl; + return "bar"; + } + + void uberLogger() + { + llinfos << "uber(" << outerLogger() << "," << innerLogger() << ")" << llendl; + } + + class LogWhileLogging + { + public: + void print(std::ostream& out) const + { + llinfos << "logging" << llendl; + out << "baz"; + } + }; + + std::ostream& operator<<(std::ostream& out, const LogWhileLogging& l) + { l.print(out); return out; } + + void metaLogger() + { + LogWhileLogging l; + llinfos << "meta(" << l << ")" << llendl; + } + +} + +namespace tut +{ + template<> template<> + // handle nested logging + void ErrorTestObject::test<7>() + { + outerLogger(); + ensure_message_contains(0, "inside"); + ensure_message_contains(1, "outside(moo)"); + ensure_message_count(2); + + uberLogger(); + ensure_message_contains(2, "inside"); + ensure_message_contains(3, "inside"); + ensure_message_contains(4, "outside(moo)"); + ensure_message_contains(5, "uber(bar,moo)"); + ensure_message_count(6); + + metaLogger(); + ensure_message_contains(6, "logging"); + ensure_message_contains(7, "meta(baz)"); + ensure_message_count(8); + } + + template<> template<> + // special handling of llerrs calls + void ErrorTestObject::test<8>() + { + LLError::setPrintLocation(false); + std::string location = errorReturningLocation(); + + ensure_message_contains(0, location + "error"); + ensure_message_contains(1, "die"); + ensure_message_count(2); + + ensure("fatal callback called", fatalWasCalled); + } +} + +namespace +{ + std::string roswell() + { + return "1947-07-08T03:04:05Z"; + } + + void ufoSighting() + { + llinfos << "ufo" << llendl; + } +} + +namespace tut +{ + template<> template<> + // time in output (for recorders that need it) + void ErrorTestObject::test<9>() + { + LLError::setTimeFunction(roswell); + + mRecorder.setWantsTime(false); + ufoSighting(); + ensure_message_contains(0, "ufo"); + ensure_message_does_not_contain(0, roswell()); + + mRecorder.setWantsTime(true); + ufoSighting(); + ensure_message_contains(1, "ufo"); + ensure_message_contains(1, roswell()); + } + + template<> template<> + // output order + void ErrorTestObject::test<10>() + { + LLError::setPrintLocation(true); + LLError::setTimeFunction(roswell); + mRecorder.setWantsTime(true); + std::string locationAndFunction = writeReturningLocationAndFunction(); + + ensure_equals("order is time type location function message", + mRecorder.message(0), + roswell() + " INFO: " + locationAndFunction + ": apple"); + } + + template<> template<> + // multiple recorders + void ErrorTestObject::test<11>() + { + TestRecorder altRecorder; + LLError::addRecorder(&altRecorder); + + llinfos << "boo" << llendl; + + ensure_message_contains(0, "boo"); + ensure_equals("alt recorder count", altRecorder.countMessages(), 1); + ensure_contains("alt recorder message 0", altRecorder.message(0), "boo"); + + LLError::setTimeFunction(roswell); + + TestRecorder anotherRecorder; + anotherRecorder.setWantsTime(true); + LLError::addRecorder(&anotherRecorder); + + llinfos << "baz" << llendl; + + std::string when = roswell(); + + ensure_message_does_not_contain(1, when); + ensure_equals("alt recorder count", altRecorder.countMessages(), 2); + ensure_does_not_contain("alt recorder message 1", altRecorder.message(1), when); + ensure_equals("another recorder count", anotherRecorder.countMessages(), 1); + ensure_contains("another recorder message 0", anotherRecorder.message(0), when); + } +} + +class TestAlpha +{ + LOG_CLASS(TestAlpha); +public: + static void doDebug() { lldebugs << "add dice" << llendl; } + static void doInfo() { llinfos << "any idea" << llendl; } + static void doWarn() { llwarns << "aim west" << llendl; } + static void doError() { llerrs << "ate eels" << llendl; } + static void doAll() { doDebug(); doInfo(); doWarn(); doError(); } +}; + +class TestBeta +{ + LOG_CLASS(TestBeta); +public: + static void doDebug() { lldebugs << "bed down" << llendl; } + static void doInfo() { llinfos << "buy iron" << llendl; } + static void doWarn() { llwarns << "bad word" << llendl; } + static void doError() { llerrs << "big easy" << llendl; } + static void doAll() { doDebug(); doInfo(); doWarn(); doError(); } +}; + +namespace tut +{ + template<> template<> + // filtering by class + void ErrorTestObject::test<12>() + { + LLError::setDefaultLevel(LLError::LEVEL_WARN); + LLError::setClassLevel("TestBeta", LLError::LEVEL_INFO); + + TestAlpha::doAll(); + TestBeta::doAll(); + + ensure_message_contains(0, "aim west"); + ensure_message_contains(1, "error"); + ensure_message_contains(2, "ate eels"); + ensure_message_contains(3, "buy iron"); + ensure_message_contains(4, "bad word"); + ensure_message_contains(5, "error"); + ensure_message_contains(6, "big easy"); + ensure_message_count(7); + } + + template<> template<> + // filtering by function, and that it will override class filtering + void ErrorTestObject::test<13>() + { + LLError::setDefaultLevel(LLError::LEVEL_DEBUG); + LLError::setClassLevel("TestBeta", LLError::LEVEL_WARN); + LLError::setFunctionLevel("TestBeta::doInfo", LLError::LEVEL_DEBUG); + LLError::setFunctionLevel("TestBeta::doError", LLError::LEVEL_NONE); + + TestBeta::doAll(); + ensure_message_contains(0, "buy iron"); + ensure_message_contains(1, "bad word"); + ensure_message_count(2); + } + + template<> template<> + // filtering by file + // and that it is overridden by both class and function filtering + void ErrorTestObject::test<14>() + { + LLError::setDefaultLevel(LLError::LEVEL_DEBUG); + LLError::setFileLevel(LLError::abbreviateFile(__FILE__), + LLError::LEVEL_WARN); + LLError::setClassLevel("TestAlpha", LLError::LEVEL_INFO); + LLError::setFunctionLevel("TestAlpha::doError", + LLError::LEVEL_NONE); + LLError::setFunctionLevel("TestBeta::doError", + LLError::LEVEL_NONE); + + TestAlpha::doAll(); + TestBeta::doAll(); + ensure_message_contains(0, "any idea"); + ensure_message_contains(1, "aim west"); + ensure_message_contains(2, "bad word"); + ensure_message_count(3); + } + + template<> template<> + // proper cached, efficient lookup of filtering + void ErrorTestObject::test<15>() + { + LLError::setDefaultLevel(LLError::LEVEL_NONE); + + TestAlpha::doInfo(); + ensure_message_count(0); + ensure_equals("first check", LLError::shouldLogCallCount(), 1); + TestAlpha::doInfo(); + ensure_message_count(0); + ensure_equals("second check", LLError::shouldLogCallCount(), 1); + + LLError::setClassLevel("TestAlpha", LLError::LEVEL_DEBUG); + TestAlpha::doInfo(); + ensure_message_count(1); + ensure_equals("third check", LLError::shouldLogCallCount(), 2); + TestAlpha::doInfo(); + ensure_message_count(2); + ensure_equals("fourth check", LLError::shouldLogCallCount(), 2); + + LLError::setClassLevel("TestAlpha", LLError::LEVEL_WARN); + TestAlpha::doInfo(); + ensure_message_count(2); + ensure_equals("fifth check", LLError::shouldLogCallCount(), 3); + TestAlpha::doInfo(); + ensure_message_count(2); + ensure_equals("sixth check", LLError::shouldLogCallCount(), 3); + } + + template<> template<> + // configuration from LLSD + void ErrorTestObject::test<16>() + { + std::string this_file = LLError::abbreviateFile(__FILE__); + LLSD config; + config["print-location"] = true; + config["default-level"] = "DEBUG"; + + LLSD set1; + set1["level"] = "WARN"; + set1["files"][0] = this_file; + + LLSD set2; + set2["level"] = "INFO"; + set2["classes"][0] = "TestAlpha"; + + LLSD set3; + set3["level"] = "NONE"; + set3["functions"][0] = "TestAlpha::doError"; + set3["functions"][1] = "TestBeta::doError"; + + config["settings"][0] = set1; + config["settings"][1] = set2; + config["settings"][2] = set3; + + LLError::configure(config); + + TestAlpha::doAll(); + TestBeta::doAll(); + ensure_message_contains(0, "any idea"); + ensure_message_contains(0, this_file); + ensure_message_contains(1, "aim west"); + ensure_message_contains(2, "bad word"); + ensure_message_count(3); + + // make sure reconfiguring works + LLSD config2; + config2["default-level"] = "WARN"; + + LLError::configure(config2); + + TestAlpha::doAll(); + TestBeta::doAll(); + ensure_message_contains(3, "aim west"); + ensure_message_does_not_contain(3, this_file); + ensure_message_contains(4, "error"); + ensure_message_contains(5, "ate eels"); + ensure_message_contains(6, "bad word"); + ensure_message_contains(7, "error"); + ensure_message_contains(8, "big easy"); + ensure_message_count(9); + } +} + +/* Tests left: + handling of classes without LOG_CLASS + + live update of filtering from file + + syslog recorder + file recorder + cerr/stderr recorder + fixed buffer recorder + windows recorder + + mutex use when logging (?) + strange careful about to crash handling (?) +*/ diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt index c40f16e02c..27f3582562 100644 --- a/indra/test/CMakeLists.txt +++ b/indra/test/CMakeLists.txt @@ -34,7 +34,6 @@ set(test_SOURCE_FILES llbuffer_tut.cpp lldependencies_tut.cpp lldoubledispatch_tut.cpp - llerror_tut.cpp llevents_tut.cpp llhost_tut.cpp llhttpdate_tut.cpp -- cgit v1.3 From ad583afe2caf05a8cb4b4f6409d9157153a26a22 Mon Sep 17 00:00:00 2001 From: Adam Moss Date: Thu, 15 Oct 2009 18:12:10 +0000 Subject: DEV-41354 #includes tidyup. --- indra/llcommon/tests/llerror_test.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp index 930047e164..8055647b94 100644 --- a/indra/llcommon/tests/llerror_test.cpp +++ b/indra/llcommon/tests/llerror_test.cpp @@ -31,9 +31,17 @@ * $/LicenseInfo$ */ +#include + #include "linden_common.h" + #include "../llerror.h" +#include "../llerrorcontrol.h" +#include "../llsd.h" + +#include "../test/lltut.h" + namespace { void test_that_error_h_includes_enough_things_to_compile_a_message() @@ -42,13 +50,6 @@ namespace } } -#include "../test/lltut.h" - -#include - -#include "../llerrorcontrol.h" -#include "../llsd.h" - namespace { static bool fatalWasCalled; -- cgit v1.3 From 35c0d21c1ec4628462ec766e39f1d5b77df54d17 Mon Sep 17 00:00:00 2001 From: Adam Moss Date: Thu, 15 Oct 2009 18:44:59 +0000 Subject: DEV-41366 convert monolithic llbase64 test into a llcommon integration test. --- indra/llcommon/CMakeLists.txt | 1 + indra/llcommon/tests/llbase64_test.cpp | 83 ++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 indra/llcommon/tests/llbase64_test.cpp (limited to 'indra/llcommon') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 414aaea08b..cc55742df6 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -242,6 +242,7 @@ LL_ADD_PROJECT_UNIT_TESTS(llcommon "${llcommon_TEST_SOURCE_FILES}") #set(TEST_DEBUG on) set(test_libs llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES}) LL_ADD_INTEGRATION_TEST(commonmisc "" "${test_libs}") +LL_ADD_INTEGRATION_TEST(llbase64 "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lldate "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llerror "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llframetimer "" "${test_libs}") diff --git a/indra/llcommon/tests/llbase64_test.cpp b/indra/llcommon/tests/llbase64_test.cpp new file mode 100644 index 0000000000..dde43b5169 --- /dev/null +++ b/indra/llcommon/tests/llbase64_test.cpp @@ -0,0 +1,83 @@ +/** + * @file llbase64_tut.cpp + * @author James Cook + * @date 2007-02-04 + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-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 + +#include "linden_common.h" + +#include "../llbase64.h" +#include "../lluuid.h" + +#include "../test/lltut.h" + +namespace tut +{ + struct base64_data + { + }; + typedef test_group base64_test; + typedef base64_test::object base64_object; + tut::base64_test base64("base64"); + + template<> template<> + void base64_object::test<1>() + { + std::string result; + + result = LLBase64::encode(NULL, 0); + ensure("encode nothing", (result == "") ); + + LLUUID nothing; + result = LLBase64::encode(¬hing.mData[0], UUID_BYTES); + ensure("encode blank uuid", + (result == "AAAAAAAAAAAAAAAAAAAAAA==") ); + + LLUUID id("526a1e07-a19d-baed-84c4-ff08a488d15e"); + result = LLBase64::encode(&id.mData[0], UUID_BYTES); + ensure("encode random uuid", + (result == "UmoeB6Gduu2ExP8IpIjRXg==") ); + + } + + template<> template<> + void base64_object::test<2>() + { + std::string result; + + U8 blob[40] = { 115, 223, 172, 255, 140, 70, 49, 125, 236, 155, 45, 199, 101, 17, 164, 131, 230, 19, 80, 64, 112, 53, 135, 98, 237, 12, 26, 72, 126, 14, 145, 143, 118, 196, 11, 177, 132, 169, 195, 134 }; + result = LLBase64::encode(&blob[0], 40); + ensure("encode 40 bytes", + (result == "c9+s/4xGMX3smy3HZRGkg+YTUEBwNYdi7QwaSH4OkY92xAuxhKnDhg==") ); + } + +} -- cgit v1.3 From 9672abecd4b2bbcb9a6b6d0f30b0df97da079f22 Mon Sep 17 00:00:00 2001 From: Adam Moss Date: Thu, 15 Oct 2009 18:51:23 +0000 Subject: DEV-41367 resurrect dead bitpack test, convert it to a llcommon integration test. --- indra/llcommon/CMakeLists.txt | 1 + indra/llcommon/bitpack.cpp | 36 ++++++++++ indra/llcommon/tests/bitpack_test.cpp | 125 ++++++++++++++++++++++++++++++++++ 3 files changed, 162 insertions(+) create mode 100644 indra/llcommon/bitpack.cpp create mode 100644 indra/llcommon/tests/bitpack_test.cpp (limited to 'indra/llcommon') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index cc55742df6..d635fad832 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -242,6 +242,7 @@ LL_ADD_PROJECT_UNIT_TESTS(llcommon "${llcommon_TEST_SOURCE_FILES}") #set(TEST_DEBUG on) set(test_libs llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES}) 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(llerror "" "${test_libs}") diff --git a/indra/llcommon/bitpack.cpp b/indra/llcommon/bitpack.cpp new file mode 100644 index 0000000000..8db403febf --- /dev/null +++ b/indra/llcommon/bitpack.cpp @@ -0,0 +1,36 @@ +/** + * @file bitpack.cpp + * @brief LLBitPack class implementation + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-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" + +// implementation is all in the header, this include dep ensures the unit test is rerun if the implementation changes. +#include "bitpack.h" diff --git a/indra/llcommon/tests/bitpack_test.cpp b/indra/llcommon/tests/bitpack_test.cpp new file mode 100644 index 0000000000..09fd037f02 --- /dev/null +++ b/indra/llcommon/tests/bitpack_test.cpp @@ -0,0 +1,125 @@ +/** + * @file bitpack_test.cpp + * @author Adroit + * @date 2007-02 + * @brief llstreamtools test cases. + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-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 "../bitpack.h" + +#include "../test/lltut.h" + + +namespace tut +{ + struct bit_pack + { + }; + typedef test_group bit_pack_t; + typedef bit_pack_t::object bit_pack_object_t; + tut::bit_pack_t tut_bit_pack("bitpack"); + + // pack -> unpack + template<> template<> + void bit_pack_object_t::test<1>() + { + U8 packbuffer[255]; + U8 unpackbuffer[255]; + int pack_bufsize = 0; + int unpack_bufsize = 0; + + LLBitPack bitpack(packbuffer, 255); + + char str[] = "SecondLife is a 3D virtual world"; + int len = sizeof(str); + pack_bufsize = bitpack.bitPack((U8*) str, len*8); + pack_bufsize = bitpack.flushBitPack(); + + LLBitPack bitunpack(packbuffer, pack_bufsize*8); + unpack_bufsize = bitunpack.bitUnpack(unpackbuffer, len*8); + ensure("bitPack: unpack size should be same as string size prior to pack", len == unpack_bufsize); + ensure_memory_matches("str->bitPack->bitUnpack should be equal to string", str, len, unpackbuffer, unpack_bufsize); + } + + // pack large, unpack in individual bytes + template<> template<> + void bit_pack_object_t::test<2>() + { + U8 packbuffer[255]; + U8 unpackbuffer[255]; + int pack_bufsize = 0; + int unpack_bufsize = 0; + + LLBitPack bitpack(packbuffer, 255); + + char str[] = "SecondLife"; + int len = sizeof(str); + pack_bufsize = bitpack.bitPack((U8*) str, len*8); + pack_bufsize = bitpack.flushBitPack(); + + LLBitPack bitunpack(packbuffer, pack_bufsize*8); + unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8); + ensure("bitPack: individual unpack: 0", unpackbuffer[0] == (U8) str[0]); + unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8); + ensure("bitPack: individual unpack: 1", unpackbuffer[0] == (U8) str[1]); + unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8); + ensure("bitPack: individual unpack: 2", unpackbuffer[0] == (U8) str[2]); + unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8); + ensure("bitPack: individual unpack: 3", unpackbuffer[0] == (U8) str[3]); + unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8); + ensure("bitPack: individual unpack: 4", unpackbuffer[0] == (U8) str[4]); + unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8); + ensure("bitPack: individual unpack: 5", unpackbuffer[0] == (U8) str[5]); + unpack_bufsize = bitunpack.bitUnpack(unpackbuffer, 8*4); // Life + ensure_memory_matches("bitPack: 4 bytes unpack:", unpackbuffer, 4, str+6, 4); + } + + // U32 packing + template<> template<> + void bit_pack_object_t::test<3>() + { + U8 packbuffer[255]; + int pack_bufsize = 0; + + LLBitPack bitpack(packbuffer, 255); + U32 num = 0x41fab67a; + pack_bufsize = bitpack.bitPack((U8*)&num, 8*sizeof(U32)); + pack_bufsize = bitpack.flushBitPack(); + + LLBitPack bitunpack(packbuffer, pack_bufsize*8); + U32 res = 0; + // since packing and unpacking is done on same machine in the unit test run, + // endianness should not matter + bitunpack.bitUnpack((U8*) &res, sizeof(res)*8); + ensure("U32->bitPack->bitUnpack->U32 should be equal", num == res); + } +} -- cgit v1.3