Apertura del repositorio

This commit is contained in:
2025-05-24 18:09:39 -03:00
parent 76e6359dad
commit d883ddd0d0
35253 changed files with 2891973 additions and 2 deletions
+120
View File
@@ -0,0 +1,120 @@
# -*- cmake -*-
project (lltest)
include(00-Common)
include(LLCommon)
include(LLCoreHttp)
include(Linking)
include(Tut)
include(LLAddBuildTest)
include(bugsplat)
set(test_SOURCE_FILES
io.cpp
llapp_tut.cpp
llblowfish_tut.cpp
llbuffer_tut.cpp
lldoubledispatch_tut.cpp
llevents_tut.cpp
llhttpdate_tut.cpp
llhttpnode_tut.cpp
lliohttpserver_tut.cpp
llmessageconfig_tut.cpp
llpermissions_tut.cpp
llpipeutil.cpp
llsaleinfo_tut.cpp
llsdmessagebuilder_tut.cpp
llsdmessagereader_tut.cpp
llsd_new_tut.cpp
llsdutil_tut.cpp
llservicebuilder_tut.cpp
llstreamtools_tut.cpp
lltemplatemessagebuilder_tut.cpp
lltut.cpp
message_tut.cpp
test.cpp
)
set(test_HEADER_FILES
CMakeLists.txt
debug.h
llpipeutil.h
llsdtraits.h
lltut.h
sync.h
)
if (NOT WINDOWS)
list(APPEND test_SOURCE_FILES
llmessagetemplateparser_tut.cpp
)
endif (NOT WINDOWS)
list(APPEND test_SOURCE_FILES ${test_HEADER_FILES})
add_executable(lltest ${test_SOURCE_FILES})
target_link_libraries(lltest
llinventory
llmessage
llmath
llfilesystem
llxml
llcommon
llcorehttp
)
if (WINDOWS)
set_target_properties(lltest
PROPERTIES
LINK_FLAGS "/NODEFAULTLIB:LIBCMT"
LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\""
RUNTIME_OUTPUT_DIRECTORY "${EXE_STAGING_DIR}"
)
elseif (DARWIN)
# Support our "@executable_path/../Resources" load path for our test
# executable. This SHOULD properly be "$<TARGET_FILE_DIR:lltest>/Resources",
# but the CMake $<TARGET_FILE_DIR> generator expression isn't evaluated by
# CREATE_LINK, so fudge it.
file(CREATE_LINK "../sharedlibs/Release/Resources" "${CMAKE_BINARY_DIR}/test/Resources"
SYMBOLIC)
endif (WINDOWS)
set(TEST_EXE $<TARGET_FILE:lltest>)
SET_TEST_PATH(LD_LIBRARY_PATH)
LL_TEST_COMMAND(command
"${LD_LIBRARY_PATH}"
"${TEST_EXE}"
"--output=${CMAKE_CURRENT_BINARY_DIR}/cpp_test_results.txt"
"--touch=${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt")
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt
COMMAND ${command}
DEPENDS lltest
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "C++ unit tests"
)
set(test_results ${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt)
# This should cause the test executable to be built, but not
# run if LL_TESTS is disabled. This will hopefully keep the
# tests up to date with any code changes changes even if
# developers choose to disable LL_TESTS.
if (LL_TESTS)
add_custom_target(tests_ok ALL DEPENDS ${test_results})
if(DARWIN)
# Support our "@executable_path/../Resources" load path for our test
# executable. This SHOULD properly be "$<TARGET_FILE_DIR:lltest>/Resources",
# but the CMake $<TARGET_FILE_DIR> generator expression isn't evaluated by
# CREATE_LINK, so fudge it.
add_custom_command( TARGET lltest POST_BUILD
COMMAND cmake -E create_symlink ${SHARED_LIB_STAGING_DIR} ${CMAKE_BINARY_DIR}/test/Resources
)
endif()
endif (LL_TESTS)
+1
View File
@@ -0,0 +1 @@
.A„Ä3ŒLÜE ``òøÝKÛ@¼ûÇ;M[ÚBë·ø„>ËÊC—'
BIN
View File
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
01234567890123456789012345678901234
+79
View File
@@ -0,0 +1,79 @@
#!/usr/bin/perl
#
# Test Perl Crypt::CBC Blowfish algorithm and initial parameter settings
# for compatibility with OpenSSL's Blowfish algorithm/settings.
#
# Used by outbound LSL email (openssl C library) and mailglue (Perl library)
use strict;
use warnings;
# *TODO: specify test count here
use Test::More qw(no_plan);
use Crypt::CBC;
use MIME::Base64;
my $init_vector = "\x00" x 8;
# my $key = pack("H*", "ef5a8376eb0c99fe0dafa487d15bec19cae63d1e25fe31d8d92f7ab0398246d70ee733108e47360e16359654571cf5bab6c3375b42cee4fa");
# my $key = "d263eb8a78034e40";
#"8d082918aa369174";
my $key = "\x00" x 16;
my $cipher = Crypt::CBC->new( { cipher => 'Blowfish',
regenerate_key => 0,
key => $key,
iv => $init_vector,
header => 'none',
prepend_iv => 0,
keysize => 16 } );
#my $blocks = $cipher->blocksize();
#print "blocksize $blocks\n";
my $len;
my $input = "01234567890123456789012345678901234\n";
#my $input = "a whale of a tale I tell you lad, a whale of a tale for me, a whale of a tale and the fiddlers three";
$len = length($input);
is ($len, 36, "input length");
$len = length($key);
is ($len, 16, "key length");
my $encrypted = $cipher->encrypt($input);
is (length($encrypted), 40, "encrypted length");
open(FH, "blowfish.1.bin");
my $bin = scalar <FH>;
is ($encrypted, $bin, "matches openssl");
close(FH);
my $base64 = encode_base64($encrypted);
is ($base64, "LkGExDOMTNxFIGBg8gP43UvbQLz7xztNWwYF2kLrtwT4hD7LykOXJw==\n",
"base64 output");
my $unbase64 = decode_base64($base64);
is( $encrypted, $unbase64, "reverse base64" );
my $output = $cipher->decrypt($unbase64);
is ($input, $output, "reverse encrypt");
$key = pack("H[32]", "526a1e07a19dbaed84c4ff08a488d15e");
$cipher = Crypt::CBC->new( { cipher => 'Blowfish',
regenerate_key => 0,
key => $key,
iv => $init_vector,
header => 'none',
prepend_iv => 0,
keysize => 16 } );
$encrypted = $cipher->encrypt($input);
is (length($encrypted), 40, "uuid encrypted length");
$output = $cipher->decrypt($encrypted);
is ($input, $output, "uuid reverse encrypt");
open(FH, "blowfish.2.bin");
$bin = scalar <FH>;
close(FH);
is( $encrypted, $bin, "uuid matches openssl" );
print encode_base64($encrypted);
+110
View File
@@ -0,0 +1,110 @@
/**
* @file catch_and_store_what_in.h
* @author Nat Goodspeed
* @date 2012-02-15
* @brief catch_what() template function, CATCH_AND_STORE_WHAT_IN() macro
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Copyright (c) 2012, Linden Research, Inc.
* $/LicenseInfo$
*/
#if ! defined(LL_CATCH_AND_STORE_WHAT_IN_H)
#define LL_CATCH_AND_STORE_WHAT_IN_H
/**
* In the brave new world of lambdas, we can use a nicer C++ idiom for testing
* exceptions than CATCH_AND_STORE_WHAT_IN() below, e.g.:
*
* @code
* std::string threw = catch_what<std::runtime_error>(
* [](){ throw std::runtime_error("badness"); });
* ensure_equals(threw, "badness");
* @endcode
*/
template <typename EXCEPTION, typename FUNC>
std::string catch_what(FUNC func)
{
try
{
func();
return {};
}
catch (const EXCEPTION& err)
{
return err.what();
}
}
/**
* Idiom useful for test programs: catch an expected exception, store its
* what() string in a specified std::string variable. From there the caller
* can do things like:
* @code
* ensure("expected exception not thrown", ! string.empty());
* @endcode
* or
* @code
* ensure_contains("exception doesn't mention blah", string, "blah");
* @endcode
* etc.
*
* The trouble is that when linking to a dynamic libllcommon.so on Linux, we
* generally fail to catch the specific exception. Oddly, we can catch it as
* std::runtime_error and validate its typeid().name(), so we do -- but that's
* a lot of boilerplate per test. Encapsulate with this macro. Usage:
*
* @code
* std::string threw;
* try
* {
* some_call_that_should_throw_Foo();
* }
* CATCH_AND_STORE_WHAT_IN(threw, Foo)
* ensure("some_call_that_should_throw_Foo() didn't throw", ! threw.empty());
* @endcode
*/
#define CATCH_AND_STORE_WHAT_IN(THREW, EXCEPTION) \
catch (const EXCEPTION& ex) \
{ \
(THREW) = ex.what(); \
} \
CATCH_MISSED_LINUX_EXCEPTION(THREW, EXCEPTION)
#ifndef LL_LINUX
#define CATCH_MISSED_LINUX_EXCEPTION(THREW, EXCEPTION) \
/* only needed on Linux */
#else // LL_LINUX
#define CATCH_MISSED_LINUX_EXCEPTION(THREW, EXCEPTION) \
catch (const std::runtime_error& ex) \
{ \
/* This clause is needed on Linux, on the viewer side, because */ \
/* the exception isn't caught by catch (const EXCEPTION&). */ \
/* But if the expected exception was thrown, allow the test to */ \
/* succeed anyway. Not sure how else to handle this odd case. */ \
if (std::string(typeid(ex).name()) == typeid(EXCEPTION).name()) \
{ \
/* std::cerr << "Caught " << typeid(ex).name() */ \
/* << " with Linux workaround" << std::endl; */ \
(THREW) = ex.what(); \
/*std::cout << ex.what() << std::endl;*/ \
} \
else \
{ \
/* We don't even recognize this exception. Let it propagate */ \
/* out to TUT to fail the test. */ \
throw; \
} \
} \
catch (...) \
{ \
std::cerr << "Failed to catch expected exception " \
<< #EXCEPTION << "!" << std::endl; \
/* This indicates a problem in the test that should be addressed. */ \
throw; \
}
#endif // LL_LINUX
#endif /* ! defined(LL_CATCH_AND_STORE_WHAT_IN_H) */
+107
View File
@@ -0,0 +1,107 @@
/**
* @file chained_callback.h
* @author Nat Goodspeed
* @date 2020-01-03
* @brief Subclass of tut::callback used for chaining callbacks.
*
* $LicenseInfo:firstyear=2020&license=viewerlgpl$
* Copyright (c) 2020, Linden Research, Inc.
* $/LicenseInfo$
*/
#if ! defined(LL_CHAINED_CALLBACK_H)
#define LL_CHAINED_CALLBACK_H
#include "lltut.h"
/**
* Derive your TUT callback from chained_callback instead of tut::callback to
* ensure that multiple such callbacks can coexist in a given test executable.
* The relevant callback method will be called for each callback instance in
* reverse order of the instance's link() methods being called: the most
* recently link()ed callback will be called first, then the previous, and so
* forth.
*
* Obviously, for this to work, all relevant callbacks must be derived from
* chained_callback instead of tut::callback. Given that, control should reach
* each of them regardless of their construction order. The chain is
* guaranteed to stop because the first link() call will link to test_runner's
* default_callback, which is simply an instance of the callback() base class.
*
* The rule for deriving from chained_callback is that you may override any of
* its virtual methods, but your override must at some point call the
* corresponding chained_callback method.
*/
class chained_callback: public tut::callback
{
public:
/**
* Instead of calling tut::test_runner::set_callback(&your_callback), call
* your_callback.link();
* This uses the canonical instance of tut::test_runner.
*/
void link()
{
link(tut::runner.get());
}
/**
* If for some reason you have a different instance of test_runner...
*/
void link(tut::test_runner& runner)
{
// Since test_runner's constructor sets a default callback,
// get_callback() will always return a reference to a valid callback
// instance.
mPrev = &runner.get_callback();
runner.set_callback(this);
}
/**
* Called when new test run started.
*/
virtual void run_started()
{
mPrev->run_started();
}
/**
* Called when a group started
* @param name Name of the group
*/
virtual void group_started(const std::string& name)
{
mPrev->group_started(name);
}
/**
* Called when a test finished.
* @param tr Test results.
*/
virtual void test_completed(const tut::test_result& tr)
{
mPrev->test_completed(tr);
}
/**
* Called when a group is completed
* @param name Name of the group
*/
virtual void group_completed(const std::string& name)
{
mPrev->group_completed(name);
}
/**
* Called when all tests in run completed.
*/
virtual void run_completed()
{
mPrev->run_completed();
}
private:
tut::callback* mPrev;
};
#endif /* ! defined(LL_CHAINED_CALLBACK_H) */
+107
View File
@@ -0,0 +1,107 @@
/**
* @file debug.h
* @author Nat Goodspeed
* @date 2009-05-28
* @brief Debug output for unit test code
*
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#if ! defined(LL_DEBUG_H)
#define LL_DEBUG_H
#include "print.h"
/*****************************************************************************
* Debugging stuff
*****************************************************************************/
/**
* This class is intended to illuminate entry to a given block, exit from the
* same block and checkpoints along the way. It also provides a convenient
* place to turn std::cerr output on and off.
*
* If the environment variable LOGTEST is non-empty, each Debug instance will
* announce its construction and destruction, presumably at entry and exit to
* the block in which it's declared. Moreover, any arguments passed to its
* operator()() will be streamed to std::cerr, prefixed by the block
* description.
*
* The variable LOGTEST is used because that's the environment variable
* checked by test.cpp, our TUT main() program, to turn on LLError logging. It
* is expected that Debug is solely for use in test programs.
*/
class Debug
{
public:
Debug(const std::string& block):
mBlock(block),
mLOGTEST(getenv("LOGTEST")),
// debug output enabled when LOGTEST is set AND non-empty
mEnabled(mLOGTEST && *mLOGTEST)
{
(*this)("entry");
}
// non-copyable
Debug(const Debug&) = delete;
~Debug()
{
(*this)("exit");
}
template <typename... ARGS>
void operator()(ARGS&&... args)
{
if (mEnabled)
{
print(mBlock, ' ', std::forward<ARGS>(args)...);
}
}
private:
const std::string mBlock;
const char* mLOGTEST;
bool mEnabled;
};
// It's often convenient to use the name of the enclosing function as the name
// of the Debug block.
#define DEBUG Debug debug(LL_PRETTY_FUNCTION)
// These BEGIN/END macros are specifically for debugging output -- please
// don't assume you must use such for coroutines in general! They only help to
// make control flow (as well as exception exits) explicit.
#define BEGIN \
{ \
DEBUG; \
try
#define END \
catch (...) \
{ \
debug("*** exceptional "); \
throw; \
} \
}
#endif /* ! defined(LL_DEBUG_H) */
+97
View File
@@ -0,0 +1,97 @@
/**
* @file hexdump.h
* @author Nat Goodspeed
* @date 2023-09-08
* @brief Provide hexdump() and hexmix() ostream formatters
*
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Copyright (c) 2023, Linden Research, Inc.
* $/LicenseInfo$
*/
#if ! defined(LL_HEXDUMP_H)
#define LL_HEXDUMP_H
#include <cctype>
#include <iomanip>
#include <iostream>
#include <string_view>
// Format a given byte string as 2-digit hex values, no separators
// Usage: std::cout << hexdump(somestring) << ...
class hexdump
{
public:
hexdump(const std::string_view& data):
hexdump(data.data(), data.length())
{}
hexdump(const char* data, size_t len):
hexdump(reinterpret_cast<const unsigned char*>(data), len)
{}
hexdump(const unsigned char* data, size_t len):
mData(data, data + len)
{}
friend std::ostream& operator<<(std::ostream& out, const hexdump& self)
{
auto oldfmt{ out.flags() };
auto oldfill{ out.fill() };
out.setf(std::ios_base::hex, std::ios_base::basefield);
out.fill('0');
for (auto c : self.mData)
{
out << std::setw(2) << unsigned(c);
}
out.setf(oldfmt, std::ios_base::basefield);
out.fill(oldfill);
return out;
}
private:
std::vector<unsigned char> mData;
};
// Format a given byte string as a mix of printable characters and, for each
// non-printable character, "\xnn"
// Usage: std::cout << hexmix(somestring) << ...
class hexmix
{
public:
hexmix(const std::string_view& data):
mData(data)
{}
hexmix(const char* data, size_t len):
mData(data, len)
{}
friend std::ostream& operator<<(std::ostream& out, const hexmix& self)
{
auto oldfmt{ out.flags() };
auto oldfill{ out.fill() };
out.setf(std::ios_base::hex, std::ios_base::basefield);
out.fill('0');
for (auto c : self.mData)
{
// std::isprint() must be passed an unsigned char!
if (std::isprint(static_cast<unsigned char>(c)))
{
out << c;
}
else
{
out << "\\x" << std::setw(2) << unsigned(c);
}
}
out.setf(oldfmt, std::ios_base::basefield);
out.fill(oldfill);
return out;
}
private:
std::string mData;
};
#endif /* ! defined(LL_HEXDUMP_H) */
+1181
View File
File diff suppressed because one or more lines are too long
+162
View File
@@ -0,0 +1,162 @@
/**
* @file llapp_tut.cpp
* @author Phoenix
* @date 2006-09-12
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2006-2011, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include <tut/tut.hpp>
#include "linden_common.h"
#include "llapp.h"
#include "lltut.h"
namespace tut
{
struct application
{
class LLTestApp : public LLApp
{
public:
virtual bool init() { return true; }
virtual bool cleanup() { return true; }
virtual bool frame() { return true; }
};
LLTestApp* mApp;
application()
{
mApp = new LLTestApp;
}
~application()
{
delete mApp;
}
};
typedef test_group<application> application_t;
typedef application_t::object application_object_t;
tut::application_t tut_application("application");
template<> template<>
void application_object_t::test<1>()
{
LLSD defaults;
defaults["template"] = "../../../scripts/messages/message_template.msg";
defaults["configdir"] = ".";
defaults["datadir"] = "data";
mApp->setOptionData(LLApp::PRIORITY_DEFAULT, defaults);
LLSD datadir_sd = mApp->getOption("datadir");
ensure_equals("data type", datadir_sd.type(), LLSD::TypeString);
ensure_equals(
"data value", datadir_sd.asString(), std::string("data"));
}
template<> template<>
void application_object_t::test<2>()
{
const int ARGC = 13;
const char* ARGV[ARGC] =
{
"", // argv[0] is usually the application name
"-crashcount",
"2",
"-space",
"spaceserver.grid.lindenlab.com",
"-db_host",
"localhost",
"--allowlslhttprequests",
"-asset-uri",
"http://test.lindenlab.com/assets",
"-data",
"127.0.0.1",
"--smtp"
};
bool ok = mApp->parseCommandOptions(ARGC, const_cast<char**>(ARGV));
ensure("command line parsed", ok);
ensure_equals(
"crashcount", mApp->getOption("crashcount").asInteger(), 2);
ensure_equals(
"space",
mApp->getOption("space").asString(),
std::string("spaceserver.grid.lindenlab.com"));
ensure_equals(
"db_host",
mApp->getOption("db_host").asString(),
std::string("localhost"));
ensure("allowlshlttprequests", mApp->getOption("smtp"));
ensure_equals(
"asset-uri",
mApp->getOption("asset-uri").asString(),
std::string("http://test.lindenlab.com/assets"));
ensure_equals(
"data",
mApp->getOption("data").asString(),
std::string("127.0.0.1"));
ensure("smtp", mApp->getOption("smtp"));
}
template<> template<>
void application_object_t::test<3>()
{
const int ARGC = 4;
const char* ARGV[ARGC] =
{
"", // argv[0] is usually the application name
"crashcount",
"2",
"--space"
};
bool ok = mApp->parseCommandOptions(ARGC, const_cast<char**>(ARGV));
ensure("command line parse failure", !ok);
}
template<> template<>
void application_object_t::test<4>()
{
const int ARGC = 4;
const char* ARGV[ARGC] =
{
"", // argv[0] is usually the application name
"--crashcount",
"2",
"space"
};
bool ok = mApp->parseCommandOptions(ARGC, const_cast<char**>(ARGV));
ensure("command line parse failure", !ok);
}
template<> template<>
void application_object_t::test<5>()
{
LLSD options;
options["boolean-test"] = true;
mApp->setOptionData(LLApp::PRIORITY_GENERAL_CONFIGURATION, options);
ensure("bool set", mApp->getOption("boolean-test").asBoolean());
options["boolean-test"] = false;
mApp->setOptionData(LLApp::PRIORITY_RUNTIME_OVERRIDE, options);
ensure("bool unset", !mApp->getOption("boolean-test").asBoolean());
}
}
+195
View File
@@ -0,0 +1,195 @@
/**
* @file asset_upload_queue_tut.cpp
* @brief Tests for newview/llassetuploadqueue.cpp
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "lltut.h"
#include "mock_http_client.h"
#include "../newview/llassetuploadqueue.cpp"
// Mock implementation.
LLAssetUploadResponder::LLAssetUploadResponder(const LLSD& post_data,
const LLUUID& vfile_id,
LLAssetType::EType asset_type)
{
}
LLAssetUploadResponder::LLAssetUploadResponder(const LLSD& post_data, const std::string& file_name)
{
}
LLAssetUploadResponder::~LLAssetUploadResponder()
{
}
void LLAssetUploadResponder::httpFailure()
{
}
void LLAssetUploadResponder::httpSuccess()
{
}
void LLAssetUploadResponder::uploadUpload(const LLSD& content)
{
}
void LLAssetUploadResponder::uploadComplete(const LLSD& content)
{
}
void LLAssetUploadResponder::uploadFailure(const LLSD& content)
{
}
LLUpdateTaskInventoryResponder::LLUpdateTaskInventoryResponder(const LLSD& post_data,
const LLUUID& vfile_id,
LLAssetType::EType asset_type) :
LLAssetUploadResponder(post_data, vfile_id, asset_type)
{
}
LLUpdateTaskInventoryResponder::LLUpdateTaskInventoryResponder(const LLSD& post_data,
const std::string& file_name) :
LLAssetUploadResponder(post_data, file_name)
{
}
LLUpdateTaskInventoryResponder::LLUpdateTaskInventoryResponder(const LLSD& post_data,
const std::string& file_name,
const LLUUID& queue_id) :
LLAssetUploadResponder(post_data, file_name)
{
}
void LLUpdateTaskInventoryResponder::uploadComplete(const LLSD& content)
{
}
namespace tut
{
class asset_upload_queue_test_data : public MockHttpClient {};
typedef test_group<asset_upload_queue_test_data> asset_upload_queue_test;
typedef asset_upload_queue_test::object asset_upload_queue_object;
tut::asset_upload_queue_test asset_upload_queue("asset_upload_queue");
void queue(LLAssetUploadQueue& q, const std::string& filename)
{
LLUUID task_id;
LLUUID item_id;
BOOL is_running = FALSE;
BOOL is_target_mono = TRUE;
LLUUID queue_id;
q.queue(filename, task_id, item_id, is_running, is_target_mono, queue_id);
}
class LLTestSupplier : public LLAssetUploadQueueSupplier
{
public:
void set(LLAssetUploadQueue* queue) {mQueue = queue;}
virtual LLAssetUploadQueue* get() const
{
return mQueue;
}
private:
LLAssetUploadQueue* mQueue;
};
template<> template<>
void asset_upload_queue_object::test<1>()
{
setupTheServer();
reset();
LLTestSupplier* supplier = new LLTestSupplier();
LLAssetUploadQueue q("http://localhost:8888/test/success", supplier);
supplier->set(&q);
queue(q, "foo.bar");
ensure("upload queue not empty before request", q.isEmpty());
runThePump(10);
ensure("upload queue not empty after request", q.isEmpty());
}
template<> template<>
void asset_upload_queue_object::test<2>()
{
reset();
LLTestSupplier* supplier = new LLTestSupplier();
LLAssetUploadQueue q("http://localhost:8888/test/error", supplier);
supplier->set(&q);
queue(q, "foo.bar");
ensure("upload queue not empty before request", q.isEmpty());
runThePump(10);
ensure("upload queue not empty after request", q.isEmpty());
}
template<> template<>
void asset_upload_queue_object::test<3>()
{
reset();
LLTestSupplier* supplier = new LLTestSupplier();
LLAssetUploadQueue q("http://localhost:8888/test/timeout", supplier);
supplier->set(&q);
queue(q, "foo.bar");
ensure("upload queue not empty before request", q.isEmpty());
runThePump(10);
ensure("upload queue not empty after request", q.isEmpty());
}
template<> template<>
void asset_upload_queue_object::test<4>()
{
reset();
LLTestSupplier* supplier = new LLTestSupplier();
LLAssetUploadQueue q("http://localhost:8888/test/success", supplier);
supplier->set(&q);
queue(q, "foo.bar");
queue(q, "baz.bar");
ensure("upload queue empty before request", !q.isEmpty());
runThePump(10);
ensure("upload queue not empty before request", q.isEmpty());
runThePump(10);
ensure("upload queue not empty after request", q.isEmpty());
}
template<> template<>
void asset_upload_queue_object::test<5>()
{
reset();
LLTestSupplier* supplier = new LLTestSupplier();
LLAssetUploadQueue q("http://localhost:8888/test/success", supplier);
supplier->set(&q);
queue(q, "foo.bar");
runThePump(10);
ensure("upload queue not empty before request", q.isEmpty());
queue(q, "baz.bar");
ensure("upload queue not empty after request", q.isEmpty());
runThePump(10);
killServer();
}
}
+141
View File
@@ -0,0 +1,141 @@
/**
* @file llblowfish_tut.cpp
* @author James Cook, james@lindenlab.com
* @date 2007-02-04
*
* Data files generated with:
* openssl enc -bf-cbc -in blowfish.digits.txt -out blowfish.1.bin -K 00000000000000000000000000000000 -iv 0000000000000000 -p
* openssl enc -bf-cbc -in blowfish.digits.txt -out blowfish.2.bin -K 526a1e07a19dbaed84c4ff08a488d15e -iv 0000000000000000 -p
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "lltut.h"
#include "llblowfishcipher.h"
#include "lluuid.h"
namespace tut
{
class LLData
{
public:
unsigned char* mInput;
int mInputSize;
LLData()
{
// \n to make it easier to create text files
// for testing with command line openssl
mInput = (unsigned char*)"01234567890123456789012345678901234\n";
mInputSize = 36;
}
bool matchFile(const std::string& filename,
const std::string& data)
{
LLFILE* fp = LLFile::fopen(filename, "rb");
if (!fp)
{
// sometimes test is run inside the indra directory
std::string path = "test/";
path += filename;
fp = LLFile::fopen(path, "rb");
}
if (!fp)
{
LL_WARNS() << "unable to open " << filename << LL_ENDL;
return false;
}
std::string good;
good.resize(256);
size_t got = fread(&good[0], 1, 256, fp);
LL_DEBUGS() << "matchFile read " << got << LL_ENDL;
fclose(fp);
good.resize(got);
return (good == data);
}
};
typedef test_group<LLData> blowfish_test;
typedef blowfish_test::object blowfish_object;
// Create test with name that can be selected on
// command line of test app.
tut::blowfish_test blowfish("blowfish");
template<> template<>
void blowfish_object::test<1>()
{
LLUUID blank;
LLBlowfishCipher cipher(&blank.mData[0], UUID_BYTES);
U32 dst_len = cipher.requiredEncryptionSpace(36);
ensure("encryption space 36",
(dst_len == 40) );
// Blowfish adds an additional 8-byte block if your
// input is an exact multiple of 8
dst_len = cipher.requiredEncryptionSpace(8);
ensure("encryption space 8",
(dst_len == 16) );
}
template<> template<>
void blowfish_object::test<2>()
{
LLUUID blank;
LLBlowfishCipher cipher(&blank.mData[0], UUID_BYTES);
std::string result;
result.resize(256);
U32 count = cipher.encrypt(mInput, mInputSize,
(U8*) &result[0], 256);
ensure("encrypt output count",
(count == 40) );
result.resize(count);
ensure("encrypt null key", matchFile("blowfish.1.bin", result));
}
template<> template<>
void blowfish_object::test<3>()
{
// same as base64 test id
LLUUID id("526a1e07-a19d-baed-84c4-ff08a488d15e");
LLBlowfishCipher cipher(&id.mData[0], UUID_BYTES);
std::string result;
result.resize(256);
U32 count = cipher.encrypt(mInput, mInputSize,
(U8*) &result[0], 256);
ensure("encrypt output count",
(count == 40) );
result.resize(count);
ensure("encrypt real key", matchFile("blowfish.2.bin", result));
}
}
+271
View File
@@ -0,0 +1,271 @@
/**
* @file llbuffer_tut.cpp
* @author Adroit
* @date 2007-03
* @brief llbuffer test cases.
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include <tut/tut.hpp>
#include "linden_common.h"
#include "lltut.h"
#include "llbuffer.h"
#include "llerror.h"
namespace tut
{
struct buffer
{
};
typedef test_group<buffer> buffer_t;
typedef buffer_t::object buffer_object_t;
tut::buffer_t tut_buffer("buffer");
template<> template<>
void buffer_object_t::test<1>()
{
LLChannelDescriptors channelDescriptors;
ensure("in() and out() functions Failed", (0 == channelDescriptors.in() && 1 == channelDescriptors.out()));
S32 val = 50;
LLChannelDescriptors channelDescriptors1(val);
ensure("LLChannelDescriptors in() and out() functions Failed", (50 == channelDescriptors1.in() && 51 == channelDescriptors1.out()));
}
template<> template<>
void buffer_object_t::test<2>()
{
LLSegment segment;
ensure("LLSegment get functions failed", (0 == segment.getChannel() && NULL == segment.data() && 0 == segment.size()));
segment.setChannel(50);
ensure_equals("LLSegment setChannel() function failed", segment.getChannel(), 50);
ensure("LLSegment isOnChannel() function failed", (true == segment.isOnChannel(50)));
}
template<> template<>
void buffer_object_t::test<3>()
{
S32 channel = 30;
const char str[] = "SecondLife";
S32 len = sizeof(str);
LLSegment segment(channel, (U8*)str, len);
ensure("LLSegment get functions failed", (30 == segment.getChannel() && len == segment.size() && (U8*)str == segment.data()));
ensure_memory_matches("LLSegment::data() failed", segment.data(), segment.size(), (U8*)str, len);
ensure("LLSegment isOnChannel() function failed", (true == segment.isOnChannel(channel)));
}
template<> template<>
void buffer_object_t::test<4>()
{
S32 channel = 50;
S32 bigSize = 16384*2;
char str[] = "SecondLife";
S32 smallSize = sizeof(str);
LLSegment segment;
LLHeapBuffer buf; // use default size of DEFAULT_HEAP_BUFFER_SIZE = 16384
S32 requestSize;
requestSize = 16384-1;
ensure("1. LLHeapBuffer createSegment failed", (true == buf.createSegment(channel, requestSize, segment)) && segment.size() == requestSize);
// second request for remainign 1 byte
requestSize = 1;
ensure("2. LLHeapBuffer createSegment failed", (true == buf.createSegment(channel, requestSize, segment)) && segment.size() == requestSize);
// it should fail now.
requestSize = 1;
ensure("3. LLHeapBuffer createSegment failed", (false == buf.createSegment(channel, requestSize, segment)));
LLHeapBuffer buf1(bigSize);
// requst for more than default size but less than total sizeit should fail now.
requestSize = 16384 + 1;
ensure("4. LLHeapBuffer createSegment failed", (true == buf1.createSegment(channel, requestSize, segment)) && segment.size() == requestSize);
LLHeapBuffer buf2((U8*) str, smallSize);
requestSize = smallSize;
ensure("5. LLHeapBuffer createSegment failed", (true == buf2.createSegment(channel, requestSize, segment)) && segment.size() == requestSize && memcmp(segment.data(), (U8*) str, requestSize) == 0);
requestSize = smallSize+1;
ensure("6. LLHeapBuffer createSegment failed", (false == buf2.createSegment(channel, requestSize, segment)));
}
//makeChannelConsumer()
template<> template<>
void buffer_object_t::test<5>()
{
LLChannelDescriptors inchannelDescriptors(20);
LLChannelDescriptors outchannelDescriptors = LLBufferArray::makeChannelConsumer(inchannelDescriptors);
ensure("LLBufferArray::makeChannelConsumer() function Failed", (21 == outchannelDescriptors.in()));
}
template<> template<>
void buffer_object_t::test<6>()
{
LLBufferArray bufferArray;
const char array[] = "SecondLife";
S32 len = static_cast<S32>(strlen(array));
LLChannelDescriptors channelDescriptors = bufferArray.nextChannel();
bufferArray.append(channelDescriptors.in(), (U8*)array, len);
S32 count = bufferArray.countAfter(channelDescriptors.in(), NULL);
ensure_equals("Appended size is:", count, len);
}
//append() and prepend()
template<> template<>
void buffer_object_t::test<7>()
{
LLBufferArray bufferArray;
const char array[] = "SecondLife";
S32 len = static_cast<S32>(strlen(array));
const char array1[] = "LindenLabs";
S32 len1 = static_cast<S32>(strlen(array1));
std::string str(array1);
str.append(array);
LLChannelDescriptors channelDescriptors = bufferArray.nextChannel();
bufferArray.append(channelDescriptors.in(), (U8*)array, len);
bufferArray.prepend(channelDescriptors.in(), (U8*)array1, len1);
char buf[100];
S32 len2 = 20;
bufferArray.readAfter(channelDescriptors.in(), NULL, (U8*)buf, len2);
ensure_equals("readAfter length failed", len2, 20);
buf[len2] = '\0';
ensure_equals("readAfter/prepend/append failed", buf, str);
}
//append()
template<> template<>
void buffer_object_t::test<8>()
{
LLBufferArray bufferArray;
const char array[] = "SecondLife";
S32 len = static_cast<S32>(strlen(array));
const char array1[] = "LindenLabs";
S32 len1 = static_cast<S32>(strlen(array1));
std::string str(array);
str.append(array1);
LLChannelDescriptors channelDescriptors = bufferArray.nextChannel();
bufferArray.append(channelDescriptors.in(), (U8*)array, len);
bufferArray.append(channelDescriptors.in(), (U8*)array1, len1);
char buf[100];
S32 len2 = 20;
bufferArray.readAfter(channelDescriptors.in(), NULL, (U8*)buf, len2);
ensure_equals("readAfter length failed", len2, 20);
buf[len2] = '\0';
ensure_equals("readAfter/append/append failed", buf, str);
}
template<> template<>
void buffer_object_t::test<9>()
{
LLBufferArray bufferArray;
const char array[] = "SecondLife";
S32 len = static_cast<S32>(strlen(array)) + 1;
std::string str(array);
LLChannelDescriptors channelDescriptors = bufferArray.nextChannel();
bufferArray.append(channelDescriptors.in(), (U8*)array, len);
LLBufferArray bufferArray1;
ensure("Contents are not copied and the source buffer is not empty", (1 == bufferArray1.takeContents(bufferArray)));
char buf[100];
S32 len2 = len;
bufferArray1.readAfter(channelDescriptors.in(), NULL, (U8*)buf, len2);
ensure_equals("takeContents failed to copy", buf, str);
}
//seek()
template<> template<>
void buffer_object_t::test<10>()
{
const char array[] = "SecondLife is a Virtual World";
S32 len = static_cast<S32>(strlen(array));
LLBufferArray bufferArray;
bufferArray.append(0, (U8*)array, len);
char buf[255];
S32 len1 = 16;
U8* last = bufferArray.readAfter(0, 0, (U8*)buf, len1);
buf[len1] = '\0';
last = bufferArray.seek(0, last, -2);
len1 = 15;
last = bufferArray.readAfter(0, last, (U8*)buf, len1);
buf[len1] = '\0';
std::string str(buf);
ensure_equals("Seek does'nt worked", str, std::string("a Virtual World"));
}
template<> template<>
void buffer_object_t::test<11>()
{
const char array[] = "SecondLife is a Virtual World";
S32 len = static_cast<S32>(strlen(array));
LLBufferArray bufferArray;
bufferArray.append(0, (U8*)array, len);
char buf[255];
S32 len1 = 10;
U8* last = bufferArray.readAfter(0, 0, (U8*)buf, len1);
bufferArray.splitAfter(last);
LLBufferArray::segment_iterator_t iterator = bufferArray.beginSegment();
++iterator;
std::string str(((char*)(*iterator).data()), (*iterator).size());
ensure_equals("Strings are not equal;splitAfter() operation failed", str, std::string(" is a Virtual World"));
}
//makeSegment()->eraseSegment()
template<> template<>
void buffer_object_t::test<12>()
{
LLBufferArray bufferArray;
LLChannelDescriptors channelDescriptors;
LLBufferArray::segment_iterator_t it;
S32 length = 1000;
it = bufferArray.makeSegment(channelDescriptors.out(), length);
ensure("makeSegment() function failed", (it != bufferArray.endSegment()));
ensure("eraseSegment() function failed", bufferArray.eraseSegment(it));
ensure("eraseSegment() begin/end should now be same", bufferArray.beginSegment() == bufferArray.endSegment());
}
// constructSegmentAfter()
template<> template<>
void buffer_object_t::test<13>()
{
LLBufferArray bufferArray;
LLBufferArray::segment_iterator_t it;
LLSegment segment;
LLBufferArray::segment_iterator_t end = bufferArray.endSegment();
it = bufferArray.constructSegmentAfter(NULL, segment);
ensure("constructSegmentAfter() function failed", (it == end));
}
}
+570
View File
@@ -0,0 +1,570 @@
/**
* @file lldatapacker_tut.cpp
* @author Adroit
* @date 2007-02
* @brief LLDataPacker test cases.
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include <tut/tut.hpp>
#include "lltut.h"
#include "linden_common.h"
#include "lldatapacker.h"
#include "v4color.h"
#include "v4coloru.h"
#include "v2math.h"
#include "v3math.h"
#include "v4math.h"
#include "llsdserialize.h"
#define TEST_FILE_NAME "datapacker_test.txt"
namespace tut
{
struct datapacker_test
{
};
typedef test_group<datapacker_test> datapacker_test_t;
typedef datapacker_test_t::object datapacker_test_object_t;
tut::datapacker_test_t tut_datapacker_test("datapacker_test");
//*********LLDataPackerBinaryBuffer
template<> template<>
void datapacker_test_object_t::test<1>()
{
U8 packbuf[128];
F32 f_val1 = 44.44f, f_unpkval1;
F32 f_val2 = 12344.443232f, f_unpkval2;
F32 f_val3 = 44.4456789f, f_unpkval3;
LLDataPackerBinaryBuffer lldp(packbuf,128);
lldp.packFixed( f_val1, "linden_lab", FALSE, 8, 8);
lldp.packFixed( f_val2, "linden_lab", FALSE, 14, 16);
lldp.packFixed( f_val3, "linden_lab", FALSE, 8, 23);
LLDataPackerBinaryBuffer lldp1(packbuf, lldp.getCurrentSize());
lldp1.unpackFixed(f_unpkval1, "linden_lab", FALSE, 8, 8);
lldp1.unpackFixed(f_unpkval2, "linden_lab", FALSE, 14, 16);
lldp1.unpackFixed(f_unpkval3, "linden_lab", FALSE, 8, 23);
ensure_approximately_equals("LLDataPackerBinaryBuffer::packFixed 8 failed", f_val1, f_unpkval1, 8);
ensure_approximately_equals("LLDataPackerBinaryBuffer::packFixed 16 failed", f_val2, f_unpkval2, 16);
ensure_approximately_equals("LLDataPackerBinaryBuffer::packFixed 23 failed", f_val3, f_unpkval3, 31);
}
template<> template<>
void datapacker_test_object_t::test<2>()
{
U8 packbuf[1024];
char str[] = "SecondLife is virtual World\0";
char strBinary[] = "SecondLife is virtual World";
char strBinaryFixed[] = "Fixed Data";
S32 sizeBinaryFixed = sizeof(strBinaryFixed);
U8 valU8 = 'C';
U16 valU16 = 0xFFFF;
U32 valU32 = 0xFFFFFFFF;
S32 valS32 = -94967295;
F32 valF32 = 4354355.44f ;
LLColor4 llcol4(3.3f, 0, 4.4f, 5.5f);
LLColor4U llcol4u(3, 128, 24, 33);
LLVector2 llvec2(333.33f, 444.44f);
LLVector3 llvec3(333.33f, 444.44f, 555.55f);
LLVector4 llvec4(333.33f, 444.44f, 555.55f, 666.66f);
LLUUID uuid;
std::string unpkstr;
char unpkstrBinary[256];
char unpkstrBinaryFixed[256];
S32 unpksizeBinary;
U8 unpkvalU8;
U16 unpkvalU16;
U32 unpkvalU32;
S32 unpkvalS32;
F32 unpkvalF32;
LLColor4 unpkllcol4;
LLColor4U unpkllcol4u;
LLVector2 unpkllvec2;
LLVector3 unpkllvec3;
LLVector4 unpkllvec4;
LLUUID unpkuuid;
LLDataPackerBinaryBuffer lldp(packbuf,1024);
lldp.packString(str , "linden_lab_str");
lldp.packBinaryData((U8*)strBinary, sizeof(strBinary), "linden_lab_bd");
lldp.packBinaryDataFixed((U8*)strBinaryFixed, sizeBinaryFixed, "linden_lab_bdf");
lldp.packU8(valU8,"linden_lab_u8");
lldp.packU16(valU16,"linden_lab_u16");
lldp.packU32(valU32, "linden_lab_u32");
lldp.packS32(valS32, "linden_lab_s32");
lldp.packF32(valF32, "linden_lab_f32");
lldp.packColor4(llcol4, "linden_lab_col4");
lldp.packColor4U(llcol4u, "linden_lab_col4u");
lldp.packVector2(llvec2, "linden_lab_vec2");
lldp.packVector3(llvec3, "linden_lab_vec3");
lldp.packVector4(llvec4, "linden_lab_vec4");
uuid.generate();
lldp.packUUID(uuid, "linden_lab_uuid");
S32 cur_size = lldp.getCurrentSize();
LLDataPackerBinaryBuffer lldp1(packbuf, cur_size);
lldp1.unpackString(unpkstr , "linden_lab_str");
lldp1.unpackBinaryData((U8*)unpkstrBinary, unpksizeBinary, "linden_lab_bd");
lldp1.unpackBinaryDataFixed((U8*)unpkstrBinaryFixed, sizeBinaryFixed, "linden_lab_bdf");
lldp1.unpackU8(unpkvalU8,"linden_lab_u8");
lldp1.unpackU16(unpkvalU16,"linden_lab_u16");
lldp1.unpackU32(unpkvalU32, "linden_lab_u32");
lldp1.unpackS32(unpkvalS32, "linden_lab_s32");
lldp1.unpackF32(unpkvalF32, "linden_lab_f32");
lldp1.unpackColor4(unpkllcol4, "linden_lab_col4");
lldp1.unpackColor4U(unpkllcol4u, "linden_lab_col4u");
lldp1.unpackVector2(unpkllvec2, "linden_lab_vec2");
lldp1.unpackVector3(unpkllvec3, "linden_lab_vec3");
lldp1.unpackVector4(unpkllvec4, "linden_lab_vec4");
lldp1.unpackUUID(unpkuuid, "linden_lab_uuid");
ensure("LLDataPackerBinaryBuffer::packString failed", strcmp(str, unpkstr.c_str()) == 0);
ensure("LLDataPackerBinaryBuffer::packBinaryData failed", strcmp(strBinary, unpkstrBinary) == 0);
ensure("LLDataPackerBinaryBuffer::packBinaryDataFixed failed", strcmp(strBinaryFixed, unpkstrBinaryFixed) == 0);
ensure_equals("LLDataPackerBinaryBuffer::packU8 failed", valU8, unpkvalU8);
ensure_equals("LLDataPackerBinaryBuffer::packU16 failed", valU16, unpkvalU16);
ensure_equals("LLDataPackerBinaryBuffer::packU32 failed", valU32, unpkvalU32);
ensure_equals("LLDataPackerBinaryBuffer::packS32 failed", valS32, unpkvalS32);
ensure("LLDataPackerBinaryBuffer::packF32 failed", is_approx_equal(valF32, unpkvalF32));
ensure_equals("LLDataPackerBinaryBuffer::packColor4 failed", llcol4, unpkllcol4);
ensure_equals("LLDataPackerBinaryBuffer::packColor4U failed", llcol4u, unpkllcol4u);
ensure_equals("LLDataPackerBinaryBuffer::packVector2 failed", llvec2, unpkllvec2);
ensure_equals("LLDataPackerBinaryBuffer::packVector3 failed", llvec3, unpkllvec3);
ensure_equals("LLDataPackerBinaryBuffer::packVector4 failed", llvec4, unpkllvec4);
ensure_equals("LLDataPackerBinaryBuffer::packUUID failed", uuid, unpkuuid);
}
template<> template<>
void datapacker_test_object_t::test<3>()
{
U8 packbuf[128];
char str[] = "SecondLife is virtual World";
S32 strSize = sizeof(str); // include '\0'
LLDataPackerBinaryBuffer lldp(packbuf, 128);
lldp.packString(str , "linden_lab");
ensure("LLDataPackerBinaryBuffer: current size is wrong", strSize == lldp.getCurrentSize());
ensure("LLDataPackerBinaryBuffer: buffer size is wrong", 128 == lldp.getBufferSize());
lldp.reset();
ensure("LLDataPackerBinaryBuffer::reset failed",0 == lldp.getCurrentSize());
}
template<> template<>
void datapacker_test_object_t::test<4>()
{
U8* packbuf = new U8[128];
char str[] = "SecondLife is virtual World";
LLDataPackerBinaryBuffer lldp(packbuf, 128);
lldp.packString(str , "linden_lab");
lldp.freeBuffer();
ensure("LLDataPackerBinaryBuffer.freeBuffer failed" , 0 == lldp.getBufferSize());
}
template<> template<>
void datapacker_test_object_t::test<5>()
{
U8 buf[] = "SecondLife is virtual World";
S32 size = sizeof(buf);
LLDataPackerBinaryBuffer lldp(buf, size);
U8 new_buf[] = "Its Amazing";
size = sizeof(new_buf);
lldp.assignBuffer(new_buf, size);
ensure("LLDataPackerBinaryBuffer::assignBuffer failed" , ((lldp.getBufferSize() == size) && (0 == lldp.getCurrentSize()))) ;
}
template<> template<>
void datapacker_test_object_t::test<6>()
{
U8 packbuf[128];
char str[] = "SecondLife is virtual World";
LLDataPackerBinaryBuffer lldp(packbuf, 128);
lldp.packString(str , "linden_lab");
U8 new_buffer[128];
std::string unpkbuf;
LLDataPackerBinaryBuffer lldp1(new_buffer,128);
lldp1 = lldp;
lldp1.unpackString(unpkbuf, "linden_lab");
ensure("1. LLDataPackerBinaryBuffer::operator= failed" , lldp1.getBufferSize() == lldp.getBufferSize());
ensure_equals("2.LLDataPackerBinaryBuffer::operator= failed", str,unpkbuf);
}
//*********LLDataPackerAsciiBuffer
template<> template<>
void datapacker_test_object_t::test<7>()
{
char packbuf[128];
F32 f_val = 44.44f, f_unpkval;
LLDataPackerAsciiBuffer lldp(packbuf,128);
lldp.packFixed( f_val, "linden_lab", FALSE, 8, 8);
LLDataPackerAsciiBuffer lldp1(packbuf, lldp.getCurrentSize());
lldp1.unpackFixed(f_unpkval, "linden_lab", FALSE, 8, 8);
ensure_approximately_equals("LLDataPackerAsciiBuffer::packFixed failed", f_val, f_unpkval, 8);
}
template<> template<>
void datapacker_test_object_t::test<8>()
{
char packbuf[1024];
char str[] = "SecondLife is virtual World\0";
char strBinary[] = "SecondLife is virtual World";
char strBinaryFixed[] = "Fixed Data";
S32 sizeBinaryFixed = sizeof(strBinaryFixed);
U8 valU8 = 'C';
U16 valU16 = 0xFFFF;
U32 valU32 = 0xFFFFFFFF;
S32 valS32 = -94967295;
F32 valF32 = 4354355.44f ;
LLColor4 llcol4(3.3f, 0, 4.4f, 5.5f);
LLColor4U llcol4u(3, 128, 24, 33);
LLVector2 llvec2(333.33f, 444.44f);
LLVector3 llvec3(333.33f, 444.44f, 555.55f);
LLVector4 llvec4(4354355.44f, 444.44f, 555.55f, 666.66f);
LLUUID uuid;
std::string unpkstr;
char unpkstrBinary[256];
char unpkstrBinaryFixed[256];
S32 unpksizeBinary;
U8 unpkvalU8;
U16 unpkvalU16;
U32 unpkvalU32;
S32 unpkvalS32;
F32 unpkvalF32;
LLColor4 unpkllcol4;
LLColor4U unpkllcol4u;
LLVector2 unpkllvec2;
LLVector3 unpkllvec3;
LLVector4 unpkllvec4;
LLUUID unpkuuid;
LLDataPackerAsciiBuffer lldp(packbuf,1024);
lldp.packString(str , "linden_lab_str");
lldp.packBinaryData((U8*)strBinary, sizeof(strBinary), "linden_lab_bd");
lldp.packBinaryDataFixed((U8*)strBinaryFixed, sizeBinaryFixed, "linden_lab_bdf");
lldp.packU8(valU8,"linden_lab_u8");
lldp.packU16(valU16,"linden_lab_u16");
lldp.packU32(valU32, "linden_lab_u32");
lldp.packS32(valS32, "linden_lab_s32");
lldp.packF32(valF32, "linden_lab_f32");
lldp.packColor4(llcol4, "linden_lab_col4");
lldp.packColor4U(llcol4u, "linden_lab_col4u");
lldp.packVector2(llvec2, "linden_lab_vec2");
lldp.packVector3(llvec3, "linden_lab_vec3");
lldp.packVector4(llvec4, "linden_lab_vec4");
uuid.generate();
lldp.packUUID(uuid, "linden_lab_uuid");
S32 cur_size = lldp.getCurrentSize();
LLDataPackerAsciiBuffer lldp1(packbuf, cur_size);
lldp1.unpackString(unpkstr , "linden_lab_str");
lldp1.unpackBinaryData((U8*)unpkstrBinary, unpksizeBinary, "linden_lab_bd");
lldp1.unpackBinaryDataFixed((U8*)unpkstrBinaryFixed, sizeBinaryFixed, "linden_lab_bdf");
lldp1.unpackU8(unpkvalU8,"linden_lab_u8");
lldp1.unpackU16(unpkvalU16,"linden_lab_u16");
lldp1.unpackU32(unpkvalU32, "linden_lab_u32");
lldp1.unpackS32(unpkvalS32, "linden_lab_s32");
lldp1.unpackF32(unpkvalF32, "linden_lab_f32");
lldp1.unpackColor4(unpkllcol4, "linden_lab_col4");
lldp1.unpackColor4U(unpkllcol4u, "linden_lab_col4u");
lldp1.unpackVector2(unpkllvec2, "linden_lab_vec2");
lldp1.unpackVector3(unpkllvec3, "linden_lab_vec3");
lldp1.unpackVector4(unpkllvec4, "linden_lab_vec4");
lldp1.unpackUUID(unpkuuid, "linden_lab_uuid");
ensure("LLDataPackerAsciiBuffer::packString failed", strcmp(str, unpkstr.c_str()) == 0);
ensure("LLDataPackerAsciiBuffer::packBinaryData failed", strcmp(strBinary, unpkstrBinary) == 0);
ensure("LLDataPackerAsciiBuffer::packBinaryDataFixed failed", strcmp(strBinaryFixed, unpkstrBinaryFixed) == 0);
ensure_equals("LLDataPackerAsciiBuffer::packU8 failed", valU8, unpkvalU8);
ensure_equals("LLDataPackerAsciiBuffer::packU16 failed", valU16, unpkvalU16);
ensure_equals("LLDataPackerAsciiBuffer::packU32 failed", valU32, unpkvalU32);
ensure_equals("LLDataPackerAsciiBuffer::packS32 failed", valS32, unpkvalS32);
ensure("LLDataPackerAsciiBuffer::packF32 failed", is_approx_equal(valF32, unpkvalF32));
ensure_equals("LLDataPackerAsciiBuffer::packColor4 failed", llcol4, unpkllcol4);
ensure_equals("LLDataPackerAsciiBuffer::packColor4U failed", llcol4u, unpkllcol4u);
ensure_equals("LLDataPackerAsciiBuffer::packVector2 failed", llvec2, unpkllvec2);
ensure_equals("LLDataPackerAsciiBuffer::packVector3 failed", llvec3, unpkllvec3);
ensure_equals("LLDataPackerAsciiBuffer::packVector4 failed", llvec4, unpkllvec4);
ensure_equals("LLDataPackerAsciiBuffer::packUUID failed", uuid, unpkuuid);
}
template<> template<>
void datapacker_test_object_t::test<9>()
{
char* packbuf = new char[128];
char str[] = "SecondLife is virtual World";
LLDataPackerAsciiBuffer lldp(packbuf, 128);
lldp.packString(str , "linden_lab");
lldp.freeBuffer();
ensure("LLDataPackerAsciiBuffer::freeBuffer failed" , 0 == lldp.getBufferSize());
}
template<> template<>
void datapacker_test_object_t::test<10>()
{
char buf[] = "SecondLife is virtual World";
S32 size = sizeof(buf);
LLDataPackerAsciiBuffer lldp(buf, size);
char new_buf[] = "Its Amazing";
size = sizeof(new_buf);
lldp.assignBuffer(new_buf, size);
ensure("LLDataPackerAsciiBuffer::assignBuffer failed" , ((lldp.getBufferSize() == size) && (1 == lldp.getCurrentSize()))) ;
}
//*********LLDataPackerAsciiFile
template<> template<>
void datapacker_test_object_t::test<11>()
{
F32 f_val = 44.44f, f_unpkval;
LLFILE* fp = LLFile::fopen(TEST_FILE_NAME, "w+");
if(!fp)
{
LL_ERRS() << "File couldnt be open" << LL_ENDL;
return;
}
LLDataPackerAsciiFile lldp(fp,2);
lldp.packFixed( f_val, "linden_lab", FALSE, 8, 8);
fflush(fp);
fseek(fp,0,SEEK_SET);
LLDataPackerAsciiFile lldp1(fp,2);
lldp1.unpackFixed(f_unpkval, "linden_lab", FALSE, 8, 8);
fclose(fp);
ensure_approximately_equals("LLDataPackerAsciiFile::packFixed failed", f_val, f_unpkval, 8);
}
template<> template<>
void datapacker_test_object_t::test<12>()
{
char str[] = "SecondLife is virtual World\0";
char strBinary[] = "SecondLife is virtual World";
char strBinaryFixed[] = "Fixed Data";
S32 sizeBinaryFixed = sizeof(strBinaryFixed);
U8 valU8 = 'C';
U16 valU16 = 0xFFFF;
U32 valU32 = 0xFFFFFFFF;
S32 valS32 = -94967295;
F32 valF32 = 4354355.44f ;
LLColor4 llcol4(3.3f, 0, 4.4f, 5.5f);
LLColor4U llcol4u(3, 128, 24, 33);
LLVector2 llvec2(333.33f, 444.44f);
LLVector3 llvec3(333.33f, 444.44f, 555.55f);
LLVector4 llvec4(333.33f, 444.44f, 555.55f, 666.66f);
LLUUID uuid;
std::string unpkstr;
char unpkstrBinary[256];
char unpkstrBinaryFixed[256];
S32 unpksizeBinary;
U8 unpkvalU8;
U16 unpkvalU16;
U32 unpkvalU32;
S32 unpkvalS32;
F32 unpkvalF32;
LLColor4 unpkllcol4;
LLColor4U unpkllcol4u;
LLVector2 unpkllvec2;
LLVector3 unpkllvec3;
LLVector4 unpkllvec4;
LLUUID unpkuuid;
LLFILE* fp = LLFile::fopen(TEST_FILE_NAME,"w+");
if(!fp)
{
LL_ERRS() << "File couldnt be open" << LL_ENDL;
return;
}
LLDataPackerAsciiFile lldp(fp,2);
lldp.packString(str , "linden_lab_str");
lldp.packBinaryData((U8*)strBinary, sizeof(strBinary), "linden_lab_bd");
lldp.packBinaryDataFixed((U8*)strBinaryFixed, sizeBinaryFixed, "linden_lab_bdf");
lldp.packU8(valU8,"linden_lab_u8");
lldp.packU16(valU16,"linden_lab_u16");
lldp.packU32(valU32, "linden_lab_u32");
lldp.packS32(valS32, "linden_lab_s32");
lldp.packF32(valF32, "linden_lab_f32");
lldp.packColor4(llcol4, "linden_lab_col4");
lldp.packColor4U(llcol4u, "linden_lab_col4u");
lldp.packVector2(llvec2, "linden_lab_vec2");
lldp.packVector3(llvec3, "linden_lab_vec3");
lldp.packVector4(llvec4, "linden_lab_vec4");
uuid.generate();
lldp.packUUID(uuid, "linden_lab_uuid");
fflush(fp);
fseek(fp,0,SEEK_SET);
LLDataPackerAsciiFile lldp1(fp,2);
lldp1.unpackString(unpkstr , "linden_lab_str");
lldp1.unpackBinaryData((U8*)unpkstrBinary, unpksizeBinary, "linden_lab_bd");
lldp1.unpackBinaryDataFixed((U8*)unpkstrBinaryFixed, sizeBinaryFixed, "linden_lab_bdf");
lldp1.unpackU8(unpkvalU8,"linden_lab_u8");
lldp1.unpackU16(unpkvalU16,"linden_lab_u16");
lldp1.unpackU32(unpkvalU32, "linden_lab_u32");
lldp1.unpackS32(unpkvalS32, "linden_lab_s32");
lldp1.unpackF32(unpkvalF32, "linden_lab_f32");
lldp1.unpackColor4(unpkllcol4, "linden_lab_col4");
lldp1.unpackColor4U(unpkllcol4u, "linden_lab_col4u");
lldp1.unpackVector2(unpkllvec2, "linden_lab_vec2");
lldp1.unpackVector3(unpkllvec3, "linden_lab_vec3");
lldp1.unpackVector4(unpkllvec4, "linden_lab_vec4");
lldp1.unpackUUID(unpkuuid, "linden_lab_uuid");
fclose(fp);
ensure("LLDataPackerAsciiFile::packString failed", strcmp(str, unpkstr.c_str()) == 0);
ensure("LLDataPackerAsciiFile::packBinaryData failed", strcmp(strBinary, unpkstrBinary) == 0);
ensure("LLDataPackerAsciiFile::packBinaryDataFixed failed", strcmp(strBinaryFixed, unpkstrBinaryFixed) == 0);
ensure_equals("LLDataPackerAsciiFile::packU8 failed", valU8, unpkvalU8);
ensure_equals("LLDataPackerAsciiFile::packU16 failed", valU16, unpkvalU16);
ensure_equals("LLDataPackerAsciiFile::packU32 failed", valU32, unpkvalU32);
ensure_equals("LLDataPackerAsciiFile::packS32 failed", valS32, unpkvalS32);
ensure("LLDataPackerAsciiFile::packF32 failed", is_approx_equal(valF32, unpkvalF32));
ensure_equals("LLDataPackerAsciiFile::packColor4 failed", llcol4, unpkllcol4);
ensure_equals("LLDataPackerAsciiFile::packColor4U failed", llcol4u, unpkllcol4u);
ensure_equals("LLDataPackerAsciiFile::packVector2 failed", llvec2, unpkllvec2);
ensure_equals("LLDataPackerAsciiFile::packVector3 failed", llvec3, unpkllvec3);
ensure_equals("LLDataPackerAsciiFile::packVector4 failed", llvec4, unpkllvec4);
ensure_equals("LLDataPackerAsciiFile::packUUID failed", uuid, unpkuuid);
}
template<> template<>
void datapacker_test_object_t::test<13>()
{
F32 f_val = 44.44f, f_unpkval;
std::ostringstream ostr;
LLDataPackerAsciiFile lldp(ostr,2);
lldp.packFixed( f_val, "linden_lab", FALSE, 8, 8);
std::istringstream istr(ostr.str());
LLDataPackerAsciiFile lldp1(istr,2);
lldp1.unpackFixed(f_unpkval, "linden_lab", FALSE, 8, 8);
ensure_approximately_equals("LLDataPackerAsciiFile::packFixed (iostring) failed", f_val, f_unpkval, 8);
}
template<> template<>
void datapacker_test_object_t::test<14>()
{
char str[] = "SecondLife is virtual World\0";
char strBinary[] = "SecondLife is virtual World";
char strBinaryFixed[] = "Fixed Data";
S32 sizeBinaryFixed = sizeof(strBinaryFixed);
U8 valU8 = 'C';
U16 valU16 = 0xFFFF;
U32 valU32 = 0xFFFFFFFF;
S32 valS32 = -94967295;
F32 valF32 = 4354355.44f ;
LLColor4 llcol4(3.3f, 0, 4.4f, 5.5f);
LLColor4U llcol4u(3, 128, 24, 33);
LLVector2 llvec2(3333333.33f, 444.333344f);
LLVector3 llvec3(3323233.33f, 444.4324f, 555.553232f);
LLVector4 llvec4(333.33233f, 444.4323234f, 55323225.55f, 6323236.66f);
LLUUID uuid;
std::string unpkstr;
char unpkstrBinary[256];
char unpkstrBinaryFixed[256];
S32 unpksizeBinary;
U8 unpkvalU8;
U16 unpkvalU16;
U32 unpkvalU32;
S32 unpkvalS32;
F32 unpkvalF32;
LLColor4 unpkllcol4;
LLColor4U unpkllcol4u;
LLVector2 unpkllvec2;
LLVector3 unpkllvec3;
LLVector4 unpkllvec4;
LLUUID unpkuuid;
std::ostringstream ostr;
LLDataPackerAsciiFile lldp(ostr,2);
lldp.packString(str , "linden_lab_str");
lldp.packBinaryData((U8*)strBinary, sizeof(strBinary), "linden_lab_bd");
lldp.packBinaryDataFixed((U8*)strBinaryFixed, sizeBinaryFixed, "linden_lab_bdf");
lldp.packU8(valU8,"linden_lab_u8");
lldp.packU16(valU16,"linden_lab_u16");
lldp.packU32(valU32, "linden_lab_u32");
lldp.packS32(valS32, "linden_lab_s32");
lldp.packF32(valF32, "linden_lab_f32");
lldp.packColor4(llcol4, "linden_lab_col4");
lldp.packColor4U(llcol4u, "linden_lab_col4u");
lldp.packVector2(llvec2, "linden_lab_vec2");
lldp.packVector3(llvec3, "linden_lab_vec3");
lldp.packVector4(llvec4, "linden_lab_vec4");
uuid.generate();
lldp.packUUID(uuid, "linden_lab_uuid");
std::istringstream istr(ostr.str());
LLDataPackerAsciiFile lldp1(istr,2);
lldp1.unpackString(unpkstr , "linden_lab_str");
lldp1.unpackBinaryData((U8*)unpkstrBinary, unpksizeBinary, "linden_lab_bd");
lldp1.unpackBinaryDataFixed((U8*)unpkstrBinaryFixed, sizeBinaryFixed, "linden_lab_bdf");
lldp1.unpackU8(unpkvalU8,"linden_lab_u8");
lldp1.unpackU16(unpkvalU16,"linden_lab_u16");
lldp1.unpackU32(unpkvalU32, "linden_lab_u32");
lldp1.unpackS32(unpkvalS32, "linden_lab_s32");
lldp1.unpackF32(unpkvalF32, "linden_lab_f32");
lldp1.unpackColor4(unpkllcol4, "linden_lab_col4");
lldp1.unpackColor4U(unpkllcol4u, "linden_lab_col4u");
lldp1.unpackVector2(unpkllvec2, "linden_lab_vec2");
lldp1.unpackVector3(unpkllvec3, "linden_lab_vec3");
lldp1.unpackVector4(unpkllvec4, "linden_lab_vec4");
lldp1.unpackUUID(unpkuuid, "linden_lab_uuid");
ensure("LLDataPackerAsciiFile::packString (iostring) failed", strcmp(str, unpkstr.c_str()) == 0);
ensure("LLDataPackerAsciiFile::packBinaryData (iostring) failed", strcmp(strBinary, unpkstrBinary) == 0);
ensure("LLDataPackerAsciiFile::packBinaryDataFixed (iostring) failed", strcmp(strBinaryFixed, unpkstrBinaryFixed) == 0);
ensure_equals("LLDataPackerAsciiFile::packU8 (iostring) failed", valU8, unpkvalU8);
ensure_equals("LLDataPackerAsciiFile::packU16 (iostring) failed", valU16, unpkvalU16);
ensure_equals("LLDataPackerAsciiFile::packU32 (iostring) failed", valU32, unpkvalU32);
ensure_equals("LLDataPackerAsciiFile::packS32 (iostring) failed", valS32, unpkvalS32);
ensure("LLDataPackerAsciiFile::packF32 (iostring) failed", is_approx_equal(valF32, unpkvalF32));
ensure_equals("LLDataPackerAsciiFile::packColor4 (iostring) failed", llcol4, unpkllcol4);
ensure_equals("LLDataPackerAsciiFile::packColor4U (iostring) failed", llcol4u, unpkllcol4u);
ensure_equals("LLDataPackerAsciiFile::packVector2 (iostring) failed", llvec2, unpkllvec2);
ensure_equals("LLDataPackerAsciiFile::packVector3 (iostring) failed", llvec3, unpkllvec3);
ensure_equals("LLDataPackerAsciiFile::packVector4 (iostring) failed", llvec4, unpkllvec4);
ensure_equals("LLDataPackerAsciiFile::packUUID (iostring) failed", uuid, unpkuuid);
}
}
+240
View File
@@ -0,0 +1,240 @@
/**
* @file lldoubledispatch_tut.cpp
* @author Nat Goodspeed
* @date 2008-11-13
* @brief Test for lldoubledispatch.h
*
* This program tests the DoubleDispatch class, using a variation on the example
* from Scott Meyers' "More Effective C++", Item 31.
*
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
// Precompiled header
#include "linden_common.h"
// associated header
#include "lldoubledispatch.h"
// STL headers
// std headers
#include <iostream>
#include <memory>
#include <string>
#include <typeinfo>
// external library headers
// other Linden headers
#include "lltut.h"
/*---------------------------- Class hierarchy -----------------------------*/
// All objects are GameObjects.
class GameObject
{
public:
GameObject(const std::string& name): mName(name) {}
virtual ~GameObject() {}
virtual std::string stringize() { return std::string(typeid(*this).name()) + " " + mName; }
protected:
std::string mName;
};
// SpaceStation, Asteroid and SpaceShip are peer GameObjects.
struct SpaceStation: public GameObject
{
SpaceStation(const std::string& name): GameObject(name) {}
// Only a dummy SpaceStation is constructed without a name
SpaceStation(): GameObject("dummy") {}
};
struct Asteroid: public GameObject
{
Asteroid(const std::string& name): GameObject(name) {}
Asteroid(): GameObject("dummy") {}
};
struct SpaceShip: public GameObject
{
SpaceShip(const std::string& name): GameObject(name) {}
SpaceShip(): GameObject("dummy") {}
};
// SpaceShip is specialized further into CommercialShip and MilitaryShip.
struct CommercialShip: public SpaceShip
{
CommercialShip(const std::string& name): SpaceShip(name) {}
CommercialShip(): SpaceShip("dummy") {}
};
struct MilitaryShip: public SpaceShip
{
MilitaryShip(const std::string& name): SpaceShip(name) {}
MilitaryShip(): SpaceShip("dummy") {}
};
/*-------------------------- Collision functions ---------------------------*/
// This mechanism permits us to overcome a limitation of Meyers' approach: we
// can declare the parameter types exactly as we want, rather than having to
// make them all GameObject& parameters.
std::string shipAsteroid(SpaceShip& ship, Asteroid& rock)
{
// std::cout << rock.stringize() << " has pulverized " << ship.stringize() << std::endl;
return "shipAsteroid";
}
std::string militaryShipAsteroid(MilitaryShip& ship, Asteroid& rock)
{
// std::cout << rock.stringize() << " has severely damaged " << ship.stringize() << std::endl;
return "militaryShipAsteroid";
}
std::string shipStation(SpaceShip& ship, SpaceStation& dock)
{
// std::cout << ship.stringize() << " has docked at " << dock.stringize() << std::endl;
return "shipStation";
}
std::string asteroidStation(Asteroid& rock, SpaceStation& dock)
{
// std::cout << rock.stringize() << " has damaged " << dock.stringize() << std::endl;
return "asteroidStation";
}
/*------------------------------- Test code --------------------------------*/
namespace tut
{
struct dispatch_data
{
dispatch_data():
home(new SpaceStation("Terra Station")),
obstacle(new Asteroid("Ganymede")),
tug(new CommercialShip("Pilotfish")),
patrol(new MilitaryShip("Enterprise"))
{}
// Instantiate and populate the DoubleDispatch object.
typedef LLDoubleDispatch<std::string, GameObject> DD;
DD dispatcher;
// Instantiate a few GameObjects. Make sure we refer to them
// polymorphically, and don't let them leak.
std::unique_ptr<GameObject> home;
std::unique_ptr<GameObject> obstacle;
std::unique_ptr<GameObject> tug;
std::unique_ptr<GameObject> patrol;
// prototype objects
Asteroid dummyAsteroid;
SpaceShip dummyShip;
MilitaryShip dummyMilitary;
CommercialShip dummyCommercial;
SpaceStation dummyStation;
};
typedef test_group<dispatch_data> dispatch_group;
typedef dispatch_group::object dispatch_object;
tut::dispatch_group ddgr("double dispatch");
template<> template<>
void dispatch_object::test<1>()
{
// Describe param types using explicit DD::Type objects
// (order-sensitive add() variant)
dispatcher.add(DD::Type<SpaceShip>(), DD::Type<Asteroid>(), shipAsteroid, true);
// naive adding, won't work
dispatcher.add(DD::Type<MilitaryShip>(), DD::Type<Asteroid>(), militaryShipAsteroid, true);
dispatcher.add(DD::Type<SpaceShip>(), DD::Type<SpaceStation>(), shipStation, true);
dispatcher.add(DD::Type<Asteroid>(), DD::Type<SpaceStation>(), asteroidStation, true);
// Try colliding them.
ensure_equals(dispatcher(*home, *tug), // reverse params, SpaceShip subclass
"shipStation");
ensure_equals(dispatcher(*patrol, *home), // forward params, SpaceShip subclass
"shipStation");
ensure_equals(dispatcher(*obstacle, *home), // forward params
"asteroidStation");
ensure_equals(dispatcher(*home, *obstacle), // reverse params
"asteroidStation");
ensure_equals(dispatcher(*tug, *obstacle), // forward params, SpaceShip subclass
"shipAsteroid");
ensure_equals(dispatcher(*obstacle, *patrol), // reverse params, SpaceShip subclass
// won't use militaryShipAsteroid() because it was added
// in wrong order
"shipAsteroid");
}
template<> template<>
void dispatch_object::test<2>()
{
// Describe param types using explicit DD::Type objects
// (order-sensitive add() variant)
// adding in correct order
dispatcher.add(DD::Type<MilitaryShip>(), DD::Type<Asteroid>(), militaryShipAsteroid, true);
dispatcher.add(DD::Type<SpaceShip>(), DD::Type<Asteroid>(), shipAsteroid, true);
dispatcher.add(DD::Type<SpaceShip>(), DD::Type<SpaceStation>(), shipStation, true);
dispatcher.add(DD::Type<Asteroid>(), DD::Type<SpaceStation>(), asteroidStation, true);
ensure_equals(dispatcher(*patrol, *obstacle), "militaryShipAsteroid");
ensure_equals(dispatcher(*tug, *obstacle), "shipAsteroid");
}
template<> template<>
void dispatch_object::test<3>()
{
// Describe param types with actual prototype instances
// (order-insensitive add() variant)
dispatcher.add(dummyMilitary, dummyAsteroid, militaryShipAsteroid);
dispatcher.add(dummyShip, dummyAsteroid, shipAsteroid);
dispatcher.add(dummyShip, dummyStation, shipStation);
dispatcher.add(dummyAsteroid, dummyStation, asteroidStation);
ensure_equals(dispatcher(*patrol, *obstacle), "militaryShipAsteroid");
ensure_equals(dispatcher(*tug, *obstacle), "shipAsteroid");
ensure_equals(dispatcher(*obstacle, *patrol), "");
}
template<> template<>
void dispatch_object::test<4>()
{
// Describe param types with actual prototype instances
// (order-insensitive add() variant)
dispatcher.add(dummyShip, dummyAsteroid, shipAsteroid);
// Even if we add the militaryShipAsteroid in the wrong order, it
// should still work.
dispatcher.add(dummyMilitary, dummyAsteroid, militaryShipAsteroid);
dispatcher.add(dummyShip, dummyStation, shipStation);
dispatcher.add(dummyAsteroid, dummyStation, asteroidStation);
ensure_equals(dispatcher(*patrol, *obstacle), "militaryShipAsteroid");
ensure_equals(dispatcher(*tug, *obstacle), "shipAsteroid");
}
template<> template<>
void dispatch_object::test<5>()
{
dispatcher.add<SpaceShip, Asteroid>(shipAsteroid);
dispatcher.add<MilitaryShip, Asteroid>(militaryShipAsteroid);
dispatcher.add<SpaceShip, SpaceStation>(shipStation);
dispatcher.add<Asteroid, SpaceStation>(asteroidStation);
ensure_equals(dispatcher(*patrol, *obstacle), "militaryShipAsteroid");
ensure_equals(dispatcher(*tug, *obstacle), "shipAsteroid");
}
} // namespace tut
+511
View File
@@ -0,0 +1,511 @@
/**
* @file llevents_tut.cpp
* @author Nat Goodspeed
* @date 2008-09-12
* @brief Test of llevents.h
*
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#if LL_WINDOWS
#pragma warning (disable : 4675) // "resolved by ADL" -- just as I want!
#endif
// Precompiled header
#include "linden_common.h"
// associated header
// UGLY HACK! We want to verify state internal to the classes without
// providing public accessors.
#define testable public
#include "llevents.h"
#undef testable
// STL headers
// std headers
#include <iostream>
#include <typeinfo>
// external library headers
#include <boost/bind.hpp>
#include <boost/assign/list_of.hpp>
// other Linden headers
#include "tests/listener.h" // must PRECEDE lltut.h
#include "lltut.h"
#include "catch_and_store_what_in.h"
#include "stringize.h"
using boost::assign::list_of;
template<typename T>
T make(const T& value)
{
return value;
}
/*****************************************************************************
* tut test group
*****************************************************************************/
namespace tut
{
struct events_data
{
events_data() :
pumps(LLEventPumps::instance()),
listener0("first"),
listener1("second")
{
}
LLEventPumps& pumps;
Listener listener0;
Listener listener1;
void check_listener(const std::string& desc, const Listener& listener, LLSD::Integer got)
{
ensure_equals(STRINGIZE(listener << ' ' << desc),
listener.getLastEvent().asInteger(), got);
}
};
typedef test_group<events_data> events_group;
typedef events_group::object events_object;
tut::events_group evgr("events");
template<> template<>
void events_object::test<1>()
{
set_test_name("basic operations");
// Having to modify this to track the statically-
// constructed pumps in other TUT modules in this giant monolithic test
// executable isn't such a hot idea.
// ensure_equals("initial pump", pumps.mPumpMap.size(), 1);
size_t initial_pumps(pumps.mPumpMap.size());
LLEventPump& per_frame(pumps.obtain("per-frame"));
ensure_equals("first explicit pump", pumps.mPumpMap.size(), initial_pumps + 1);
// Verify that per_frame was instantiated as an LLEventStream.
ensure("LLEventStream leaf class", dynamic_cast<LLEventStream*> (&per_frame));
ensure("enabled", per_frame.enabled());
// Trivial test, but posting an event to an EventPump with no
// listeners should not blow up. The test is relevant because defining
// a boost::signal with a non-void return signature, using the default
// combiner, blows up if there are no listeners. This is because the
// default combiner is defined to return the value returned by the
// last listener, which is meaningless if there were no listeners.
per_frame.post(0);
LLBoundListener connection = listener0.listenTo(per_frame);
ensure("connected", connection.connected());
ensure("not blocked", !connection.blocked());
per_frame.post(1);
check_listener("received", listener0, 1);
{ // block the connection
LLEventPump::Blocker block(connection);
ensure("blocked", connection.blocked());
per_frame.post(2);
check_listener("not updated", listener0, 1);
} // unblock
ensure("unblocked", !connection.blocked());
per_frame.post(3);
check_listener("unblocked", listener0, 3);
LLBoundListener sameConnection = per_frame.getListener(listener0.getName());
ensure("still connected", sameConnection.connected());
ensure("still not blocked", !sameConnection.blocked());
{ // block it again
LLEventPump::Blocker block(sameConnection);
ensure("re-blocked", sameConnection.blocked());
per_frame.post(4);
check_listener("re-blocked", listener0, 3);
} // unblock
std::string threw = catch_what<LLEventPump::DupListenerName>(
[&per_frame, this](){
// NOTE: boost::bind() saves its arguments by VALUE! If you pass
// an object instance rather than a pointer, you'll end up binding
// to an internal copy of that instance! Use boost::ref() to
// capture a reference instead.
per_frame.listen(listener0.getName(), // note bug, dup name
boost::bind(&Listener::call, boost::ref(listener1), _1));
});
ensure_equals(threw,
std::string("DupListenerName: "
"Attempt to register duplicate listener name '") +
listener0.getName() + "' on " + typeid(per_frame).name() +
" '" + per_frame.getName() + "'");
// do it right this time
listener1.listenTo(per_frame);
per_frame.post(5);
check_listener("got", listener0, 5);
check_listener("got", listener1, 5);
per_frame.enable(false);
per_frame.post(6);
check_listener("didn't get", listener0, 5);
check_listener("didn't get", listener1, 5);
per_frame.enable();
per_frame.post(7);
check_listener("got", listener0, 7);
check_listener("got", listener1, 7);
per_frame.stopListening(listener0.getName());
ensure("disconnected 0", ! connection.connected());
ensure("disconnected 1", ! sameConnection.connected());
per_frame.post(8);
check_listener("disconnected", listener0, 7);
check_listener("still connected", listener1, 8);
per_frame.stopListening(listener1.getName());
per_frame.post(9);
check_listener("disconnected", listener1, 8);
}
template<> template<>
void events_object::test<2>()
{
set_test_name("callstop() returning true");
LLEventPump& per_frame(pumps.obtain("per-frame"));
listener0.reset(0);
listener1.reset(0);
LLBoundListener bound0 = listener0.listenTo(per_frame, &Listener::callstop);
LLBoundListener bound1 = listener1.listenTo(per_frame, &Listener::call,
// after listener0
make<LLEventPump::NameList>(list_of(listener0.getName())));
ensure("enabled", per_frame.enabled());
ensure("connected 0", bound0.connected());
ensure("unblocked 0", !bound0.blocked());
ensure("connected 1", bound1.connected());
ensure("unblocked 1", !bound1.blocked());
per_frame.post(1);
check_listener("got", listener0, 1);
// Because listener0.callstop() returns true, control never reaches listener1.call().
check_listener("got", listener1, 0);
}
bool chainEvents(Listener& someListener, const LLSD& event)
{
// Make this call so we can watch for side effects for test purposes.
someListener.call(event);
// This function represents a recursive event chain -- or some other
// scenario in which an event handler raises additional events.
int value = event.asInteger();
if (value)
{
LLEventPumps::instance().obtain("login").post(value - 1);
}
return false;
}
template<> template<>
void events_object::test<3>()
{
set_test_name("explicitly-instantiated LLEventStream");
// Explicitly instantiate an LLEventStream, and verify that it
// self-registers with LLEventPumps
size_t registered = pumps.mPumpMap.size();
size_t owned = pumps.mOurPumps.size();
LLEventPump* localInstance;
{
LLEventStream myEventStream("stream");
localInstance = &myEventStream;
LLEventPump& stream(pumps.obtain("stream"));
ensure("found named LLEventStream instance", &stream == localInstance);
ensure_equals("registered new instance", pumps.mPumpMap.size(), registered + 1);
ensure_equals("explicit instance not owned", pumps.mOurPumps.size(), owned);
} // destroy myEventStream -- should unregister
ensure_equals("destroyed instance unregistered", pumps.mPumpMap.size(), registered);
ensure_equals("destroyed instance not owned", pumps.mOurPumps.size(), owned);
LLEventPump& stream(pumps.obtain("stream"));
ensure("new LLEventStream instance", &stream != localInstance);
ensure_equals("obtain()ed instance registered", pumps.mPumpMap.size(), registered + 1);
ensure_equals("obtain()ed instance owned", pumps.mOurPumps.size(), owned + 1);
}
template<> template<>
void events_object::test<4>()
{
set_test_name("stopListening()");
LLEventPump& login(pumps.obtain("login"));
listener0.listenTo(login);
login.stopListening(listener0.getName());
// should not throw because stopListening() should have removed name
listener0.listenTo(login, &Listener::callstop);
LLBoundListener wrong = login.getListener("bogus");
ensure("bogus connection disconnected", !wrong.connected());
ensure("bogus connection blocked", wrong.blocked());
}
template<> template<>
void events_object::test<5>()
{
set_test_name("chaining LLEventPump instances");
LLEventPump& upstream(pumps.obtain("upstream"));
// One potentially-useful construct is to chain LLEventPumps together.
// Among other things, this allows you to turn subsets of listeners on
// and off in groups.
LLEventPump& filter0(pumps.obtain("filter0"));
LLEventPump& filter1(pumps.obtain("filter1"));
upstream.listen(filter0.getName(), boost::bind(&LLEventPump::post, boost::ref(filter0), _1));
upstream.listen(filter1.getName(), boost::bind(&LLEventPump::post, boost::ref(filter1), _1));
listener0.listenTo(filter0);
listener1.listenTo(filter1);
listener0.reset(0);
listener1.reset(0);
upstream.post(1);
check_listener("got unfiltered", listener0, 1);
check_listener("got unfiltered", listener1, 1);
filter0.enable(false);
upstream.post(2);
check_listener("didn't get filtered", listener0, 1);
check_listener("got filtered", listener1, 2);
}
template<> template<>
void events_object::test<6>()
{
set_test_name("listener dependency order");
typedef LLEventPump::NameList NameList;
LLEventPump& button(pumps.obtain("button"));
Collect collector;
button.listen("Mary",
boost::bind(&Collect::add, boost::ref(collector), "Mary", _1),
// state that "Mary" must come after "checked"
make<NameList> (list_of("checked")));
button.listen("checked",
boost::bind(&Collect::add, boost::ref(collector), "checked", _1),
// "checked" must come after "spot"
make<NameList> (list_of("spot")));
button.listen("spot",
boost::bind(&Collect::add, boost::ref(collector), "spot", _1));
button.post(1);
ensure_equals(collector.result, make<StringVec>(list_of("spot")("checked")("Mary")));
collector.clear();
button.stopListening("Mary");
button.listen("Mary",
boost::bind(&Collect::add, boost::ref(collector), "Mary", _1),
LLEventPump::empty, // no after dependencies
// now "Mary" must come before "spot"
make<NameList>(list_of("spot")));
button.post(2);
ensure_equals(collector.result, make<StringVec>(list_of("Mary")("spot")("checked")));
collector.clear();
button.stopListening("spot");
std::string threw = catch_what<LLEventPump::Cycle>(
[&button, &collector](){
button.listen("spot",
boost::bind(&Collect::add, boost::ref(collector), "spot", _1),
// after "Mary" and "checked" -- whoops!
make<NameList>(list_of("Mary")("checked")));
});
// Obviously the specific wording of the exception text can
// change; go ahead and change the test to match.
// Establish that it contains:
// - the name and runtime type of the LLEventPump
ensure_contains("LLEventPump type", threw, typeid(button).name());
ensure_contains("LLEventPump name", threw, "'button'");
// - the name of the new listener that caused the problem
ensure_contains("new listener name", threw, "'spot'");
// - a synopsis of the problematic dependencies.
ensure_contains("cyclic dependencies", threw,
"\"Mary\" -> before (\"spot\")");
ensure_contains("cyclic dependencies", threw,
"after (\"spot\") -> \"checked\"");
ensure_contains("cyclic dependencies", threw,
"after (\"Mary\", \"checked\") -> \"spot\"");
button.listen("yellow",
boost::bind(&Collect::add, boost::ref(collector), "yellow", _1),
make<NameList>(list_of("checked")));
button.listen("shoelaces",
boost::bind(&Collect::add, boost::ref(collector), "shoelaces", _1),
make<NameList>(list_of("checked")));
button.post(3);
ensure_equals(collector.result, make<StringVec>(list_of("Mary")("checked")("yellow")("shoelaces")));
collector.clear();
threw = catch_what<LLEventPump::OrderChange>(
[&button, &collector](){
button.listen("of",
boost::bind(&Collect::add, boost::ref(collector), "of", _1),
make<NameList>(list_of("shoelaces")),
make<NameList>(list_of("yellow")));
});
// Same remarks about the specific wording of the exception. Just
// ensure that it contains enough information to clarify the
// problem and what must be done to resolve it.
ensure_contains("LLEventPump type", threw, typeid(button).name());
ensure_contains("LLEventPump name", threw, "'button'");
ensure_contains("new listener name", threw, "'of'");
ensure_contains("prev listener name", threw, "'yellow'");
// std::cout << "Thrown Exception: " << threw << std::endl;
ensure_contains("old order", threw, "was: Mary, checked, yellow, shoelaces");
ensure_contains("new order", threw, "now: Mary, checked, shoelaces, of, yellow");
button.post(4);
ensure_equals(collector.result, make<StringVec>(list_of("Mary")("checked")("yellow")("shoelaces")));
}
template<> template<>
void events_object::test<7>()
{
set_test_name("tweaked and untweaked LLEventPump instance names");
{ // nested scope
// Hand-instantiate an LLEventStream...
LLEventStream bob("bob");
std::string threw = catch_what<LLEventPump::DupPumpName>(
[](){
// then another with a duplicate name.
LLEventStream bob2("bob");
});
ensure("Caught DupPumpName", !threw.empty());
} // delete first 'bob'
LLEventStream bob("bob"); // should work, previous one unregistered
LLEventStream bob1("bob", true);// allowed to tweak name
ensure_equals("tweaked LLEventStream name", bob1.getName(), "bob1");
std::vector<std::shared_ptr<LLEventStream> > streams;
for (int i = 2; i <= 10; ++i)
{
streams.push_back(std::shared_ptr<LLEventStream>(new LLEventStream("bob", true)));
}
ensure_equals("last tweaked LLEventStream name", streams.back()->getName(), "bob10");
}
// Define a function that accepts an LLListenerOrPumpName
void eventSource(const LLListenerOrPumpName& listener)
{
// Pretend that some time has elapsed. Call listener immediately.
listener(17);
}
template<> template<>
void events_object::test<8>()
{
set_test_name("LLListenerOrPumpName");
// Passing a boost::bind() expression to LLListenerOrPumpName
listener0.reset(0);
eventSource(boost::bind(&Listener::call, boost::ref(listener0), _1));
check_listener("got by listener", listener0, 17);
// Passing a string LLEventPump name to LLListenerOrPumpName
listener0.reset(0);
LLEventStream random("random");
listener0.listenTo(random);
eventSource("random");
check_listener("got by pump name", listener0, 17);
std::string threw = catch_what<LLListenerOrPumpName::Empty>(
[](){
LLListenerOrPumpName empty;
empty(17);
});
ensure("threw Empty", !threw.empty());
}
class TempListener: public Listener
{
public:
TempListener(const std::string& name, bool& liveFlag) :
Listener(name), mLiveFlag(liveFlag)
{
mLiveFlag = true;
}
virtual ~TempListener()
{
mLiveFlag = false;
}
private:
bool& mLiveFlag;
};
template<> template<>
void events_object::test<9>()
{
set_test_name("listen(boost::bind(...TempListener...))");
// listen() can't do anything about a plain TempListener instance:
// it's not managed with shared_ptr, nor is it an LLEventTrackable subclass
bool live = false;
LLEventPump& heaptest(pumps.obtain("heaptest"));
LLBoundListener connection;
{
TempListener tempListener("temp", live);
ensure("TempListener constructed", live);
connection = heaptest.listen(tempListener.getName(),
boost::bind(&Listener::call,
boost::ref(tempListener),
_1));
heaptest.post(1);
check_listener("received", tempListener, 1);
} // presumably this will make newListener go away?
// verify that
ensure("TempListener destroyed", !live);
// This is the case against which we can't defend. Don't even try to
// post to heaptest -- that would engage Undefined Behavior.
// Cautiously inspect connection...
ensure("misleadingly connected", connection.connected());
// then disconnect by hand.
heaptest.stopListening("temp");
}
class TempTrackableListener: public TempListener, public LLEventTrackable
{
public:
TempTrackableListener(const std::string& name, bool& liveFlag):
TempListener(name, liveFlag)
{}
};
template<> template<>
void events_object::test<10>()
{
set_test_name("listen(boost::bind(...TempTrackableListener ref...))");
bool live = false;
LLEventPump& heaptest(pumps.obtain("heaptest"));
LLBoundListener connection;
{
TempTrackableListener tempListener("temp", live);
ensure("TempTrackableListener constructed", live);
connection = heaptest.listen(tempListener.getName(),
boost::bind(&TempTrackableListener::call,
boost::ref(tempListener), _1));
heaptest.post(1);
check_listener("received", tempListener, 1);
} // presumably this will make tempListener go away?
// verify that
ensure("TempTrackableListener destroyed", ! live);
ensure("implicit disconnect", ! connection.connected());
// now just make sure we don't blow up trying to access a freed object!
heaptest.post(2);
}
template<> template<>
void events_object::test<11>()
{
set_test_name("listen(boost::bind(...TempTrackableListener pointer...))");
bool live = false;
LLEventPump& heaptest(pumps.obtain("heaptest"));
LLBoundListener connection;
{
TempTrackableListener* newListener(new TempTrackableListener("temp", live));
ensure("TempTrackableListener constructed", live);
connection = heaptest.listen(newListener->getName(),
boost::bind(&TempTrackableListener::call,
newListener, _1));
heaptest.post(1);
check_listener("received", *newListener, 1);
// explicitly destroy newListener
delete newListener;
}
// verify that
ensure("TempTrackableListener destroyed", ! live);
ensure("implicit disconnect", ! connection.connected());
// now just make sure we don't blow up trying to access a freed object!
heaptest.post(2);
}
} // namespace tut
+167
View File
@@ -0,0 +1,167 @@
/**
* @file llhttpdate_tut.cpp
* @author Kartic Krishnamurthy
* @date Wednesday, 18 Jul 2007 17:00:00 GMT :)
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "lltut.h"
#include "lldate.h"
#include "llcommon.h"
#include "llframetimer.h"
#include <time.h>
#include <locale.h>
namespace tut
{
struct httpdate_data
{
httpdate_data()
{
}
~httpdate_data()
{
}
LLDate some_date;
};
typedef test_group<httpdate_data> httpdate_test;
typedef httpdate_test::object httpdate_object;
tut::httpdate_test httpdate("httpdate");
template<> template<>
void httpdate_object::test<1>()
{
static std::string epoch_expected = "Thursday, 01 Jan 1970 00:00:00 GMT" ;
ensure("Check Epoch in RFC 1123", ( epoch_expected == some_date.asRFC1123()));
}
template<> template<>
void httpdate_object::test<2>()
{
static std::string expected = "Wednesday, 18 Jul 2007 22:17:24 GMT" ;
some_date = LLDate(1184797044.037586);
ensure("Check some timestamp in RFC 1123", ( expected == some_date.asRFC1123()));
}
// This test of course most generic.. runs off current time
template<> template<>
void httpdate_object::test<3>()
{
//F64 sometime = LLFrameTimer::getTotalSeconds();
time_t sometime;
time(&sometime);
some_date = LLDate((F64) sometime);
struct tm *result;
char expected[255];
std::string actual;
result = gmtime(&sometime);
/*
std::cout << " seconds: "<< result->tm_sec
<< ", minutes: " << result->tm_min
<< ", hours: " << result->tm_hour
<< ", day of the month: " << result->tm_mday
<< ", month: " << result->tm_mon
<< ", year: " << result->tm_year
<< ", day of the week: " << result->tm_wday
<< ", day in the year: " << result->tm_yday
<< ", DST: " << result->tm_isdst << std::endl;
*/
strftime(expected, 255, "%A, %d %b %Y %H:%M:%S GMT", result);
actual = some_date.asRFC1123();
// probably not a good idea to use strcmp but this is just a unit test
ensure("Current time in RFC 1123", (strcmp(expected, actual.c_str()) == 0));
}
void test_date_string(const std::string &locale, struct tm *t,
const std::string &fmt, const std::string &expected)
{
std::string result = LLDate::toHTTPDateString(t, fmt);
LLStringUtil::toLower(result);
std::string label = std::string("toHTTPDateString - ") + locale;
ensure_equals(label.c_str(), result, expected);
}
template<> template<>
void httpdate_object::test<4>()
{
// test localization of http dates
#if LL_WINDOWS
const char *en_locale = "english";
const char *fr_locale = "french";
#else
const char *en_locale = "en_GB.UTF-8";
const char *fr_locale = "fr_FR.UTF-8";
#endif
std::string prev_locale = LLStringUtil::getLocale();
std::string prev_clocale = std::string(setlocale(LC_TIME, NULL));
time_t test_time = 1252374030; // 8 Sep 2009 01:40:01
struct tm *t = gmtime(&test_time);
setlocale(LC_TIME, en_locale);
if (strcmp(setlocale(LC_TIME, NULL), en_locale) != 0)
{
setlocale(LC_TIME, prev_clocale.c_str());
skip("Cannot set English locale");
}
LLStringUtil::setLocale(en_locale);
test_date_string(en_locale, t, "%d %B %Y - %H:%M", "08 september 2009 - 01:40");
test_date_string(en_locale, t, "%H", "01");
test_date_string(en_locale, t, "%M", "40");
test_date_string(en_locale, t, "%I", "01");
test_date_string(en_locale, t, "%d", "08");
test_date_string(en_locale, t, "%Y", "2009");
test_date_string(en_locale, t, "%p", "am");
test_date_string(en_locale, t, "%A", "tuesday");
test_date_string(en_locale, t, "%B", "september");
setlocale(LC_TIME, fr_locale);
if (strcmp(setlocale(LC_TIME, NULL), fr_locale) != 0)
{
LLStringUtil::setLocale(prev_locale);
setlocale(LC_TIME, prev_clocale.c_str());
skip("Cannot set French locale");
}
LLStringUtil::setLocale(fr_locale);
test_date_string(fr_locale, t, "%d %B %Y - %H:%M", "08 septembre 2009 - 01:40");
test_date_string(fr_locale, t, "%H", "01");
test_date_string(fr_locale, t, "%M", "40");
test_date_string(fr_locale, t, "%I", "01");
test_date_string(fr_locale, t, "%d", "08");
test_date_string(fr_locale, t, "%Y", "2009");
test_date_string(fr_locale, t, "%A", "mardi");
test_date_string(fr_locale, t, "%B", "septembre");
LLStringUtil::setLocale(prev_locale);
setlocale(LC_TIME, prev_clocale.c_str());
}
}
+428
View File
@@ -0,0 +1,428 @@
/**
* @file lliohttpnode_tut.cpp
* @date May 2006
* @brief HTTP server unit tests
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "lltut.h"
#include "llhttpnode.h"
#include "llsdhttpserver.h"
namespace tut
{
struct HTTPNodeTestData
{
LLHTTPNode mRoot;
LLSD mContext;
const LLSD& context() { return mContext; }
std::string remainderPath()
{
std::ostringstream pathOutput;
bool addSlash = false;
LLSD& remainder = mContext[CONTEXT_REQUEST]["remainder"];
for (LLSD::array_const_iterator i = remainder.beginArray();
i != remainder.endArray();
++i)
{
if (addSlash) { pathOutput << '/'; }
pathOutput << i->asString();
addSlash = true;
}
return pathOutput.str();
}
void ensureRootTraversal(const std::string& path,
const LLHTTPNode* expectedNode,
const char* expectedRemainder)
{
mContext.clear();
const LLHTTPNode* actualNode = mRoot.traverse(path, mContext);
ensure_equals("traverse " + path + " node",
actualNode, expectedNode);
ensure_equals("traverse " + path + " remainder",
remainderPath(), expectedRemainder);
}
class Response : public LLHTTPNode::Response
{
public:
static LLPointer<Response> create() {return new Response();}
LLSD mResult;
void result(const LLSD& result) { mResult = result; }
void status(S32 code, const std::string& message) { }
void extendedResult(S32 code, const std::string& message, const LLSD& headers) { }
void extendedResult(S32 code, const LLSD& result, const LLSD& headers) { }
private:
Response() {;} // Must be accessed through LLPointer.
};
typedef LLPointer<Response> ResponsePtr;
LLSD get(const std::string& path)
{
mContext.clear();
const LLHTTPNode* node = mRoot.traverse(path, mContext);
ensure(path + " found", node != NULL);
ResponsePtr response = Response::create();
node->get(LLHTTPNode::ResponsePtr(response), mContext);
return response->mResult;
}
LLSD post(const std::string& path, const LLSD& input)
{
mContext.clear();
const LLHTTPNode* node = mRoot.traverse(path, mContext);
ensure(path + " found", node != NULL);
ResponsePtr response = Response::create();
node->post(LLHTTPNode::ResponsePtr(response), mContext, input);
return response->mResult;
}
void ensureMemberString(const std::string& name,
const LLSD& actualMap, const std::string& member,
const std::string& expectedValue)
{
ensure_equals(name + " " + member,
actualMap[member].asString(), expectedValue);
}
void ensureInArray(const LLSD& actualArray,
const std::string& expectedValue)
{
LLSD::array_const_iterator i = actualArray.beginArray();
LLSD::array_const_iterator end = actualArray.endArray();
for (; i != end; ++i)
{
std::string path = i->asString();
if (path == expectedValue)
{
return;
}
}
fail("didn't find " + expectedValue);
}
};
typedef test_group<HTTPNodeTestData> HTTPNodeTestGroup;
typedef HTTPNodeTestGroup::object HTTPNodeTestObject;
HTTPNodeTestGroup httpNodeTestGroup("http node");
template<> template<>
void HTTPNodeTestObject::test<1>()
{
// traversal of the lone node
ensureRootTraversal("", &mRoot, "");
ensureRootTraversal("/", &mRoot, "");
ensureRootTraversal("foo", NULL, "foo");
ensureRootTraversal("foo/bar", NULL, "foo/bar");
ensure_equals("root of root", mRoot.rootNode(), &mRoot);
}
template<> template<>
void HTTPNodeTestObject::test<2>()
{
// simple traversal of a single node
LLHTTPNode* helloNode = new LLHTTPNode;
mRoot.addNode("hello", helloNode);
ensureRootTraversal("hello", helloNode, "");
ensureRootTraversal("/hello", helloNode, "");
ensureRootTraversal("hello/", helloNode, "");
ensureRootTraversal("/hello/", helloNode, "");
ensureRootTraversal("hello/there", NULL, "there");
ensure_equals("root of hello", helloNode->rootNode(), &mRoot);
}
template<> template<>
void HTTPNodeTestObject::test<3>()
{
// traversal of mutli-branched tree
LLHTTPNode* greekNode = new LLHTTPNode;
LLHTTPNode* alphaNode = new LLHTTPNode;
LLHTTPNode* betaNode = new LLHTTPNode;
LLHTTPNode* gammaNode = new LLHTTPNode;
greekNode->addNode("alpha", alphaNode);
greekNode->addNode("beta", betaNode);
greekNode->addNode("gamma", gammaNode);
mRoot.addNode("greek", greekNode);
LLHTTPNode* hebrewNode = new LLHTTPNode;
LLHTTPNode* alephNode = new LLHTTPNode;
hebrewNode->addNode("aleph", alephNode);
mRoot.addNode("hebrew", hebrewNode);
ensureRootTraversal("greek/alpha", alphaNode, "");
ensureRootTraversal("greek/beta", betaNode, "");
ensureRootTraversal("greek/delta", NULL, "delta");
ensureRootTraversal("greek/gamma", gammaNode, "");
ensureRootTraversal("hebrew/aleph", alephNode, "");
ensure_equals("root of greek", greekNode->rootNode(), &mRoot);
ensure_equals("root of alpha", alphaNode->rootNode(), &mRoot);
ensure_equals("root of beta", betaNode->rootNode(), &mRoot);
ensure_equals("root of gamma", gammaNode->rootNode(), &mRoot);
ensure_equals("root of hebrew", hebrewNode->rootNode(), &mRoot);
ensure_equals("root of aleph", alephNode->rootNode(), &mRoot);
}
template<> template<>
void HTTPNodeTestObject::test<4>()
{
// automatic creation of parent nodes and not overriding existing nodes
LLHTTPNode* alphaNode = new LLHTTPNode;
LLHTTPNode* betaNode = new LLHTTPNode;
LLHTTPNode* gammaNode = new LLHTTPNode;
LLHTTPNode* gamma2Node = new LLHTTPNode;
mRoot.addNode("greek/alpha", alphaNode);
mRoot.addNode("greek/beta", betaNode);
mRoot.addNode("greek/gamma", gammaNode);
mRoot.addNode("greek/gamma", gamma2Node);
LLHTTPNode* alephNode = new LLHTTPNode;
mRoot.addNode("hebrew/aleph", alephNode);
ensureRootTraversal("greek/alpha", alphaNode, "");
ensureRootTraversal("greek/beta", betaNode, "");
ensureRootTraversal("greek/delta", NULL, "delta");
ensureRootTraversal("greek/gamma", gammaNode, "");
ensureRootTraversal("hebrew/aleph", alephNode, "");
ensure_equals("root of alpha", alphaNode->rootNode(), &mRoot);
ensure_equals("root of beta", betaNode->rootNode(), &mRoot);
ensure_equals("root of gamma", gammaNode->rootNode(), &mRoot);
ensure_equals("root of aleph", alephNode->rootNode(), &mRoot);
}
class IntegerNode : public LLHTTPNode
{
public:
virtual void get(ResponsePtr response, const LLSD& context) const
{
int n = context["extra"]["value"];
LLSD info;
info["value"] = n;
info["positive"] = n > 0;
info["zero"] = n == 0;
info["negative"] = n < 0;
response->result(info);
}
virtual bool validate(const std::string& name, LLSD& context) const
{
int n;
std::istringstream i_stream(name);
i_stream >> n;
if (i_stream.fail() || i_stream.get() != EOF)
{
return false;
}
context["extra"]["value"] = n;
return true;
}
};
class SquareNode : public LLHTTPNode
{
public:
virtual void get(ResponsePtr response, const LLSD& context) const
{
int n = context["extra"]["value"];
response->result(n*n);
}
};
template<> template<>
void HTTPNodeTestObject::test<5>()
{
// wildcard nodes
LLHTTPNode* miscNode = new LLHTTPNode;
LLHTTPNode* iNode = new IntegerNode;
LLHTTPNode* sqNode = new SquareNode;
mRoot.addNode("test/misc", miscNode);
mRoot.addNode("test/<int>", iNode);
mRoot.addNode("test/<int>/square", sqNode);
ensureRootTraversal("test/42", iNode, "");
ensure_equals("stored integer",
context()["extra"]["value"].asInteger(), 42);
ensureRootTraversal("test/bob", NULL, "bob");
ensure("nothing stored",
context()["extra"]["value"].isUndefined());
ensureRootTraversal("test/3/square", sqNode, "");
ResponsePtr response = Response::create();
sqNode->get(LLHTTPNode::ResponsePtr(response), context());
ensure_equals("square result", response->mResult.asInteger(), 9);
}
class AlphaNode : public LLHTTPNode
{
public:
virtual bool handles(const LLSD& remainder, LLSD& context) const
{
LLSD::array_const_iterator i = remainder.beginArray();
LLSD::array_const_iterator end = remainder.endArray();
for (; i != end; ++i)
{
std::string s = i->asString();
if (s.empty() || s[0] != 'a')
{
return false;
}
}
return true;
}
};
template<> template<>
void HTTPNodeTestObject::test<6>()
{
// nodes that handle remainders
LLHTTPNode* miscNode = new LLHTTPNode;
LLHTTPNode* aNode = new AlphaNode;
LLHTTPNode* zNode = new LLHTTPNode;
mRoot.addNode("test/misc", miscNode);
mRoot.addNode("test/alpha", aNode);
mRoot.addNode("test/alpha/zebra", zNode);
ensureRootTraversal("test/alpha", aNode, "");
ensureRootTraversal("test/alpha/abe", aNode, "abe");
ensureRootTraversal("test/alpha/abe/amy", aNode, "abe/amy");
ensureRootTraversal("test/alpha/abe/bea", NULL, "abe/bea");
ensureRootTraversal("test/alpha/bob", NULL, "bob");
ensureRootTraversal("test/alpha/zebra", zNode, "");
}
template<> template<>
void HTTPNodeTestObject::test<7>()
{
// test auto registration
LLHTTPStandardServices::useServices();
LLHTTPRegistrar::buildAllServices(mRoot);
{
LLSD result = get("web/hello");
ensure_equals("hello result", result.asString(), "hello");
}
{
LLSD stuff = 3.14159;
LLSD result = post("web/echo", stuff);
ensure_equals("echo result", result, stuff);
}
}
template<> template<>
void HTTPNodeTestObject::test<8>()
{
// test introspection
LLHTTPRegistrar::buildAllServices(mRoot);
mRoot.addNode("test/misc", new LLHTTPNode);
mRoot.addNode("test/<int>", new IntegerNode);
mRoot.addNode("test/<int>/square", new SquareNode);
const LLSD result = get("web/server/api");
ensure("result is array", result.isArray());
ensure("result size", result.size() >= 2);
ensureInArray(result, "web/echo");
ensureInArray(result, "web/hello");
ensureInArray(result, "test/misc");
ensureInArray(result, "test/<int>");
ensureInArray(result, "test/<int>/square");
}
template<> template<>
void HTTPNodeTestObject::test<9>()
{
// test introspection details
LLHTTPRegistrar::buildAllServices(mRoot);
const LLSD helloDetails = get("web/server/api/web/hello");
ensure_contains("hello description",
helloDetails["description"].asString(), "hello");
ensure_equals("method name", helloDetails["api"][0].asString(), std::string("GET"));
ensureMemberString("hello", helloDetails, "output", "\"hello\"");
ensure_contains("hello __file__",
helloDetails["__file__"].asString(), "llsdhttpserver.cpp");
ensure("hello line", helloDetails["__line__"].isInteger());
const LLSD echoDetails = get("web/server/api/web/echo");
ensure_contains("echo description",
echoDetails["description"].asString(), "echo");
ensure_equals("method name", echoDetails["api"][0].asString(), std::string("POST"));
ensureMemberString("echo", echoDetails, "input", "<any>");
ensureMemberString("echo", echoDetails, "output", "<the input>");
ensure_contains("echo __file__",
echoDetails["__file__"].asString(), "llsdhttpserver.cpp");
ensure("echo", echoDetails["__line__"].isInteger());
}
}
+350
View File
@@ -0,0 +1,350 @@
/**
* @file lliohttpserver_tut.cpp
* @date May 2006
* @brief HTTP server unit tests
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "lltut.h"
#include "llbufferstream.h"
#include "lliohttpserver.h"
#include "llsdhttpserver.h"
#include "llsdserialize.h"
#include "llcommon.h"
#include "llpipeutil.h"
namespace tut
{
class HTTPServiceTestData
{
public:
class DelayedEcho : public LLHTTPNode
{
HTTPServiceTestData* mTester;
public:
DelayedEcho(HTTPServiceTestData* tester) : mTester(tester) { }
void post(ResponsePtr response, const LLSD& context, const LLSD& input) const
{
ensure("response already set", mTester->mResponse == ResponsePtr(NULL));
mTester->mResponse = response;
mTester->mResult = input;
}
};
class WireHello : public LLIOPipe
{
protected:
virtual EStatus process_impl(
const LLChannelDescriptors& channels,
buffer_ptr_t& buffer,
bool& eos,
LLSD& context,
LLPumpIO* pump)
{
if(!eos) return STATUS_BREAK;
LLSD sd = "yo!";
LLBufferStream ostr(channels, buffer.get());
ostr << LLSDXMLStreamer(sd);
return STATUS_DONE;
}
};
HTTPServiceTestData()
: mResponse(NULL)
{
LLHTTPStandardServices::useServices();
LLHTTPRegistrar::buildAllServices(mRoot);
mRoot.addNode("/delayed/echo", new DelayedEcho(this));
mRoot.addNode("/wire/hello", new LLHTTPNodeForPipe<WireHello>);
}
~HTTPServiceTestData()
{
}
LLHTTPNode mRoot;
LLHTTPNode::ResponsePtr mResponse;
LLSD mResult;
void pumpPipe(LLPumpIO* pump, S32 iterations)
{
while(iterations > 0)
{
pump->pump();
pump->callback();
--iterations;
}
}
std::string makeRequest(
const std::string& name,
const std::string& httpRequest,
bool timeout = false)
{
LLPipeStringInjector* injector = new LLPipeStringInjector(httpRequest);
LLPipeStringExtractor* extractor = new LLPipeStringExtractor();
apr_pool_t* pool;
apr_pool_create(&pool, NULL);
LLPumpIO* pump;
pump = new LLPumpIO(pool);
LLPumpIO::chain_t chain;
LLSD context;
chain.push_back(LLIOPipe::ptr_t(injector));
LLIOHTTPServer::createPipe(chain, mRoot, LLSD());
chain.push_back(LLIOPipe::ptr_t(extractor));
pump->addChain(chain, DEFAULT_CHAIN_EXPIRY_SECS);
pumpPipe(pump, 10);
if(mResponse.notNull() && (! timeout))
{
mResponse->result(mResult);
mResponse = NULL;
}
pumpPipe(pump, 10);
std::string httpResult = extractor->string();
chain.clear();
delete pump;
apr_pool_destroy(pool);
if(mResponse.notNull() && timeout)
{
mResponse->result(mResult);
mResponse = NULL;
}
return httpResult;
}
std::string httpGET(const std::string& uri,
bool timeout = false)
{
std::string httpRequest = "GET " + uri + " HTTP/1.0\r\n\r\n";
return makeRequest(uri, httpRequest, timeout);
}
std::string httpPOST(const std::string& uri,
const std::string& body,
bool timeout,
const std::string& evilExtra = "")
{
std::ostringstream httpRequest;
httpRequest << "POST " + uri + " HTTP/1.0\r\n";
httpRequest << "Content-Length: " << body.size() << "\r\n";
httpRequest << "\r\n";
httpRequest << body;
httpRequest << evilExtra;
return makeRequest(uri, httpRequest.str(), timeout);
}
std::string httpPOST(const std::string& uri,
const std::string& body,
const std::string& evilExtra = "")
{
bool timeout = false;
return httpPOST(uri, body, timeout, evilExtra);
}
};
typedef test_group<HTTPServiceTestData> HTTPServiceTestGroup;
typedef HTTPServiceTestGroup::object HTTPServiceTestObject;
HTTPServiceTestGroup httpServiceTestGroup("http service");
template<> template<>
void HTTPServiceTestObject::test<1>()
{
std::string result = httpGET("web/hello");
ensure_starts_with("web/hello status", result,
"HTTP/1.0 200 OK\r\n");
ensure_contains("web/hello content type", result,
"Content-Type: application/llsd+xml\r\n");
ensure_contains("web/hello content length", result,
"Content-Length: 36\r\n");
ensure_contains("web/hello content", result,
"\r\n"
"<llsd><string>hello</string></llsd>"
);
}
template<> template<>
void HTTPServiceTestObject::test<2>()
{
// test various HTTP errors
std::string actual;
actual = httpGET("web/missing");
ensure_starts_with("web/missing 404", actual,
"HTTP/1.0 404 Not Found\r\n");
actual = httpGET("web/echo");
ensure_starts_with("web/echo 405", actual,
"HTTP/1.0 405 Method Not Allowed\r\n");
}
template<> template<>
void HTTPServiceTestObject::test<3>()
{
// test POST & content-length handling
std::string result;
result = httpPOST("web/echo",
"<llsd><integer>42</integer></llsd>");
ensure_starts_with("web/echo status", result,
"HTTP/1.0 200 OK\r\n");
ensure_contains("web/echo content type", result,
"Content-Type: application/llsd+xml\r\n");
ensure_contains("web/echo content length", result,
"Content-Length: 35\r\n");
ensure_contains("web/hello content", result,
"\r\n"
"<llsd><integer>42</integer></llsd>"
);
/* TO DO: this test doesn't pass!!
result = httpPOST("web/echo",
"<llsd><string>evil</string></llsd>",
"really! evil!!!");
ensure_equals("web/echo evil result", result,
"HTTP/1.0 200 OK\r\n"
"Content-Length: 34\r\n"
"\r\n"
"<llsd><string>evil</string></llsd>"
);
*/
}
template<> template<>
void HTTPServiceTestObject::test<4>()
{
// test calling things based on pipes
std::string result;
result = httpGET("wire/hello");
ensure_contains("wire/hello", result, "yo!");
}
template<> template<>
void HTTPServiceTestObject::test<5>()
{
// test timeout before async response
std::string result;
bool timeout = true;
result = httpPOST("delayed/echo",
"<llsd><string>agent99</string></llsd>", timeout);
ensure_equals("timeout delayed/echo status", result, std::string(""));
}
template<> template<>
void HTTPServiceTestObject::test<6>()
{
// test delayed service
std::string result;
result = httpPOST("delayed/echo",
"<llsd><string>agent99</string></llsd>");
ensure_starts_with("delayed/echo status", result,
"HTTP/1.0 200 OK\r\n");
ensure_contains("delayed/echo content", result,
"\r\n"
"<llsd><string>agent99</string></llsd>"
);
}
template<> template<>
void HTTPServiceTestObject::test<7>()
{
// test large request
std::stringstream stream;
//U32 size = 36 * 1024 * 1024;
//U32 size = 36 * 1024;
//std::vector<char> data(size);
//memset(&(data[0]), '1', size);
//data[size - 1] = '\0';
//std::string result = httpPOST("web/echo", &(data[0]));
stream << "<llsd><array>";
for(U32 i = 0; i < 1000000; ++i)
{
stream << "<integer>42</integer>";
}
stream << "</array></llsd>";
LL_INFOS() << "HTTPServiceTestObject::test<7>"
<< stream.str().length() << LL_ENDL;
std::string result = httpPOST("web/echo", stream.str());
ensure_starts_with("large echo status", result, "HTTP/1.0 200 OK\r\n");
}
template<> template<>
void HTTPServiceTestObject::test<8>()
{
// test the OPTIONS http method -- the default implementation
// should return the X-Documentation-URL
std::ostringstream http_request;
http_request << "OPTIONS / HTTP/1.0\r\nHost: localhost\r\n\r\n";
bool timeout = false;
std::string result = makeRequest("/", http_request.str(), timeout);
ensure_starts_with("OPTIONS verb ok", result, "HTTP/1.0 200 OK\r\n");
ensure_contains(
"Doc url header exists",
result,
"X-Documentation-URL: http://localhost");
}
/* TO DO:
test generation of not found and method not allowed errors
*/
}
+236
View File
@@ -0,0 +1,236 @@
/**
* @file llmessageconfig_tut.cpp
* @date March 2007
* @brief LLMessageConfig unit tests
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llmessageconfig.h"
#include "lltut.h"
#include "llsdserialize.h"
#include "llfile.h"
#include "lltimer.h"
#include "llframetimer.h"
#include "llsdutil.h"
namespace tut
{
struct LLMessageConfigTestData {
std::string mTestConfigDir;
LLMessageConfigTestData()
{
LLUUID random;
random.generate();
// generate temp dir
std::ostringstream oStr;
#if LL_WINDOWS
oStr << "llmessage-config-test-" << random;
#else
oStr << "/tmp/llmessage-config-test-" << random;
#endif
mTestConfigDir = oStr.str();
LLFile::mkdir(mTestConfigDir);
writeConfigFile(LLSD());
LLMessageConfig::initClass("simulator", mTestConfigDir);
}
~LLMessageConfigTestData()
{
// rm contents of temp dir
int rmfile = LLFile::remove((mTestConfigDir + "/message.xml"));
ensure_equals("rmfile value", rmfile, 0);
// rm temp dir
int rmdir = LLFile::rmdir(mTestConfigDir);
ensure_equals("rmdir value", rmdir, 0);
}
void writeConfigFile(const LLSD& config)
{
llofstream file((mTestConfigDir + "/message.xml").c_str());
if (file.is_open())
{
LLSDSerialize::toPrettyXML(config, file);
}
file.close();
}
};
typedef test_group<LLMessageConfigTestData> LLMessageConfigTestGroup;
typedef LLMessageConfigTestGroup::object LLMessageConfigTestObject;
LLMessageConfigTestGroup llMessageConfigTestGroup("LLMessageConfig");
template<> template<>
void LLMessageConfigTestObject::test<1>()
// tests server defaults
{
LLSD config;
config["serverDefaults"]["simulator"] = "template";
LLMessageConfig::useConfig(config);
ensure_equals("Ensure server default is not template",
LLMessageConfig::getServerDefaultFlavor(),
LLMessageConfig::TEMPLATE_FLAVOR);
}
template<> template<>
void LLMessageConfigTestObject::test<2>()
// tests message flavors
{
LLSD config;
config["serverDefaults"]["simulator"] = "template";
config["messages"]["msg1"]["flavor"] = "template";
config["messages"]["msg2"]["flavor"] = "llsd";
LLMessageConfig::useConfig(config);
ensure_equals("Ensure msg template flavor",
LLMessageConfig::getMessageFlavor("msg1"),
LLMessageConfig::TEMPLATE_FLAVOR);
ensure_equals("Ensure msg llsd flavor",
LLMessageConfig::getMessageFlavor("msg2"),
LLMessageConfig::LLSD_FLAVOR);
}
template<> template<>
void LLMessageConfigTestObject::test<4>()
// tests message flavor defaults
{
LLSD config;
config["serverDefaults"]["simulator"] = "llsd";
config["messages"]["msg1"]["trusted-sender"] = true;
LLMessageConfig::useConfig(config);
ensure_equals("Ensure missing message gives no flavor",
LLMessageConfig::getMessageFlavor("Test"),
LLMessageConfig::NO_FLAVOR);
ensure_equals("Ensure missing flavor is NO_FLAVOR even with sender trustedness set",
LLMessageConfig::getMessageFlavor("msg1"),
LLMessageConfig::NO_FLAVOR);
ensure_equals("Ensure server default is llsd",
LLMessageConfig::getServerDefaultFlavor(),
LLMessageConfig::LLSD_FLAVOR);
}
template<> template<>
void LLMessageConfigTestObject::test<3>()
// tests trusted/untrusted senders
{
LLSD config;
config["serverDefaults"]["simulator"] = "template";
config["messages"]["msg1"]["flavor"] = "llsd";
config["messages"]["msg1"]["trusted-sender"] = false;
config["messages"]["msg2"]["flavor"] = "llsd";
config["messages"]["msg2"]["trusted-sender"] = true;
LLMessageConfig::useConfig(config);
ensure_equals("Ensure untrusted is untrusted",
LLMessageConfig::getSenderTrustedness("msg1"),
LLMessageConfig::UNTRUSTED);
ensure_equals("Ensure trusted is trusted",
LLMessageConfig::getSenderTrustedness("msg2"),
LLMessageConfig::TRUSTED);
ensure_equals("Ensure missing trustedness is NOT_SET",
LLMessageConfig::getSenderTrustedness("msg3"),
LLMessageConfig::NOT_SET);
}
template<> template<>
void LLMessageConfigTestObject::test<5>()
// tests trusted/untrusted without flag, only flavor
{
LLSD config;
config["serverDefaults"]["simulator"] = "template";
config["messages"]["msg1"]["flavor"] = "llsd";
LLMessageConfig::useConfig(config);
ensure_equals("Ensure msg1 exists, has llsd flavor",
LLMessageConfig::getMessageFlavor("msg1"),
LLMessageConfig::LLSD_FLAVOR);
ensure_equals("Ensure missing trusted is not set",
LLMessageConfig::getSenderTrustedness("msg1"),
LLMessageConfig::NOT_SET);
}
template<> template<>
void LLMessageConfigTestObject::test<6>()
{
LLSD config;
config["capBans"]["MapLayer"] = true;
config["capBans"]["MapLayerGod"] = false;
LLMessageConfig::useConfig(config);
ensure_equals("Ensure cap ban true MapLayer",
LLMessageConfig::isCapBanned("MapLayer"),
true);
ensure_equals("Ensure cap ban false",
LLMessageConfig::isCapBanned("MapLayerGod"),
false);
}
template<> template<>
void LLMessageConfigTestObject::test<7>()
// tests that config changes are picked up/refreshed periodically
{
LLSD config;
config["serverDefaults"]["simulator"] = "llsd";
writeConfigFile(config);
// wait for it to reload after N seconds
ms_sleep(6*1000);
LLFrameTimer::updateFrameTime();
ensure_equals("Ensure reload after 6 seconds",
LLMessageConfig::getServerDefaultFlavor(),
LLMessageConfig::LLSD_FLAVOR);
}
template<> template<>
void LLMessageConfigTestObject::test<8>()
// tests that config changes are picked up/refreshed periodically
{
LLSD config;
config["serverDefaults"]["simulator"] = "template";
config["messages"]["msg1"]["flavor"] = "llsd";
config["messages"]["msg1"]["only-send-latest"] = true;
config["messages"]["msg2"]["flavor"] = "llsd";
config["messages"]["msg2"]["only-send-latest"] = false;
LLMessageConfig::useConfig(config);
ensure_equals("Ensure msg1 exists, sent latest-only",
LLMessageConfig::onlySendLatest("msg1"),
true);
ensure_equals("Ensure msg2 exists, sent latest-only",
LLMessageConfig::onlySendLatest("msg2"),
false);
}
template<> template<>
void LLMessageConfigTestObject::test<9>()
// tests that event queue max is reloaded
{
LLSD config;
config["maxQueuedEvents"] = 200;
LLMessageConfig::useConfig(config);
ensure_equals("Ensure setting maxQueuedEvents",
LLMessageConfig::getMaxQueuedEvents(),
200);
LLMessageConfig::useConfig(LLSD());
ensure_equals("Ensure default of event queue max 100",
LLMessageConfig::getMaxQueuedEvents(),
100);
}
}
+368
View File
@@ -0,0 +1,368 @@
/**
* @file llmessagetemplateparser_tut.cpp
* @date April 2007
* @brief LLMessageTemplateParser unit tests
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llmessagetemplateparser.h"
#include "lltut.h"
namespace tut
{
struct LLMessageTemplateParserTestData {
LLMessageTemplateParserTestData() : mMessage("unset message")
{
}
~LLMessageTemplateParserTestData()
{
}
void ensure_next(LLTemplateTokenizer & tokens,
std::string value,
U32 line)
{
std::string next = tokens.next();
ensure_equals(mMessage + " token matches", next, value);
ensure_equals(mMessage + " line matches", tokens.line(), line);
}
char * prehash(const char * name)
{
return LLMessageStringTable::getInstance()->getString(name);
}
void ensure_block_attributes(std::string identifier,
const LLMessageTemplate * message,
const char * name,
EMsgBlockType type,
S32 number,
S32 total_size)
{
const LLMessageBlock * block = message->getBlock(prehash(name));
identifier = identifier + ":" + message->mName + ":" + name + " block";
ensure(identifier + " exists", block != NULL);
ensure_equals(identifier + " name", block->mName, prehash(name));
ensure_equals(identifier + " type", block->mType, type);
ensure_equals(identifier + " number", block->mNumber, number);
ensure_equals(identifier + " total size", block->mTotalSize, total_size);
}
void ensure_variable_attributes(std::string identifier,
const LLMessageBlock * block,
const char * name,
EMsgVariableType type,
S32 size)
{
const LLMessageVariable * var = block->getVariable(prehash(name));
identifier = identifier + ":" + block->mName + ":" + name + " variable";
ensure(identifier + " exists", var != NULL);
ensure_equals(
identifier + " name", var->getName(), prehash(name));
ensure_equals(
identifier + " type", var->getType(), type);
ensure_equals(identifier + " size", var->getSize(), size);
}
std::string mMessage;
};
typedef test_group<LLMessageTemplateParserTestData> LLMessageTemplateParserTestGroup;
typedef LLMessageTemplateParserTestGroup::object LLMessageTemplateParserTestObject;
LLMessageTemplateParserTestGroup llMessageTemplateParserTestGroup("LLMessageTemplateParser");
template<> template<>
void LLMessageTemplateParserTestObject::test<1>()
// tests tokenizer constructor and next methods
{
mMessage = "test method 1 walkthrough";
LLTemplateTokenizer tokens("first line\nnext\t line\n\nfourth");
ensure_next(tokens, "first", 1);
ensure_next(tokens, "line", 1);
ensure_next(tokens, "next", 2);
ensure_next(tokens, "line", 2);
ensure_next(tokens, "fourth", 4);
tokens = LLTemplateTokenizer("\n\t{ \t Test1 Fixed \n 523 }\n\n");
ensure(tokens.want("{"));
ensure_next(tokens, "Test1", 2);
ensure_next(tokens, "Fixed", 2);
ensure_next(tokens, "523", 3);
ensure(tokens.want("}"));
tokens = LLTemplateTokenizer("first line\nnext\t line\n\nfourth");
ensure(tokens.want("first"));
ensure_next(tokens, "line", 1);
ensure_next(tokens, "next", 2);
ensure_next(tokens, "line", 2);
ensure(tokens.want("fourth"));
}
template<> template<>
void LLMessageTemplateParserTestObject::test<2>()
// tests tokenizer want method
{
// *NOTE: order matters
LLTemplateTokenizer tokens("first line\nnext\t line\n\nfourth");
ensure_equals("wants first token", tokens.want("first"), true);
ensure_equals("doesn't want blar token", tokens.want("blar"), false);
ensure_equals("wants line token", tokens.want("line"), true);
}
template<> template<>
void LLMessageTemplateParserTestObject::test<3>()
// tests tokenizer eof methods
{
LLTemplateTokenizer tokens("single\n\n");
ensure_equals("is not at eof at beginning", tokens.atEOF(), false);
ensure_equals("doesn't want eof", tokens.wantEOF(), false);
ensure_equals("wants the first token just to consume it",
tokens.want("single"), true);
ensure_equals("is not at eof in middle", tokens.atEOF(), false);
ensure_equals("wants eof", tokens.wantEOF(), true);
ensure_equals("is at eof at end", tokens.atEOF(), true);
}
template<> template<>
void LLMessageTemplateParserTestObject::test<4>()
// tests variable parsing method
{
LLTemplateTokenizer tokens(std::string("{ Test0 \n\t\n U32 \n\n }"));
LLMessageVariable * var = LLTemplateParser::parseVariable(tokens);
ensure("test0 var parsed", var != 0);
ensure_equals("name of variable", std::string(var->getName()), std::string("Test0"));
ensure_equals("type of variable is U32", var->getType(), MVT_U32);
ensure_equals("size of variable", var->getSize(), 4);
delete var;
std::string message_string("\n\t{ \t Test1 Fixed \n 523 }\n\n");
tokens = LLTemplateTokenizer(message_string);
var = LLTemplateParser::parseVariable(tokens);
ensure("test1 var parsed", var != 0);
ensure_equals("name of variable", std::string(var->getName()), std::string("Test1"));
ensure_equals("type of variable is Fixed", var->getType(), MVT_FIXED);
ensure_equals("size of variable", var->getSize(), 523);
delete var;
// *NOTE: the parsers call LL_ERRS() on invalid input, so we can't really
// test that :-(
}
template<> template<>
void LLMessageTemplateParserTestObject::test<5>()
// tests block parsing method
{
LLTemplateTokenizer tokens("{ BlockA Single { VarX F32 } }");
LLMessageBlock * block = LLTemplateParser::parseBlock(tokens);
ensure("blockA block parsed", block != 0);
ensure_equals("name of block", std::string(block->mName), std::string("BlockA"));
ensure_equals("type of block is Single", block->mType, MBT_SINGLE);
ensure_equals("total size of block", block->mTotalSize, 4);
ensure_equals("number of block defaults to 1", block->mNumber, 1);
ensure_equals("variable type of VarX is F32",
block->getVariableType(prehash("VarX")), MVT_F32);
ensure_equals("variable size of VarX",
block->getVariableSize(prehash("VarX")), 4);
delete block;
tokens = LLTemplateTokenizer("{ Stuff Variable { Id LLUUID } }");
block = LLTemplateParser::parseBlock(tokens);
ensure("stuff block parsed", block != 0);
ensure_equals("name of block", std::string(block->mName), std::string("Stuff"));
ensure_equals("type of block is Multiple", block->mType, MBT_VARIABLE);
ensure_equals("total size of block", block->mTotalSize, 16);
ensure_equals("number of block defaults to 1", block->mNumber, 1);
ensure_equals("variable type of Id is LLUUID",
block->getVariableType(prehash("Id")), MVT_LLUUID);
ensure_equals("variable size of Id",
block->getVariableSize(prehash("Id")), 16);
delete block;
tokens = LLTemplateTokenizer("{ Stuff2 Multiple 45 { Shid LLVector3d } }");
block = LLTemplateParser::parseBlock(tokens);
ensure("stuff2 block parsed", block != 0);
ensure_equals("name of block", std::string(block->mName), std::string("Stuff2"));
ensure_equals("type of block is Multiple", block->mType, MBT_MULTIPLE);
ensure_equals("total size of block", block->mTotalSize, 24);
ensure_equals("number of blocks", block->mNumber, 45);
ensure_equals("variable type of Shid is Vector3d",
block->getVariableType(prehash("Shid")), MVT_LLVector3d);
ensure_equals("variable size of Shid",
block->getVariableSize(prehash("Shid")), 24);
delete block;
}
template<> template<>
void LLMessageTemplateParserTestObject::test<6>()
// tests message parsing method on a simple message
{
std::string message_skel(
"{\n"
"TestMessage Low 1 NotTrusted Zerocoded\n"
"// comment \n"
" {\n"
"TestBlock1 Single\n"
" { Test1 U32 }\n"
" }\n"
" {\n"
" NeighborBlock Multiple 4\n"
" { Test0 U32 }\n"
" { Test1 U32 }\n"
" { Test2 U32 }\n"
" }\n"
"}");
LLTemplateTokenizer tokens(message_skel);
LLMessageTemplate * message = LLTemplateParser::parseMessage(tokens);
ensure("simple message parsed", message != 0);
ensure_equals("name of message", std::string(message->mName), std::string("TestMessage"));
ensure_equals("frequency is Low", message->mFrequency, MFT_LOW);
ensure_equals("trust is untrusted", message->mTrust, MT_NOTRUST);
ensure_equals("message number", message->mMessageNumber, (U32)((255 << 24) | (255 << 16) | 1));
ensure_equals("message encoding is zerocoded", message->mEncoding, ME_ZEROCODED);
ensure_equals("message deprecation is notdeprecated", message->mDeprecation, MD_NOTDEPRECATED);
LLMessageBlock * block = message->getBlock(prehash("NonexistantBlock"));
ensure("Nonexistant block does not exist", block == 0);
delete message;
}
template<> template<>
void LLMessageTemplateParserTestObject::test<7>()
// tests message parsing method on a deprecated message
{
std::string message_skel(
"{\n"
"TestMessageDeprecated High 34 Trusted Unencoded Deprecated\n"
" {\n"
"TestBlock2 Single\n"
" { Test2 S32 }\n"
" }\n"
"}");
LLTemplateTokenizer tokens(message_skel);
LLMessageTemplate * message = LLTemplateParser::parseMessage(tokens);
ensure("deprecated message parsed", message != 0);
ensure_equals("name of message", std::string(message->mName), std::string("TestMessageDeprecated"));
ensure_equals("frequency is High", message->mFrequency, MFT_HIGH);
ensure_equals("trust is trusted", message->mTrust, MT_TRUST);
ensure_equals("message number", message->mMessageNumber, (U32)34);
ensure_equals("message encoding is unencoded", message->mEncoding, ME_UNENCODED);
ensure_equals("message deprecation is deprecated", message->mDeprecation, MD_DEPRECATED);
delete message;
}
template<> template<> void LLMessageTemplateParserTestObject::test<8>()
// tests message parsing on RezMultipleAttachmentsFromInv, a possibly-faulty message
{
std::string message_skel(
"{\n\
RezMultipleAttachmentsFromInv Low 452 NotTrusted Zerocoded\n\
{\n\
AgentData Single\n\
{ AgentID LLUUID }\n\
{ SessionID LLUUID }\n\
} \n\
{\n\
HeaderData Single\n\
{ CompoundMsgID LLUUID } // All messages a single \"compound msg\" must have the same id\n\
{ TotalObjects U8 }\n\
{ FirstDetachAll BOOL }\n\
}\n\
{\n\
ObjectData Variable // 1 to 4 of these per packet\n\
{ ItemID LLUUID }\n\
{ OwnerID LLUUID }\n\
{ AttachmentPt U8 } // 0 for default\n\
{ ItemFlags U32 }\n\
{ GroupMask U32 }\n\
{ EveryoneMask U32 }\n\
{ NextOwnerMask U32 }\n\
{ Name Variable 1 }\n\
{ Description Variable 1 }\n\
}\n\
}\n\
");
LLTemplateTokenizer tokens(message_skel);
LLMessageTemplate * message = LLTemplateParser::parseMessage(tokens);
ensure("RezMultipleAttachmentsFromInv message parsed", message != 0);
ensure_equals("name of message", message->mName, prehash("RezMultipleAttachmentsFromInv"));
ensure_equals("frequency is low", message->mFrequency, MFT_LOW);
ensure_equals("trust is not trusted", message->mTrust, MT_NOTRUST);
ensure_equals("message number", message->mMessageNumber, (U32)((255 << 24) | (255 << 16) | 452));
ensure_equals("message encoding is zerocoded", message->mEncoding, ME_ZEROCODED);
ensure_block_attributes(
"RMAFI", message, "AgentData", MBT_SINGLE, 1, 16+16);
LLMessageBlock * block = message->getBlock(prehash("AgentData"));
ensure_variable_attributes("RMAFI",
block, "AgentID", MVT_LLUUID, 16);
ensure_variable_attributes("RMAFI",
block, "SessionID", MVT_LLUUID, 16);
ensure_block_attributes(
"RMAFI", message, "HeaderData", MBT_SINGLE, 1, 16+1+1);
block = message->getBlock(prehash("HeaderData"));
ensure_variable_attributes(
"RMAFI", block, "CompoundMsgID", MVT_LLUUID, 16);
ensure_variable_attributes(
"RMAFI", block, "TotalObjects", MVT_U8, 1);
ensure_variable_attributes(
"RMAFI", block, "FirstDetachAll", MVT_BOOL, 1);
ensure_block_attributes(
"RMAFI", message, "ObjectData", MBT_VARIABLE, 1, -1);
block = message->getBlock(prehash("ObjectData"));
ensure_variable_attributes("RMAFI", block, "ItemID", MVT_LLUUID, 16);
ensure_variable_attributes("RMAFI", block, "OwnerID", MVT_LLUUID, 16);
ensure_variable_attributes("RMAFI", block, "AttachmentPt", MVT_U8, 1);
ensure_variable_attributes("RMAFI", block, "ItemFlags", MVT_U32, 4);
ensure_variable_attributes("RMAFI", block, "GroupMask", MVT_U32, 4);
ensure_variable_attributes("RMAFI", block, "EveryoneMask", MVT_U32, 4);
ensure_variable_attributes("RMAFI", block, "NextOwnerMask", MVT_U32, 4);
ensure_variable_attributes("RMAFI", block, "Name", MVT_VARIABLE, 1);
ensure_variable_attributes("RMAFI", block, "Description", MVT_VARIABLE, 1);
delete message;
}
}
+491
View File
@@ -0,0 +1,491 @@
/**
* @file llpermissions_tut.cpp
* @author Adroit
* @date March 2007
* @brief llpermissions test cases.
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include <tut/tut.hpp>
#include "linden_common.h"
#include "lltut.h"
#include "message.h"
#include "llpermissions.h"
namespace tut
{
struct permission
{
};
typedef test_group<permission> permission_t;
typedef permission_t::object permission_object_t;
tut::permission_t tut_permission("permission");
template<> template<>
void permission_object_t::test<1>()
{
LLPermissions permissions;
LLUUID uuid = permissions.getCreator();
LLUUID uuid1 = permissions.getOwner();
LLUUID uuid2 = permissions.getGroup();
LLUUID uuid3 = permissions.getLastOwner();
ensure("LLPermission Get Functions failed", (uuid == LLUUID::null && uuid1 == LLUUID::null &&
uuid2 == LLUUID::null && uuid3 == LLUUID::null));
ensure("LLPermission Get Functions failed", (permissions.getMaskBase() == PERM_ALL && permissions.getMaskOwner() == PERM_ALL &&
permissions.getMaskGroup() == PERM_ALL && permissions.getMaskEveryone() == PERM_ALL && permissions.getMaskNextOwner() == PERM_ALL));
ensure("Ownership functions failed", ((! permissions.isGroupOwned()) && (! permissions.isOwned())));
}
template<> template<>
void permission_object_t::test<2>()
{
LLPermissions permissions;
LLUUID creator("abf0d56b-82e5-47a2-a8ad-74741bb2c29e");
LLUUID owner("68edcf47-ccd7-45b8-9f90-1649d7f12806");
LLUUID lastOwner("5e47a0dc-97bf-44e0-8b40-de06718cee9d");
LLUUID group("9c8eca51-53d5-42a7-bb58-cef070395db8");
permissions.init(creator, owner, lastOwner, group);
ensure_equals("init/getCreator():failed to return the creator ", creator, permissions.getCreator());
ensure_equals("init/getOwner():failed to return the owner ", owner, permissions.getOwner());
ensure_equals("init/getLastOwner():failed to return the group ", lastOwner, permissions.getLastOwner());
ensure_equals("init/getGroup():failed to return the group ", group, permissions.getGroup());
}
template<> template<>
void permission_object_t::test<3>()
{
LLPermissions permissions;
U32 base = PERM_ALL;
U32 owner = PERM_ITEM_UNRESTRICTED; //PERM_ITEM_UNRESTRICTED = PERM_MODIFY | PERM_COPY | PERM_TRANSFER;
U32 group = PERM_TRANSFER | PERM_MOVE | PERM_COPY|PERM_MODIFY;
U32 everyone = PERM_TRANSFER | PERM_MOVE | PERM_MODIFY;
U32 next = PERM_NONE;
U32 fixedbase = base;
U32 fixedowner = PERM_ITEM_UNRESTRICTED; //owner & fixedbase
U32 fixedgroup = PERM_ITEM_UNRESTRICTED; // no PERM_MOVE as owner does not have that perm either
U32 fixedeveryone = PERM_TRANSFER; // no PERM_MOVE. Everyone can never modify.
U32 fixednext = PERM_NONE;
permissions.initMasks(base, owner, everyone, group, next); // will fix perms if not allowed.
ensure_equals("initMasks/getMaskBase():failed to return the MaskBase ", fixedbase, permissions.getMaskBase());
ensure_equals("initMasks/getMaskOwner():failed to return the MaskOwner ", fixedowner, permissions.getMaskOwner());
ensure_equals("initMasks/getMaskEveryone():failed to return the MaskGroup ", fixedgroup, permissions.getMaskGroup());
ensure_equals("initMasks/getMaskEveryone():failed to return the MaskEveryone ", fixedeveryone, permissions.getMaskEveryone());
ensure_equals("initMasks/getMaskNextOwner():failed to return the MaskNext ", fixednext, permissions.getMaskNextOwner());
// explictly set should maintain the values
permissions.setMaskBase(base); //no fixing
ensure_equals("setMaskBase/getMaskBase():failed to return the MaskBase ", base, permissions.getMaskBase());
permissions.setMaskOwner(owner);
ensure_equals("setMaskOwner/getMaskOwner():failed to return the MaskOwner ", owner, permissions.getMaskOwner());
permissions.setMaskEveryone(everyone);
ensure_equals("setMaskEveryone/getMaskEveryone():failed to return the MaskEveryone ", everyone, permissions.getMaskEveryone());
permissions.setMaskGroup(group);
ensure_equals("setMaskGroup/getMaskEveryone():failed to return the MaskGroup ", group, permissions.getMaskGroup());
permissions.setMaskNext(next);
ensure_equals("setMaskNext/getMaskNextOwner():failed to return the MaskNext ", next, permissions.getMaskNextOwner());
// further tests can be added to ensure perms for owner/group/everyone etc. get properly fixed.
// code however suggests that there is no explict check if the perms are correct and the user of this
// class is expected to know how to use them correctly. skipping further test cases for now for various
// perm combinations.
}
template<> template<>
void permission_object_t::test<4>()
{
LLPermissions perm,perm1;
LLUUID creator("abf0d56b-82e5-47a2-a8ad-74741bb2c29e");
LLUUID owner("68edcf47-ccd7-45b8-9f90-1649d7f12806");
LLUUID lastOwner("5e47a0dc-97bf-44e0-8b40-de06718cee9d");
LLUUID group("9c8eca51-53d5-42a7-bb58-cef070395db8");
perm1.init(creator,owner,lastOwner,group);
perm.set(perm1);
ensure("set():failed to set ", (creator == perm.getCreator()) && (owner == perm.getOwner())&&
(lastOwner == perm.getLastOwner())&& (group == perm.getGroup()));
}
template<> template<>
void permission_object_t::test<5>()
{
LLPermissions perm,perm1;
LLUUID creator("abf0d56b-82e5-47a2-a8ad-74741bb2c29e");
LLUUID owner("68edcf47-ccd7-45b8-9f90-1649d7f12806");
LLUUID lastOwner("5e47a0dc-97bf-44e0-8b40-de06718cee9d");
LLUUID group("9c8eca51-53d5-42a7-bb58-cef070395db8");
perm1.init(creator,owner,lastOwner,group);
U32 base = PERM_TRANSFER;
U32 ownerp = PERM_TRANSFER;
U32 groupp = PERM_TRANSFER;
U32 everyone = PERM_TRANSFER;
U32 next = PERM_NONE;
perm1.initMasks(base, ownerp, everyone, groupp, next);
base = PERM_ALL;
ownerp = PERM_ITEM_UNRESTRICTED; //PERM_ITEM_UNRESTRICTED = PERM_MODIFY | PERM_COPY | PERM_TRANSFER;
groupp = PERM_TRANSFER | PERM_COPY|PERM_MODIFY;
everyone = PERM_TRANSFER;
next = PERM_NONE;
perm.init(creator,owner,lastOwner,group);
perm.initMasks(base, ownerp, everyone, groupp, next);
// restrict permissions by accumulation
perm.accumulate(perm1);
U32 fixedbase = PERM_TRANSFER | PERM_MOVE;
U32 fixedowner = PERM_TRANSFER;
U32 fixedgroup = PERM_TRANSFER;
U32 fixedeveryone = PERM_TRANSFER;
U32 fixednext = PERM_NONE;
ensure_equals("accumulate failed ", fixedbase, perm.getMaskBase());
ensure_equals("accumulate failed ", fixedowner, perm.getMaskOwner());
ensure_equals("accumulate failed ", fixedgroup, perm.getMaskGroup());
ensure_equals("accumulate failed ", fixedeveryone, perm.getMaskEveryone());
ensure_equals("accumulate failed ", fixednext, perm.getMaskNextOwner());
}
template<> template<>
void permission_object_t::test<6>()
{
LLPermissions perm;
LLUUID creator("abf0d56b-82e5-47a2-a8ad-74741bb2c29e");
LLUUID owner("68edcf47-ccd7-45b8-9f90-1649d7f12806");
LLUUID lastOwner("5e47a0dc-97bf-44e0-8b40-de06718cee9d");
LLUUID group("9c8eca51-53d5-42a7-bb58-cef070395db8");
perm.init(creator,owner,lastOwner,group);
ensure_equals("getSafeOwner:failed ", owner,perm.getSafeOwner());
///NULL Owner
perm.init(creator,LLUUID::null,lastOwner,group);
ensure_equals("getSafeOwner:failed ", group, perm.getSafeOwner());
}
template<> template<>
void permission_object_t::test<7>()
{
LLPermissions perm1;
LLUUID uuid;
bool is_group_owned = false;
ensure("1:getOwnership:failed ", ! perm1.getOwnership(uuid,is_group_owned));
LLPermissions perm;
LLUUID creator("abf0d56b-82e5-47a2-a8ad-74741bb2c29e");
LLUUID owner("68edcf47-ccd7-45b8-9f90-1649d7f12806");
LLUUID lastOwner("5e47a0dc-97bf-44e0-8b40-de06718cee9d");
LLUUID group("9c8eca51-53d5-42a7-bb58-cef070395db8");
perm.init(creator,owner,lastOwner,group);
perm.getOwnership(uuid,is_group_owned);
ensure("2:getOwnership:failed ", ((uuid == owner) && (! is_group_owned)));
perm.init(creator,LLUUID::null,lastOwner,group);
perm.getOwnership(uuid,is_group_owned);
ensure("3:getOwnership:failed ", ((uuid == group) && is_group_owned));
}
template<> template<>
void permission_object_t::test<8>()
{
LLPermissions perm,perm1;
LLUUID creator("abf0d56b-82e5-47a2-a8ad-74741bb2c29e");
LLUUID owner("68edcf47-ccd7-45b8-9f90-1649d7f12806");
LLUUID lastOwner("5e47a0dc-97bf-44e0-8b40-de06718cee9d");
LLUUID group("9c8eca51-53d5-42a7-bb58-cef070395db8");
perm.init(creator,owner,lastOwner,group);
perm1.init(creator,owner,lastOwner,group);
ensure_equals("getCRC32:failed ", perm.getCRC32(),perm1.getCRC32());
}
template<> template<>
void permission_object_t::test<9>()
{
LLPermissions perm;
LLUUID agent("abf0d56b-82e5-47a2-a8ad-74741bb2c29e");
LLUUID owner("68edcf47-ccd7-45b8-9f90-1649d7f12806");
LLUUID group("9c8eca51-53d5-42a7-bb58-cef070395db8");
bool is_atomic = true;
ensure("setOwnerAndGroup():failed ", perm.setOwnerAndGroup(agent,owner,group,is_atomic));
LLUUID owner2("68edcf47-ccd7-45b8-9f90-1649d7f12807");
LLUUID group2("9c8eca51-53d5-42a7-bb58-cef070395db9");
// cant change - agent need to be current owner
ensure("setOwnerAndGroup():failed ", ! perm.setOwnerAndGroup(agent,owner2,group2,is_atomic));
// should be able to change - agent and owner same as current owner
ensure("setOwnerAndGroup():failed ", perm.setOwnerAndGroup(owner,owner,group2,is_atomic));
}
template<> template<>
void permission_object_t::test<10>()
{
LLPermissions perm;
LLUUID agent;
LLUUID group("9c8eca51-53d5-42a7-bb58-cef070395db8");
ensure("deedToGroup():failed ", perm.deedToGroup(agent,group));
}
template<> template<>
void permission_object_t::test<11>()
{
LLPermissions perm;
LLUUID agent;
bool set = true;
U32 bits = PERM_TRANSFER | PERM_MODIFY;
ensure("setBaseBits():failed ", perm.setBaseBits(agent, set, bits));
ensure("setOwnerBits():failed ", perm.setOwnerBits(agent, set, bits));
LLUUID agent1("9c8eca51-53d5-42a7-bb58-cef070395db8");
ensure("setBaseBits():failed ", ! perm.setBaseBits(agent1, set, bits));
ensure("setOwnerBits():failed ", ! perm.setOwnerBits(agent1, set, bits));
}
template<> template<>
void permission_object_t::test<12>()
{
LLPermissions perm;
LLUUID agent;
LLUUID group("9c8eca51-53d5-42a7-bb58-cef070395db8");
bool set = true;
U32 bits = 10;
ensure("setGroupBits():failed ", perm.setGroupBits(agent,group, set, bits));
ensure("setEveryoneBits():failed ", perm.setEveryoneBits(agent,group, set, bits));
ensure("setNextOwnerBits():failed ", perm.setNextOwnerBits(agent,group, set, bits));
LLUUID agent1("abf0d56b-82e5-47a2-a8ad-74741bb2c29e");
ensure("setGroupBits():failed ", ! perm.setGroupBits(agent1,group, set, bits));
ensure("setEveryoneBits():failed ", ! perm.setEveryoneBits(agent1,group, set, bits));
ensure("setNextOwnerBits():failed ", ! perm.setNextOwnerBits(agent1,group, set, bits));
}
template<> template<>
void permission_object_t::test<13>()
{
LLPermissions perm;
LLUUID agent;
LLUUID group("9c8eca51-53d5-42a7-bb58-cef070395db8");
U32 bits = 10;
ensure("allowOperationBy():failed ", perm.allowOperationBy(bits,agent,group));
LLUUID agent1("abf0d56b-82e5-47a2-a8ad-74741bb2c29e");
LLUUID creator("abf0d56b-82e5-47a2-a8ad-74741bb2c29e");
LLUUID owner("68edcf47-ccd7-45b8-9f90-1649d7f12806");
LLUUID lastOwner("5e47a0dc-97bf-44e0-8b40-de06718cee9d");
perm.init(creator,owner,lastOwner,group);
ensure("allowOperationBy():failed ", perm.allowOperationBy(bits,agent1,group));
}
template<> template<>
void permission_object_t::test<14>()
{
LLPermissions perm;
LLUUID creator("abf0d56b-82e5-47a2-a8ad-74741bb2c29e");
LLUUID owner;
LLUUID lastOwner("5e47a0dc-97bf-44e0-8b40-de06718cee9d");
LLUUID group("9c8eca51-53d5-42a7-bb58-cef070395db8");
perm.init(creator,owner,lastOwner,group);
LLUUID agent;
ensure("1:allowModifyBy():failed ", perm.allowModifyBy(agent));
ensure("2:allowModifyBy():failed ", perm.allowModifyBy(agent,group));
LLUUID agent1("9c8eca51-53d5-42a7-bb58-cef070395db8");
ensure("3:allowModifyBy():failed ", perm.allowModifyBy(agent1));
ensure("4:allowModifyBy():failed ", perm.allowModifyBy(agent1,group));
}
template<> template<>
void permission_object_t::test<15>()
{
LLPermissions perm;
LLUUID creator("abf0d56b-82e5-47a2-a8ad-74741bb2c29e");
LLUUID owner;
LLUUID lastOwner("5e47a0dc-97bf-44e0-8b40-de06718cee9d");
LLUUID group("9c8eca51-53d5-42a7-bb58-cef070395db8");
perm.init(creator,owner,lastOwner,group);
LLUUID agent;
ensure("1:allowCopyBy():failed ", perm.allowModifyBy(agent));
ensure("2:allowCopyBy():failed ", perm.allowModifyBy(agent,group));
LLUUID agent1("9c8eca51-53d5-42a7-bb58-cef070395db8");
ensure("3:allowCopyBy():failed ", perm.allowCopyBy(agent1));
ensure("4:allowCopyBy():failed ", perm.allowCopyBy(agent1,group));
}
template<> template<>
void permission_object_t::test<16>()
{
LLPermissions perm;
LLUUID creator("abf0d56b-82e5-47a2-a8ad-74741bb2c29e");
LLUUID owner;
LLUUID lastOwner("5e47a0dc-97bf-44e0-8b40-de06718cee9d");
LLUUID group("9c8eca51-53d5-42a7-bb58-cef070395db8");
perm.init(creator,owner,lastOwner,group);
LLUUID agent;
ensure("1:allowMoveBy():failed ", perm.allowMoveBy(agent));
ensure("2:allowMoveBy():failed ", perm.allowMoveBy(agent,group));
LLUUID agent1("9c8eca51-53d5-42a7-bb58-cef070395db8");
ensure("3:allowMoveBy():failed ", perm.allowMoveBy(agent1));
ensure("4:allowMoveBy():failed ", perm.allowMoveBy(agent1,group));
}
template<> template<>
void permission_object_t::test<17>()
{
LLPermissions perm;
LLUUID creator("abf0d56b-82e5-47a2-a8ad-74741bb2c29e");
LLUUID owner;
LLUUID lastOwner("5e47a0dc-97bf-44e0-8b40-de06718cee9d");
LLUUID group("9c8eca51-53d5-42a7-bb58-cef070395db8");
LLUUID agent;
ensure("1:allowMoveBy():failed ", perm.allowTransferTo(agent));
perm.init(creator,owner,lastOwner,group);
ensure("2:allowMoveBy():failed ", perm.allowTransferTo(agent));
}
template<> template<>
void permission_object_t::test<18>()
{
LLPermissions perm,perm1;
ensure_equals("1:Operator==:failed ", perm, perm1);
LLUUID creator("abf0d56b-82e5-47a2-a8ad-74741bb2c29e");
LLUUID owner("68edcf47-ccd7-45b8-9f90-1649d7f12806");
LLUUID lastOwner("5e47a0dc-97bf-44e0-8b40-de06718cee9d");
LLUUID group("9c8eca51-53d5-42a7-bb58-cef070395db8");
perm.init(creator,owner,lastOwner,group);
perm = perm1;
ensure_equals("2:Operator==:failed ", perm, perm1);
}
template<> template<>
void permission_object_t::test<19>()
{
LLPermissions perm,perm1;
LLUUID creator("abf0d56b-82e5-47a2-a8ad-74741bb2c29e");
LLUUID owner("68edcf47-ccd7-45b8-9f90-1649d7f12806");
LLUUID lastOwner("5e47a0dc-97bf-44e0-8b40-de06718cee9d");
LLUUID group("9c8eca51-53d5-42a7-bb58-cef070395db8");
perm.init(creator,owner,lastOwner,group);
ensure_not_equals("2:Operator==:failed ", perm, perm1);
}
template<> template<>
void permission_object_t::test<20>()
{
LLPermissions perm,perm1;
LLUUID creator("abf0d56b-82e5-47a2-a8ad-74741bb2c29e");
LLUUID owner("68edcf47-ccd7-45b8-9f90-1649d7f12806");
LLUUID lastOwner("5e47a0dc-97bf-44e0-8b40-de06718cee9d");
LLUUID group("9c8eca51-53d5-42a7-bb58-cef070395db8");
perm.init(creator,owner,lastOwner,group);
U32 base = PERM_TRANSFER | PERM_COPY;
U32 ownerp = PERM_TRANSFER;
U32 groupp = PERM_TRANSFER;
U32 everyone = PERM_TRANSFER;
U32 next = PERM_NONE;
perm.initMasks(base, ownerp, everyone, groupp, next);
std::ostringstream ostream;
perm.exportLegacyStream(ostream);
std::istringstream istream(ostream.str());
perm1.importLegacyStream(istream);
ensure_equals("exportStream()/importStream():failed to export and import the data ", perm1, perm);
}
template<> template<>
void permission_object_t::test<21>()
{
LLPermissions perm,perm1;
LLUUID creator("abf0d56b-82e5-47a2-a8ad-74741bb2c29e");
LLUUID owner("68edcf47-ccd7-45b8-9f90-1649d7f12806");
LLUUID lastOwner("5e47a0dc-97bf-44e0-8b40-de06718cee9d");
LLUUID group("9c8eca51-53d5-42a7-bb58-cef070395db8");
perm.init(creator,owner,lastOwner,group);
std::ostringstream stream1, stream2;
stream1 << perm;
perm1.init(creator,owner,lastOwner,group);
stream2 << perm1;
ensure_equals("1:operator << failed", stream1.str(), stream2.str());
}
template<> template<>
void permission_object_t::test<22>()
{
LLPermissions perm,perm1;
LLUUID creator("abf0d56b-82e5-47a2-a8ad-74741bb2c29e");
LLUUID owner("68edcf47-ccd7-45b8-9f90-1649d7f12806");
LLUUID lastOwner("5e47a0dc-97bf-44e0-8b40-de06718cee9d");
LLUUID group("9c8eca51-53d5-42a7-bb58-cef070395db8");
perm.init(creator,owner,lastOwner,group);
U32 base = PERM_TRANSFER | PERM_COPY;
U32 ownerp = PERM_TRANSFER;
U32 groupp = PERM_TRANSFER;
U32 everyone = PERM_TRANSFER;
U32 next = PERM_NONE;
perm.initMasks(base, ownerp, everyone, groupp, next);
LLSD sd = ll_create_sd_from_permissions(perm);
perm1 = ll_permissions_from_sd(sd);
ensure_equals("ll_permissions_from_sd() and ll_create_sd_from_permissions()functions failed", perm, perm1);
}
template<> template<>
void permission_object_t::test<23>()
{
LLAggregatePermissions AggrPermission;
LLAggregatePermissions AggrPermission1;
ensure_equals("getU8() function failed", AggrPermission.getU8(), 0);
ensure("isEmpty() function failed", AggrPermission.isEmpty());
AggrPermission.getValue(PERM_TRANSFER);
ensure_equals("getValue() function failed", AggrPermission.getValue(PERM_TRANSFER), 0x00);
AggrPermission.aggregate(PERM_ITEM_UNRESTRICTED);
ensure("aggregate() function failed", ! AggrPermission.isEmpty());
AggrPermission1.aggregate(AggrPermission);
ensure("aggregate() function failed", ! AggrPermission1.isEmpty());
std::ostringstream stream1;
stream1 << AggrPermission;
ensure_equals("operator<< failed", stream1.str(), "{PI_COPY=All, PI_MODIFY=All, PI_TRANSFER=All}");
}
}
+183
View File
@@ -0,0 +1,183 @@
/**
* @file llpipeutil.cpp
* @date 2006-05-18
* @brief Utility pipe fittings for injecting and extracting strings
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llpipeutil.h"
#include <stdlib.h>
#include <sstream>
#include "llbufferstream.h"
#include "lldefs.h"
#include "llframetimer.h"
#include "llpumpio.h"
#include "llrand.h"
#include "lltimer.h"
F32 pump_loop(LLPumpIO* pump, F32 seconds)
{
LLTimer timer;
timer.setTimerExpirySec(seconds);
while(!timer.hasExpired())
{
LLFrameTimer::updateFrameTime();
pump->pump();
pump->callback();
}
return timer.getElapsedTimeF32();
}
//virtual
LLIOPipe::EStatus LLPipeStringInjector::process_impl(
const LLChannelDescriptors& channels,
buffer_ptr_t& buffer,
bool& eos,
LLSD& context,
LLPumpIO* pump)
{
buffer->append(channels.out(), (U8*) mString.data(), static_cast<S32>(mString.size()));
eos = true;
return STATUS_DONE;
}
LLIOPipe::EStatus LLPipeStringExtractor::process_impl(
const LLChannelDescriptors& channels,
buffer_ptr_t& buffer,
bool& eos,
LLSD& context,
LLPumpIO* pump)
{
if(!eos) return STATUS_BREAK;
if(!pump || !buffer) return STATUS_PRECONDITION_NOT_MET;
LLBufferStream istr(channels, buffer.get());
std::ostringstream ostr;
while (istr.good())
{
char buf[1024]; /* Flawfinder: ignore */
istr.read(buf, sizeof(buf)); /* Flawfinder: ignore */
ostr.write(buf, istr.gcount());
}
mString = ostr.str();
mDone = true;
return STATUS_DONE;
}
// virtual
LLIOPipe::EStatus LLIOFuzz::process_impl(
const LLChannelDescriptors& channels,
buffer_ptr_t& buffer,
bool& eos,
LLSD& context,
LLPumpIO* pump)
{
while(mByteCount)
{
std::vector<U8> data;
data.reserve(10000);
int size = llmin(10000, mByteCount);
std::generate_n(
std::back_insert_iterator< std::vector<U8> >(data),
size,
rand);
buffer->append(channels.out(), &data[0], size);
mByteCount -= size;
}
return STATUS_OK;
}
struct random_ascii_generator
{
random_ascii_generator() {}
U8 operator()()
{
int rv = rand();
rv %= (127 - 32);
rv += 32;
return rv;
}
};
// virtual
LLIOPipe::EStatus LLIOASCIIFuzz::process_impl(
const LLChannelDescriptors& channels,
buffer_ptr_t& buffer,
bool& eos,
LLSD& context,
LLPumpIO* pump)
{
while(mByteCount)
{
std::vector<U8> data;
data.reserve(10000);
int size = llmin(10000, mByteCount);
std::generate_n(
std::back_insert_iterator< std::vector<U8> >(data),
size,
random_ascii_generator());
buffer->append(channels.out(), &data[0], size);
mByteCount -= size;
}
return STATUS_OK;
}
// virtual
LLIOPipe::EStatus LLIONull::process_impl(
const LLChannelDescriptors& channels,
buffer_ptr_t& buffer,
bool& eos,
LLSD& context,
LLPumpIO* pump)
{
return STATUS_OK;
}
// virtual
LLIOPipe::EStatus LLIOSleeper::process_impl(
const LLChannelDescriptors& channels,
buffer_ptr_t& buffer,
bool& eos,
LLSD& context,
LLPumpIO* pump)
{
if(!mRespond)
{
LL_DEBUGS() << "LLIOSleeper::process_impl() sleeping." << LL_ENDL;
mRespond = true;
static const F64 SLEEP_TIME = 2.0;
pump->sleepChain(SLEEP_TIME);
return STATUS_BREAK;
}
LL_DEBUGS() << "LLIOSleeper::process_impl() responding." << LL_ENDL;
LLBufferStream ostr(channels, buffer.get());
ostr << "huh? sorry, I was sleeping." << std::endl;
return STATUS_DONE;
}
+163
View File
@@ -0,0 +1,163 @@
/**
* @file llpipeutil.h
* @date 2006-05-18
* @brief Utility pipe fittings for injecting and extracting strings
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLPIPEUTIL_H
#define LL_LLPIPEUTIL_H
#include "lliopipe.h"
/**
* @brief Simple function which pumps for the specified time.
*/
F32 pump_loop(LLPumpIO* pump, F32 seconds);
/**
* @brief Simple class which writes a string and then marks the stream
* as done.
*/
class LLPipeStringInjector : public LLIOPipe
{
public:
LLPipeStringInjector(const std::string& string)
: mString(string)
{ }
protected:
virtual EStatus process_impl(
const LLChannelDescriptors& channels,
buffer_ptr_t& buffer,
bool& eos,
LLSD& context,
LLPumpIO* pump);
private:
std::string mString;
};
class LLPipeStringExtractor : public LLIOPipe
{
public:
LLPipeStringExtractor() : mDone(false) { }
bool done() { return mDone; }
std::string string() { return mString; }
protected:
// LLIOPipe API implementation.
virtual EStatus process_impl(
const LLChannelDescriptors& channels,
LLIOPipe::buffer_ptr_t& buffer,
bool& eos,
LLSD& context,
LLPumpIO* pump);
private:
bool mDone;
std::string mString;
};
/**
* @brief Generate a specified number of bytes of random data
*/
class LLIOFuzz : public LLIOPipe
{
public:
LLIOFuzz(int byte_count) : mByteCount(byte_count) {}
protected:
virtual EStatus process_impl(
const LLChannelDescriptors& channels,
buffer_ptr_t& buffer,
bool& eos,
LLSD& context,
LLPumpIO* pump);
private:
int mByteCount;
};
/**
* @brief Generate some ascii fuz
*/
class LLIOASCIIFuzz : public LLIOPipe
{
public:
LLIOASCIIFuzz(int byte_count) : mByteCount(byte_count) {}
protected:
virtual EStatus process_impl(
const LLChannelDescriptors& channels,
buffer_ptr_t& buffer,
bool& eos,
LLSD& context,
LLPumpIO* pump);
private:
int mByteCount;
};
/**
* @brief Pipe that does nothing except return STATUS_OK
*/
class LLIONull : public LLIOPipe
{
public:
LLIONull() {}
protected:
virtual EStatus process_impl(
const LLChannelDescriptors& channels,
buffer_ptr_t& buffer,
bool& eos,
LLSD& context,
LLPumpIO* pump);
};
/**
* @brief Pipe that sleeps, and then responds later.
*/
class LLIOSleeper : public LLIOPipe
{
public:
LLIOSleeper() : mRespond(false) {}
protected:
virtual EStatus process_impl(
const LLChannelDescriptors& channels,
buffer_ptr_t& buffer,
bool& eos,
LLSD& context,
LLPumpIO* pump);
private:
bool mRespond;
};
#endif // LL_LLPIPEUTIL_H
+194
View File
@@ -0,0 +1,194 @@
/**
* @file LLSaleInfo_tut.cpp
* @author Adroit
* @date 2007-03
* @brief Test cases of llsaleinfo.h
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include <tut/tut.hpp>
#include "linden_common.h"
#include "lltut.h"
#include "llsaleinfo.h"
namespace tut
{
struct llsaleinfo_tut
{
};
typedef test_group<llsaleinfo_tut> llsaleinfo_tut_t;
typedef llsaleinfo_tut_t::object llsaleinfo_test_t;
tut::llsaleinfo_tut_t tut_llsaleinfo_test("llsaleinfo");
template<> template<>
void llsaleinfo_test_t::test<1>()
{
//test case for getSaleType(), getSalePrice(), getCRC32() fn.
//test case for setSaleType(), setSalePrice() fn.
S32 sale_price = 10000;
LLSaleInfo llsaleinfo(LLSaleInfo::FS_COPY, sale_price);
const char* sale= "copy";
LLSD llsd_obj1 = ll_create_sd_from_sale_info(llsaleinfo);
LLSaleInfo saleinfo1 = ll_sale_info_from_sd(llsd_obj1);
ensure("1. The getSaleType() fn failed", LLSaleInfo::FS_COPY == llsaleinfo.getSaleType());
ensure("2. LLSaleInfo::isForSale() fn failed", true == llsaleinfo.isForSale());
ensure("3. The getSalePrice() fn failed", sale_price == llsaleinfo.getSalePrice());
ensure("4. The getCRC32() fn failed", 235833404 == llsaleinfo.getCRC32());
ensure("5. LLSaleInfo::lookup(const char* name) fn failed", LLSaleInfo::FS_COPY == llsaleinfo.lookup(sale));
ensure_equals("6. ll_create_sd_from_sale_info() fn failed", llsaleinfo.getSalePrice(), saleinfo1.getSalePrice());
ensure_equals("7. ll_create_sd_from_sale_info() fn failed", llsaleinfo.getSaleType(), saleinfo1.getSaleType());
llsaleinfo.setSalePrice(10000000);
llsaleinfo.setSaleType(LLSaleInfo::FS_ORIGINAL);
sale = "cntn";
llsd_obj1 = ll_create_sd_from_sale_info(llsaleinfo);
saleinfo1 = ll_sale_info_from_sd(llsd_obj1);
ensure("8. The getSaleType() and setSaleType() fn failed", LLSaleInfo::FS_ORIGINAL == llsaleinfo.getSaleType());
ensure("9. LLSaleInfo::isForSale() fn failed", true == llsaleinfo.isForSale());
ensure("10. The getSalePrice() fn failed", 10000000 == llsaleinfo.getSalePrice());
ensure("11. The getCRC32() fn failed", 127911702 == llsaleinfo.getCRC32());
ensure("12. LLSaleInfo::lookup(const char* name) fn failed", LLSaleInfo::FS_CONTENTS == llsaleinfo.lookup(sale));
ensure_equals("13. ll_create_sd_from_sale_info() fn failed", llsaleinfo.getSalePrice(), saleinfo1.getSalePrice());
ensure_equals("14. ll_create_sd_from_sale_info() fn failed", llsaleinfo.getSaleType(), saleinfo1.getSaleType());
llsaleinfo.setSalePrice(55000550);
llsaleinfo.setSaleType(LLSaleInfo::FS_CONTENTS);
sale = "orig";
llsd_obj1 = ll_create_sd_from_sale_info(llsaleinfo);
saleinfo1 = ll_sale_info_from_sd(llsd_obj1);
ensure("15. The getSaleType() and setSaleType() fn failed", LLSaleInfo::FS_CONTENTS == llsaleinfo.getSaleType());
ensure("16. LLSaleInfo::isForSale() fn failed", true == llsaleinfo.isForSale());
ensure("17. The getSalePrice() fn failed", 55000550 == llsaleinfo.getSalePrice());
ensure("18. The getCRC32() fn failed", 408735656 == llsaleinfo.getCRC32());
ensure("19. LLSaleInfo::lookup(const char* name) fn failed", LLSaleInfo::FS_ORIGINAL == llsaleinfo.lookup(sale));
ensure_equals("20. ll_create_sd_from_sale_info() fn failed", llsaleinfo.getSalePrice(), saleinfo1.getSalePrice());
ensure_equals("21. ll_create_sd_from_sale_info() fn failed", llsaleinfo.getSaleType(), saleinfo1.getSaleType());
llsaleinfo.setSalePrice(-6432);
llsaleinfo.setSaleType(LLSaleInfo::FS_NOT);
sale = "not";
llsd_obj1 = ll_create_sd_from_sale_info(llsaleinfo);
saleinfo1 = ll_sale_info_from_sd(llsd_obj1);
ensure("22. The getSaleType() and setSaleType() fn failed", LLSaleInfo::FS_NOT == llsaleinfo.getSaleType());
ensure("23. LLSaleInfo::isForSale() fn failed", false == llsaleinfo.isForSale());
ensure("24. The getSalePrice() fn failed", 0 == llsaleinfo.getSalePrice());
ensure("25. The getCRC32() fn failed", 0 == llsaleinfo.getCRC32());
ensure("26. LLSaleInfo::lookup(const char* name) fn failed", LLSaleInfo::FS_NOT == llsaleinfo.lookup(sale));
ensure_equals("27. ll_create_sd_from_sale_info() fn failed", llsaleinfo.getSalePrice(), saleinfo1.getSalePrice());
ensure_equals("28. ll_create_sd_from_sale_info() fn failed", llsaleinfo.getSaleType(), saleinfo1.getSaleType());
}
template<> template<>
void llsaleinfo_test_t::test<2>()
{
S32 sale_price = 525452;
LLSaleInfo llsaleinfo(LLSaleInfo::FS_ORIGINAL, sale_price);
std::ostringstream ostream;
llsaleinfo.exportLegacyStream(ostream);
std::istringstream istream(ostream.str());
LLSaleInfo llsaleinfo1;
U32 perm_mask = 0;
bool has_perm_mask = false;
llsaleinfo1.importLegacyStream(istream, has_perm_mask, perm_mask);
ensure("importStream() fn failed ",
llsaleinfo.getSalePrice() == llsaleinfo1.getSalePrice() &&
llsaleinfo.getSaleType() == llsaleinfo1.getSaleType());
}
template<> template<>
void llsaleinfo_test_t::test<3>()
{
S32 sale_price = 99000;
LLSaleInfo saleinfo(LLSaleInfo::FS_ORIGINAL, sale_price);
LLSD sd_result = saleinfo.asLLSD();
U32 perm_mask = 0 ;
bool has_perm_mask = false;
LLSaleInfo saleinfo1;
saleinfo1.fromLLSD( sd_result, has_perm_mask, perm_mask);
ensure_equals("asLLSD and fromLLSD failed", saleinfo.getSalePrice(), saleinfo1.getSalePrice());
ensure_equals("asLLSD and fromLLSD failed", saleinfo.getSaleType(), saleinfo1.getSaleType());
}
//static EForSale lookup(const char* name) fn test
template<> template<>
void llsaleinfo_test_t::test<4>()
{
S32 sale_price = 233223;
LLSaleInfo::EForSale ret_type = LLSaleInfo::lookup("orig");
ensure_equals("lookup(const char* name) fn failed", ret_type, LLSaleInfo::FS_ORIGINAL);
LLSaleInfo saleinfo(LLSaleInfo::FS_COPY, sale_price);
const char* result = LLSaleInfo::lookup(LLSaleInfo::FS_COPY);
ensure("char* lookup(EForSale type) fn failed", 0 == strcmp("copy", result));
}
//void LLSaleInfo::accumulate(const LLSaleInfo& sale_info) fn test
template<> template<>
void llsaleinfo_test_t::test<5>()
{
S32 sale_price = 20;
LLSaleInfo saleinfo(LLSaleInfo::FS_COPY, sale_price);
LLSaleInfo saleinfo1(LLSaleInfo::FS_COPY, sale_price);
saleinfo1.accumulate(saleinfo);
ensure_equals("LLSaleInfo::accumulate(const LLSaleInfo& sale_info) fn failed", saleinfo1.getSalePrice(), 40);
}
// test cases of bool operator==(const LLSaleInfo &rhs) fn
// test case of bool operator!=(const LLSaleInfo &rhs) fn
template<> template<>
void llsaleinfo_test_t::test<6>()
{
S32 sale_price = 55000;
LLSaleInfo saleinfo(LLSaleInfo::FS_ORIGINAL, sale_price);
LLSaleInfo saleinfoequal(LLSaleInfo::FS_ORIGINAL, sale_price);
LLSaleInfo saleinfonotequal(LLSaleInfo::FS_ORIGINAL, sale_price*2);
ensure("operator == fn. failed", true == (saleinfo == saleinfoequal));
ensure("operator != fn. failed", true == (saleinfo != saleinfonotequal));
}
template<> template<>
void llsaleinfo_test_t::test<7>()
{
//TBD: void LLSaleInfo::packMessage(LLMessageSystem* msg) const
//TBD: void LLSaleInfo::unpackMessage(LLMessageSystem* msg, const char* block)
//TBD: void LLSaleInfo::unpackMultiMessage(LLMessageSystem* msg, const char* block, S32 block_num)
}
}
+830
View File
@@ -0,0 +1,830 @@
/**
* @file llsd_new_tut.cpp
* @date February 2006
* @brief LLSD unit tests
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2006-2011, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#define LLSD_DEBUG_INFO
#include <tut/tut.hpp>
#include "linden_common.h"
#include "lltut.h"
#include "llsdtraits.h"
#include "llstring.h"
using std::fpclassify;
namespace tut
{
class SDCleanupCheck
{
private:
U32 mOutstandingAtStart;
public:
SDCleanupCheck() : mOutstandingAtStart(llsd::outstandingCount()) { }
~SDCleanupCheck()
{
ensure_equals("SDCleanupCheck",
llsd::outstandingCount(), mOutstandingAtStart);
}
};
class SDAllocationCheck : public SDCleanupCheck
{
private:
std::string mMessage;
U32 mExpectedAllocations;
U32 mAllocationAtStart;
public:
SDAllocationCheck(const std::string& message, int expectedAllocations)
: mMessage(message),
mExpectedAllocations(expectedAllocations),
mAllocationAtStart(llsd::allocationCount())
{ }
~SDAllocationCheck()
{
ensure_equals(mMessage + " SDAllocationCheck",
llsd::allocationCount() - mAllocationAtStart,
mExpectedAllocations);
}
};
struct SDTestData {
template<class T>
static void ensureTypeAndValue(const char* msg, const LLSD& actual,
T expectedValue)
{
LLSDTraits<T> traits;
std::string s(msg);
ensure( s + " type", traits.checkType(actual));
ensure_equals( s + " value", traits.get(actual), expectedValue);
}
template<class T>
static void ensureTypeAndRefValue(const char* msg, const LLSD& actual,
const T& expectedValue)
{
LLSDTraits<const T&> traits;
std::string s(msg);
ensure( s + " type", traits.checkType(actual));
ensure_equals( s + " value", traits.get(actual), expectedValue);
}
};
typedef test_group<SDTestData> SDTestGroup;
typedef SDTestGroup::object SDTestObject;
SDTestGroup sdTestGroup("LLSD(new)");
// template<> template<>
// void SDTestObject::test<1>()
// // construction and test of undefined
// {
// SDCleanupCheck check;
// LLSD u;
// ensure("is undefined", u.isUndefined());
// }
template<> template<>
void SDTestObject::test<2>()
// setting and fetching scalar types
{
SDCleanupCheck check;
LLSD v;
v = true; ensureTypeAndValue("set true", v, true);
v = false; ensureTypeAndValue("set false", v, false);
v = true; ensureTypeAndValue("set true again", v, true);
v = 42; ensureTypeAndValue("set to 42", v, 42);
v = 0; ensureTypeAndValue("set to zero", v, 0);
v = -12345; ensureTypeAndValue("set to neg", v, -12345);
v = 2000000000; ensureTypeAndValue("set to big", v, 2000000000);
v = 3.14159265359;
ensureTypeAndValue("set to pi", v, 3.14159265359);
ensure_not_equals("isn't float", v.asReal(),
(float)3.14159265359);
v = 6.7e256; ensureTypeAndValue("set to big", v, 6.7e256);
LLUUID nullUUID;
LLUUID newUUID;
newUUID.generate();
v = nullUUID; ensureTypeAndValue("set to null UUID", v, nullUUID);
v = newUUID; ensureTypeAndValue("set to new UUID", v, newUUID);
v = nullUUID; ensureTypeAndValue("set to null again", v, nullUUID);
// strings must be tested with two types of string objects
std::string s = "now is the time";
const char* cs = "for all good zorks";
v = s; ensureTypeAndValue("set to std::string", v, s);
v = cs; ensureTypeAndValue("set to const char*", v, cs);
LLDate epoch;
LLDate aDay("2001-10-22T10:11:12.00Z");
v = epoch; ensureTypeAndValue("set to epoch", v, epoch);
v = aDay; ensureTypeAndValue("set to a day", v, aDay);
LLURI path("http://slurl.com/secondlife/Ambleside/57/104/26/");
v = path; ensureTypeAndValue("set to a uri", v, path);
const char source[] = "once in a blue moon";
std::vector<U8> data;
copy(&source[0], &source[sizeof(source)], back_inserter(data));
v = data; ensureTypeAndRefValue("set to data", v, data);
v.clear();
ensure("reset to undefined", v.type() == LLSD::TypeUndefined);
}
template<> template<>
void SDTestObject::test<3>()
// construction via scalar values
// tests both constructor and initialize forms
{
SDCleanupCheck check;
LLSD b1(true); ensureTypeAndValue("construct boolean", b1, true);
LLSD b2 = true; ensureTypeAndValue("initialize boolean", b2, true);
LLSD i1(42); ensureTypeAndValue("construct int", i1, 42);
LLSD i2 =42; ensureTypeAndValue("initialize int", i2, 42);
LLSD d1(1.2); ensureTypeAndValue("construct double", d1, 1.2);
LLSD d2 = 1.2; ensureTypeAndValue("initialize double", d2, 1.2);
LLUUID newUUID;
newUUID.generate();
LLSD u1(newUUID);
ensureTypeAndValue("construct UUID", u1, newUUID);
LLSD u2 = newUUID;
ensureTypeAndValue("initialize UUID", u2, newUUID);
LLSD ss1(std::string("abc"));
ensureTypeAndValue("construct std::string", ss1, "abc");
LLSD ss2 = std::string("abc");
ensureTypeAndValue("initialize std::string",ss2, "abc");
LLSD sl1(std::string("def"));
ensureTypeAndValue("construct std::string", sl1, "def");
LLSD sl2 = std::string("def");
ensureTypeAndValue("initialize std::string", sl2, "def");
LLSD sc1("ghi");
ensureTypeAndValue("construct const char*", sc1, "ghi");
LLSD sc2 = "ghi";
ensureTypeAndValue("initialize const char*",sc2, "ghi");
LLDate aDay("2001-10-22T10:11:12.00Z");
LLSD t1(aDay); ensureTypeAndValue("construct LLDate", t1, aDay);
LLSD t2 = aDay; ensureTypeAndValue("initialize LLDate", t2, aDay);
LLURI path("http://slurl.com/secondlife/Ambleside/57/104/26/");
LLSD p1(path); ensureTypeAndValue("construct LLURI", p1, path);
LLSD p2 = path; ensureTypeAndValue("initialize LLURI", p2, path);
const char source[] = "once in a blue moon";
std::vector<U8> data;
copy(&source[0], &source[sizeof(source)], back_inserter(data));
LLSD x1(data); ensureTypeAndRefValue("construct vector<U8>", x1, data);
LLSD x2 = data; ensureTypeAndRefValue("initialize vector<U8>", x2, data);
}
void checkConversions(const char* msg, const LLSD& v,
LLSD::Boolean eBoolean, LLSD::Integer eInteger,
LLSD::Real eReal, const LLSD::String& eString)
{
std::string s(msg);
ensure_equals(s+" to bool", v.asBoolean(), eBoolean);
ensure_equals(s+" to int", v.asInteger(), eInteger);
if (eReal == eReal)
{
ensure_equals(s+" to real", v.asReal(), eReal);
ensure_equals(s+" to string", v.asString(), eString);
}
else
{
int left = fpclassify(v.asReal());
int right = fpclassify(eReal);
ensure_equals(s+" to real", left, right);
// ensure_equals(s+" to string", v.asString(), eString);
// I've commented this check out, since there doesn't
// seem to be uniform string representation for NaN on
// all platforms. For example, on my Ubuntu 8.10 laptop
// with libc 2.11.1, sqrt(-1.0) will return '-nan', not
// 'nan'.
}
}
template<> template<>
void SDTestObject::test<4>()
// conversion between undefined and basic scalar types:
// boolean, integer, real and string
{
SDCleanupCheck check;
LLSD v; checkConversions("untitled", v, false, 0, 0.0, "");
v = false; checkConversions("false", v, false, 0, 0.0, "");
v = true; checkConversions("true", v, true, 1, 1.0, "true");
v = 0; checkConversions("zero", v, false, 0, 0.0, "0");
v = 1; checkConversions("one", v, true, 1, 1.0, "1");
v = -33; checkConversions("neg33", v, true, -33, -33.0, "-33");
v = 0.0; checkConversions("0.0", v, false, 0, 0.0, "0");
v = 0.5; checkConversions("point5", v, true, 0, 0.5, "0.5");
v = 0.9; checkConversions("point9", v, true, 0, 0.9, "0.9");
v = -3.9; checkConversions("neg3dot9", v, true, -3, -3.9, "-3.9");
// Get rid of NaN test. First, some libraries don't reliably return
// NaN for sqrt(-1.0) -- meaning that I don't even know how to
// portably, reliably produce a NaN value. Second, we observe failures
// on different platforms in the asString() test. But LLSD's
// ImplReal::asString() does not itself recognize NaN! It merely
// passes the value through to llformat(), which passes it through to
// the library vsnprintf(). That is, even when we do produce NaN,
// we're not testing any LLSD code: we're testing the local library's
// vsnprintf() function, which (empirically) produces idiosyncratic
// results. This is just not a good test case.
// v = sqrt(-1.0); checkConversions("NaN", v, false, 0, sqrt(-1.0), "nan");
v = ""; checkConversions("empty", v, false, 0, 0.0, "");
v = "0"; checkConversions("digit0", v, true, 0, 0.0, "0");
v = "10"; checkConversions("digit10", v, true, 10, 10.0, "10");
v = "-2.345"; checkConversions("decdigits", v,
true, -2, -2.345, "-2.345");
v = "apple"; checkConversions("apple", v, true, 0, 0.0, "apple");
v = "33bob"; checkConversions("digialpha", v, true, 0, 0.0, "33bob");
v = " "; checkConversions("space", v, true, 0, 0.0, " ");
v = "\n"; checkConversions("newline", v, true, 0, 0.0, "\n");
}
template<class T>
void checkRoundTrip(const std::string& msg, const LLSD& actual,
const char* sExpected, T vExpected)
{
std::string str = actual.asString();
if (sExpected) {
ensure_equals(msg + " string", str, sExpected);
}
LLSD u(str);
LLSDTraits<T> traits;
ensure_equals(msg + " value", traits.get(u), vExpected);
}
template<> template<>
void SDTestObject::test<5>()
// conversion of String to and from UUID, Date and URI.
{
SDCleanupCheck check;
LLSD v;
LLUUID nullUUID;
LLUUID someUUID;
someUUID.generate();
v = nullUUID; checkRoundTrip("null uuid", v,
"00000000-0000-0000-0000-000000000000", nullUUID);
v = someUUID; checkRoundTrip("random uuid", v, 0, someUUID);
LLDate epoch;
LLDate beta("2003-04-30T04:00:00Z");
LLDate oneOh("2003-06-23T04:00:00Z");
v = epoch; checkRoundTrip("epoch date", v, 0, epoch);
v = beta; checkRoundTrip("beta date", v,
"2003-04-30T04:00:00Z", beta);
v = oneOh; checkRoundTrip("1.0 date", v,
"2003-06-23T04:00:00Z", oneOh);
LLURI empty;
LLURI path("http://slurl.com/secondlife/Ambleside/57/104/26/");
LLURI mail("mailto:zero.linden@secondlife.com");
v = empty; checkRoundTrip("empty URI", v, 0, empty);
v = path; checkRoundTrip("path URI", v,
"http://slurl.com/secondlife/Ambleside/57/104/26/",
path);
v = mail; checkRoundTrip("mail URI", v,
"mailto:zero.linden@secondlife.com", mail);
}
template<> template<>
void SDTestObject::test<6>()
// copy construction and assignment
// checking for shared values after constr. or assignment
// checking in both the same type and change of type case
{
SDCleanupCheck check;
{
LLSD v = 42;
LLSD w0(v);
ensureTypeAndValue("int constr.", w0, 42);
LLSD w1(v);
w1 = 13;
ensureTypeAndValue("int constr. change case 1", w1, 13);
ensureTypeAndValue("int constr. change case 2", v, 42);
LLSD w2(v);
v = 7;
ensureTypeAndValue("int constr. change case 3", w2, 42);
ensureTypeAndValue("int constr. change case 4", v, 7);
}
{
LLSD v = 42;
LLSD w1(v);
w1 = "bob";
ensureTypeAndValue("string constr. change case 1", w1, "bob");
ensureTypeAndValue("string constr. change case 2", v, 42);
LLSD w2(v);
v = "amy";
ensureTypeAndValue("string constr. change case 3", w2, 42);
ensureTypeAndValue("string constr. change case 4", v, "amy");
}
{
LLSD v = 42;
LLSD w0;
w0 = v;
ensureTypeAndValue("int assign", w0, 42);
LLSD w1;
w1 = v;
w1 = 13;
ensureTypeAndValue("int assign change case 1", w1, 13);
ensureTypeAndValue("int assign change case 2", v, 42);
LLSD w2;
w2 = v;
v = 7;
ensureTypeAndValue("int assign change case 3", w2, 42);
ensureTypeAndValue("int assign change case 4", v, 7);
}
{
LLSD v = 42;
LLSD w1;
w1 = v;
w1 = "bob";
ensureTypeAndValue("string assign change case 1", w1, "bob");
ensureTypeAndValue("string assign change case 2", v, 42);
LLSD w2;
w2 = v;
v = "amy";
ensureTypeAndValue("string assign change case 3", w2, 42);
ensureTypeAndValue("string assign change case 4", v, "amy");
}
}
template<> template<>
void SDTestObject::test<7>()
// Test assignment and casting to various scalar types. These
// assignments should invoke the right conversion without it being
// mentioned explicitly. The few exceptions are marked SAD.
{
SDCleanupCheck check;
LLSD v(" 42.375");
bool b = false;
b = v; ensure_equals("assign to bool", b, true);
b = (bool)v; ensure_equals("cast to bool", b, true);
int i = 99;
i = v; ensure_equals("assign to int", i, 42);
i = (int)v; ensure_equals("cast to int", i, 42);
double d = 3.14159;
d = v; ensure_equals("assign to double", d, 42.375);
d = (double)v; ensure_equals("cast to double", d, 42.375);
std::string s = "yo";
// SAD s = v; ensure_equals("assign to string", s, " 42.375");
s = (std::string)v; ensure_equals("cast to string", s, " 42.375");
std::string uuidStr = "b1e50c2b-b627-4d23-8a86-a65d97b6319b";
v = uuidStr;
LLUUID u;
u = v;
ensure_equals("assign to LLUUID", u, LLUUID(uuidStr));
// SAD u = (LLUUID)v;
// ensure_equals("cast to LLUUID", u, LLUUID(uuidStr));
std::string dateStr = "2005-10-24T15:00:00Z";
v = dateStr;
LLDate date;
date = v;
ensure_equals("assign to LLDate", date.asString(), dateStr);
// SAD date = (LLDate)v;
// ensure_equals("cast to LLDate", date.asString(), dateStr);
std::string uriStr = "http://secondlife.com";
v = uriStr;
LLURI uri;
uri = v;
ensure_equals("assign to LLURI", uri.asString(), uriStr);
// SAD uri = (LLURI)v;
// ensure_equals("cast to LLURI", uri.asString(), uriStr);
}
template<> template<>
void SDTestObject::test<8>()
// Test construction of various scalar types from LLSD.
// Test both construction and initialization forms.
// These should invoke the right conversion without it being
// mentioned explicitly. The few exceptions are marked SAD.
{
SDCleanupCheck check;
LLSD v(" 42.375");
bool b1(v); ensure_equals("contruct bool", b1, true);
bool b2 = v; ensure_equals("initialize bool", b2, true);
int i1(v); ensure_equals("contruct int", i1, 42);
int i2 = v; ensure_equals("initialize int", i2, 42);
double d1(v); ensure_equals("contruct double", d1, 42.375);
double d2 = v; ensure_equals("initialize double", d2, 42.375);
std::string s1(v);
std::string s2 = v;
ensure_equals("contruct string", s1, " 42.375");
ensure_equals("initialize string", s2, " 42.375");
std::string t1(v);
std::string t2 = v.asString(); // SAD
ensure_equals("contruct std::string", t1, " 42.375");
ensure_equals("initialize std::string", t2, " 42.375");
std::string uuidStr = "b1e50c2b-b627-4d23-8a86-a65d97b6319b";
v = uuidStr;
LLUUID uuid1(v.asUUID()); // SAD
LLUUID uuid2 = v;
ensure_equals("contruct LLUUID", uuid1, LLUUID(uuidStr));
ensure_equals("initialize LLUUID", uuid2, LLUUID(uuidStr));
std::string dateStr = "2005-10-24T15:00:00Z";
v = dateStr;
LLDate date1(v.asDate()); // SAD
LLDate date2 = v;
ensure_equals("contruct LLDate", date1.asString(), dateStr);
ensure_equals("initialize LLDate", date2.asString(), dateStr);
std::string uriStr = "http://secondlife.com";
v = uriStr;
LLURI uri1(v.asURI()); // SAD
LLURI uri2 = v;
ensure_equals("contruct LLURI", uri1.asString(), uriStr);
ensure_equals("initialize LLURI", uri2.asString(), uriStr);
}
template<> template<>
void SDTestObject::test<9>()
// test to make sure v is interpreted as a bool in a various
// scenarios.
{
SDCleanupCheck check;
LLSD v = "0";
// magic value that is interpreted as boolean true, but integer false!
ensure_equals("trinary operator bool", (v ? true : false), true);
ensure_equals("convert to int, then bool",
((int)v ? true : false), false);
if(v)
{
ensure("if converted to bool", true);
}
else
{
fail("bool did not convert to a bool in if statement.");
}
if(!v)
{
fail("bool did not convert to a bool in negated if statement.");
}
}
template<> template<>
void SDTestObject::test<10>()
// map operations
{
SDCleanupCheck check;
LLSD v;
ensure("undefined has no members", !v.has("amy"));
ensure("undefined get() is undefined", v.get("bob").isUndefined());
v = LLSD::emptyMap();
ensure("empty map is a map", v.isMap());
ensure("empty map has no members", !v.has("cam"));
ensure("empty map get() is undefined", v.get("don").isUndefined());
v.clear();
v.insert("eli", 43);
ensure("insert converts to map", v.isMap());
ensure("inserted key is present", v.has("eli"));
ensureTypeAndValue("inserted value", v.get("eli"), 43);
v.insert("fra", false);
ensure("first key still present", v.has("eli"));
ensure("second key is present", v.has("fra"));
ensureTypeAndValue("first value", v.get("eli"), 43);
ensureTypeAndValue("second value", v.get("fra"), false);
v.erase("eli");
ensure("first key now gone", !v.has("eli"));
ensure("second key still present", v.has("fra"));
ensure("first value gone", v.get("eli").isUndefined());
ensureTypeAndValue("second value sill there", v.get("fra"), false);
v.erase("fra");
ensure("second key now gone", !v.has("fra"));
ensure("second value gone", v.get("fra").isUndefined());
v["gil"] = (std::string)"good morning";
ensure("third key present", v.has("gil"));
ensureTypeAndValue("third key value", v.get("gil"), "good morning");
const LLSD& cv = v; // FIX ME IF POSSIBLE
ensure("missing key", cv["ham"].isUndefined());
ensure("key not present", !v.has("ham"));
LLSD w = 43;
const LLSD& cw = w; // FIX ME IF POSSIBLE
int i = cw["ian"];
ensureTypeAndValue("other missing value", i, 0);
ensure("other missing key", !w.has("ian"));
ensure("no conversion", w.isInteger());
LLSD x;
x = v;
ensure("copy map type", x.isMap());
ensureTypeAndValue("copy map value gil", x.get("gil"), "good morning");
}
template<> template<>
void SDTestObject::test<11>()
// array operations
{
SDCleanupCheck check;
LLSD v;
ensure_equals("undefined has no size", v.size(), 0);
ensure("undefined get() is undefined", v.get(0).isUndefined());
v = LLSD::emptyArray();
ensure("empty array is an array", v.isArray());
ensure_equals("empty array has no size", v.size(), 0);
ensure("empty map get() is undefined", v.get(0).isUndefined());
v.clear();
v.append(88);
v.append("noodle");
v.append(true);
ensure_equals("appened array size", v.size(), 3);
ensure("append array is an array", v.isArray());
ensureTypeAndValue("append 0", v[0], 88);
ensureTypeAndValue("append 1", v[1], "noodle");
ensureTypeAndValue("append 2", v[2], true);
v.insert(0, 77);
v.insert(2, "soba");
v.insert(4, false);
ensure_equals("inserted array size", v.size(), 6);
ensureTypeAndValue("post insert 0", v[0], 77);
ensureTypeAndValue("post insert 1", v[1], 88);
ensureTypeAndValue("post insert 2", v[2], "soba");
ensureTypeAndValue("post insert 3", v[3], "noodle");
ensureTypeAndValue("post insert 4", v[4], false);
ensureTypeAndValue("post insert 5", v[5], true);
ensureTypeAndValue("get 1", v.get(1), 88);
v.set(1, "hot");
ensureTypeAndValue("set 1", v.get(1), "hot");
v.erase(3);
ensure_equals("post erase array size", v.size(), 5);
ensureTypeAndValue("post erase 0", v[0], 77);
ensureTypeAndValue("post erase 1", v[1], "hot");
ensureTypeAndValue("post erase 2", v[2], "soba");
ensureTypeAndValue("post erase 3", v[3], false);
ensureTypeAndValue("post erase 4", v[4], true);
v.append(34);
ensure_equals("size after append", v.size(), 6);
ensureTypeAndValue("post append 5", v[5], 34);
LLSD w;
w = v;
ensure("copy array type", w.isArray());
ensure_equals("copy array size", w.size(), 6);
ensureTypeAndValue("copy array 0", w[0], 77);
ensureTypeAndValue("copy array 1", w[1], "hot");
ensureTypeAndValue("copy array 2", w[2], "soba");
ensureTypeAndValue("copy array 3", w[3], false);
ensureTypeAndValue("copy array 4", w[4], true);
ensureTypeAndValue("copy array 5", w[5], 34);
}
template<> template<>
void SDTestObject::test<12>()
// no sharing
{
SDCleanupCheck check;
LLSD a = 99;
LLSD b = a;
a = 34;
ensureTypeAndValue("top level original changed", a, 34);
ensureTypeAndValue("top level copy unaltered", b, 99);
b = a;
b = 66;
ensureTypeAndValue("top level original unaltered", a, 34);
ensureTypeAndValue("top level copy changed", b, 66);
a[0] = "uno";
a[1] = 99;
a[2] = 1.414;
b = a;
a[1] = 34;
ensureTypeAndValue("array member original changed", a[1], 34);
ensureTypeAndValue("array member copy unaltered", b[1], 99);
b = a;
b[1] = 66;
ensureTypeAndValue("array member original unaltered", a[1], 34);
ensureTypeAndValue("array member copy changed", b[1], 66);
a["alpha"] = "uno";
a["beta"] = 99;
a["gamma"] = 1.414;
b = a;
a["beta"] = 34;
ensureTypeAndValue("map member original changed", a["beta"], 34);
ensureTypeAndValue("map member copy unaltered", b["beta"], 99);
b = a;
b["beta"] = 66;
ensureTypeAndValue("map member original unaltered", a["beta"], 34);
ensureTypeAndValue("map member copy changed", b["beta"], 66);
}
template<> template<>
void SDTestObject::test<13>()
// sharing implementation
{
SDCleanupCheck check;
{
SDAllocationCheck check("copy construct undefinded", 0);
LLSD v;
LLSD w = v;
}
{
SDAllocationCheck check("assign undefined", 0);
LLSD v;
LLSD w;
w = v;
}
{
SDAllocationCheck check("assign integer value", 1);
LLSD v = 45;
v = 33;
v = 0;
}
{
SDAllocationCheck check("copy construct integer", 1);
LLSD v = 45;
LLSD w = v;
}
{
SDAllocationCheck check("assign integer", 1);
LLSD v = 45;
LLSD w;
w = v;
}
{
SDAllocationCheck check("avoids extra clone", 2);
LLSD v = 45;
LLSD w = v;
w = "nice day";
}
{
SDAllocationCheck check("shared values test for threaded work", 9);
//U32 start_llsd_count = LLSD::outstandingCount();
LLSD m = LLSD::emptyMap();
m["one"] = 1;
m["two"] = 2;
m["one_copy"] = m["one"]; // 3 (m, "one" and "two")
m["undef_one"] = LLSD();
m["undef_two"] = LLSD();
m["undef_one_copy"] = m["undef_one"];
{ // Ensure first_array gets freed to avoid counting it
LLSD first_array = LLSD::emptyArray();
first_array.append(1.0f);
first_array.append(2.0f);
first_array.append(3.0f); // 7
m["array"] = first_array;
m["array_clone"] = first_array;
m["array_copy"] = m["array"]; // 7
}
m["string_one"] = "string one value";
m["string_two"] = "string two value";
m["string_one_copy"] = m["string_one"]; // 9
//U32 llsd_object_count = LLSD::outstandingCount();
//std::cout << "Using " << (llsd_object_count - start_llsd_count) << " LLSD objects" << std::endl;
//m.dumpStats();
}
}
template<> template<>
void SDTestObject::test<14>()
// make sure that assignment of char* NULL in a string does not crash.
{
LLSD v;
v = (const char*)NULL;
ensure("type is a string", v.isString());
}
/* TO DO:
conversion of undefined to UUID, Date, URI and Binary
conversion of undefined to map and array
test map operations
test array operations
test array extension
test copying and assign maps and arrays (clone)
test iteration over map
test iteration over array
test iteration over scalar
test empty map and empty array are indeed shared
test serializations
*/
}
+837
View File
@@ -0,0 +1,837 @@
/**
* @file llsdmessagebuilder_tut.cpp
* @date February 2006
* @brief LLSDMessageBuilder unit tests
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include <tut/tut.hpp>
#include "linden_common.h"
#include "lltut.h"
#include "llmessagetemplate.h"
#include "llsdmessagebuilder.h"
#include "llsdmessagereader.h"
#include "llsdtraits.h"
#include "llmath.h"
#include "llquaternion.h"
#include "u64.h"
#include "v3dmath.h"
#include "v3math.h"
#include "v4math.h"
#include "llsdutil.h"
//#include "llsdutil.cpp"
#include "llsdutil_math.cpp"
#include "lltemplatemessagebuilder.h"
namespace tut
{
static LLTemplateMessageBuilder::message_template_name_map_t templateNameMap;
LLMsgData* messageData = NULL;
LLMsgBlkData* messageBlockData = NULL;
struct LLSDMessageBuilderTestData {
LLSDMessageBuilderTestData()
{
messageData = new LLMsgData("testMessage");
messageBlockData = new LLMsgBlkData("testBlock", 0);
}
static LLSDMessageBuilder defaultBuilder()
{
LLSDMessageBuilder builder;
builder.newMessage("name");
builder.nextBlock("block");
return builder;
}
static LLSDMessageReader setReader(const LLSDMessageBuilder& builder)
{
LLSDMessageReader reader;
reader.setMessage("name", builder.getMessage());
return reader;
}
static void addValue(LLMsgBlkData* mbd, char* name, void* v, EMsgVariableType type, int size, int data_size = -1)
{
LLMsgVarData tmp(name, type);
tmp.addData(v, size, type, data_size);
mbd->mMemberVarData[name] = tmp;
}
static LLMessageBlock* defaultTemplateBlock(const EMsgVariableType type = MVT_NULL, const S32 size = 0, EMsgBlockType block = MBT_VARIABLE)
{
return createTemplateBlock(_PREHASH_Test0, type, size, block);
}
static LLMessageBlock* createTemplateBlock(const char* name, const EMsgVariableType type = MVT_NULL, const S32 size = 0, EMsgBlockType block = MBT_VARIABLE)
{
LLMessageBlock* result = new LLMessageBlock(name, block);
if(type != MVT_NULL)
{
result->addVariable(const_cast<char*>(_PREHASH_Test0), type, size);
}
return result;
}
static LLTemplateMessageBuilder* defaultTemplateBuilder(LLMessageTemplate& messageTemplate, char* name = const_cast<char*>(_PREHASH_Test0))
{
templateNameMap[_PREHASH_TestMessage] = &messageTemplate;
LLTemplateMessageBuilder* builder = new LLTemplateMessageBuilder(templateNameMap);
builder->newMessage(_PREHASH_TestMessage);
builder->nextBlock(name);
return builder;
}
static LLMessageTemplate defaultTemplate()
{
return LLMessageTemplate(_PREHASH_TestMessage, 1, MFT_HIGH);
}
};
typedef test_group<LLSDMessageBuilderTestData> LLSDMessageBuilderTestGroup;
typedef LLSDMessageBuilderTestGroup::object LLSDMessageBuilderTestObject;
LLSDMessageBuilderTestGroup llsdMessageBuilderTestGroup("LLSDMessageBuilder");
template<> template<>
void LLSDMessageBuilderTestObject::test<1>()
// construction and test of undefined
{
LLSDMessageBuilder builder = defaultBuilder();
LLSDMessageReader reader = setReader(builder);
}
template<> template<>
void LLSDMessageBuilderTestObject::test<2>()
// bool
{
bool outValue, inValue = true;
LLSDMessageBuilder builder = defaultBuilder();
builder.addBOOL("var", inValue);
LLSDMessageReader reader = setReader(builder);
reader.getBOOL("block", "var", outValue);
ensure_equals("Ensure bool", inValue, outValue);
}
template<> template<>
void LLSDMessageBuilderTestObject::test<3>()
// U8
{
U8 outValue, inValue = 2;
LLSDMessageBuilder builder = defaultBuilder();
builder.addU8("var", inValue);
LLSDMessageReader reader = setReader(builder);
reader.getU8("block", "var", outValue);
ensure_equals("Ensure U8", inValue, outValue);
}
template<> template<>
void LLSDMessageBuilderTestObject::test<4>()
// S16
{
S16 outValue, inValue = 90;
LLSDMessageBuilder builder = defaultBuilder();
builder.addS16("var", inValue);
LLSDMessageReader reader = setReader(builder);
reader.getS16("block", "var", outValue);
ensure_equals("Ensure S16", inValue, outValue);
}
template<> template<>
void LLSDMessageBuilderTestObject::test<5>()
// U16
{
U16 outValue, inValue = 3;
LLSDMessageBuilder builder = defaultBuilder();
builder.addU16("var", inValue);
LLSDMessageReader reader = setReader(builder);
reader.getU16("block", "var", outValue);
ensure_equals("Ensure U16", inValue, outValue);
}
template<> template<>
void LLSDMessageBuilderTestObject::test<6>()
// S32
{
S32 outValue, inValue = 44;
LLSDMessageBuilder builder = defaultBuilder();
builder.addS32("var", inValue);
LLSDMessageReader reader = setReader(builder);
reader.getS32("block", "var", outValue);
ensure_equals("Ensure S32", inValue, outValue);
}
template<> template<>
void LLSDMessageBuilderTestObject::test<7>()
// F32
{
F32 outValue, inValue = 121.44f;
LLSDMessageBuilder builder = defaultBuilder();
builder.addF32("var", inValue);
LLSDMessageReader reader = setReader(builder);
reader.getF32("block", "var", outValue);
ensure_equals("Ensure F32", inValue, outValue);
}
template<> template<>
void LLSDMessageBuilderTestObject::test<8>()
// U32
{
U32 outValue, inValue = 88;
LLSDMessageBuilder builder = defaultBuilder();
builder.addU32("var", inValue);
LLSDMessageReader reader = setReader(builder);
reader.getU32("block", "var", outValue);
ensure_equals("Ensure U32", inValue, outValue);
}
template<> template<>
void LLSDMessageBuilderTestObject::test<9>()
// U64
{
U64 outValue, inValue = 121;
LLSDMessageBuilder builder = defaultBuilder();
builder.addU64("var", inValue);
LLSDMessageReader reader = setReader(builder);
reader.getU64("block", "var", outValue);
ensure_equals("Ensure U64", inValue, outValue);
}
template<> template<>
void LLSDMessageBuilderTestObject::test<10>()
// F64
{
F64 outValue, inValue = 3232143.33;
LLSDMessageBuilder builder = defaultBuilder();
builder.addF64("var", inValue);
LLSDMessageReader reader = setReader(builder);
reader.getF64("block", "var", outValue);
ensure_equals("Ensure F64", inValue, outValue);
}
template<> template<>
void LLSDMessageBuilderTestObject::test<11>()
// Vector3
{
LLVector3 outValue, inValue = LLVector3(1,2,3);
LLSDMessageBuilder builder = defaultBuilder();
builder.addVector3("var", inValue);
LLSDMessageReader reader = setReader(builder);
reader.getVector3("block", "var", outValue);
ensure_equals("Ensure Vector3", inValue, outValue);
}
template<> template<>
void LLSDMessageBuilderTestObject::test<12>()
// Vector4
{
LLVector4 outValue, inValue = LLVector4(1,2,3,4);
LLSDMessageBuilder builder = defaultBuilder();
builder.addVector4("var", inValue);
LLSDMessageReader reader = setReader(builder);
reader.getVector4("block", "var", outValue);
ensure_equals("Ensure Vector4", inValue, outValue);
}
template<> template<>
void LLSDMessageBuilderTestObject::test<13>()
// Vector3d
{
LLVector3d outValue, inValue = LLVector3d(1,2,3);
LLSDMessageBuilder builder = defaultBuilder();
builder.addVector3d("var", inValue);
LLSDMessageReader reader = setReader(builder);
reader.getVector3d("block", "var", outValue);
ensure_equals("Ensure Vector3d", inValue, outValue);
}
template<> template<>
void LLSDMessageBuilderTestObject::test<14>()
// Quaternion
{
LLQuaternion outValue, inValue = LLQuaternion(1,LLVector3(2,3,4));
LLSDMessageBuilder builder = defaultBuilder();
builder.addQuat("var", inValue);
LLSDMessageReader reader = setReader(builder);
reader.getQuat("block", "var", outValue);
ensure_equals("Ensure Quaternion", inValue, outValue);
}
template<> template<>
void LLSDMessageBuilderTestObject::test<15>()
// UUID
{
LLUUID outValue, inValue;
inValue.generate();
LLSDMessageBuilder builder = defaultBuilder();
builder.addUUID("var", inValue);
LLSDMessageReader reader = setReader(builder);
reader.getUUID("block", "var", outValue);
ensure_equals("Ensure UUID", inValue, outValue);
}
template<> template<>
void LLSDMessageBuilderTestObject::test<16>()
// IPAddr
{
U32 outValue, inValue = 12344556;
LLSDMessageBuilder builder = defaultBuilder();
builder.addIPAddr("var", inValue);
LLSDMessageReader reader = setReader(builder);
reader.getIPAddr("block", "var", outValue);
ensure_equals("Ensure IPAddr", inValue, outValue);
}
template<> template<>
void LLSDMessageBuilderTestObject::test<17>()
// IPPort
{
U16 outValue, inValue = 80;
LLSDMessageBuilder builder = defaultBuilder();
builder.addIPPort("var", inValue);
LLSDMessageReader reader = setReader(builder);
reader.getIPPort("block", "var", outValue);
ensure_equals("Ensure IPPort", inValue, outValue);
}
template<> template<>
void LLSDMessageBuilderTestObject::test<18>()
{
std::string outValue, inValue = "testing";
LLSDMessageBuilder builder = defaultBuilder();
builder.addString("var", inValue.c_str());
LLSDMessageReader reader = setReader(builder);
char buffer[MAX_STRING];
reader.getString("block", "var", MAX_STRING, buffer);
outValue = buffer;
ensure_equals("Ensure String", inValue, outValue);
}
template<> template<>
void LLSDMessageBuilderTestObject::test<19>()
{
LLMsgBlkData* mbd = new LLMsgBlkData("testBlock", 0);
LLMsgData* md = new LLMsgData("testMessage");
md->addBlock(mbd);
LLSDMessageBuilder builder = defaultBuilder();
builder.copyFromMessageData(*md);
LLSD output = builder.getMessage();
ensure("Ensure message block created when copied from legacy message to llsd", output["testBlock"].isDefined());
}
// MVT_FIXED
template<> template<>
void LLSDMessageBuilderTestObject::test<20>()
{
char binData[] = "abcdefghijklmnop";
addValue(messageBlockData, (char *)"testBinData", &binData, MVT_FIXED, sizeof(binData));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
builder.copyFromMessageData(*messageData);
LLSD output = builder.getMessage();
std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
ensure("Ensure MVT_S16Array data copied from legacy to llsd give a valid vector", v.size() > 0);
ensure_memory_matches("Ensure fixed binary data works in a message copied from legacy to llsd",
&v[0], sizeof(binData), binData, sizeof(binData));
}
// MVT_VARIABLE data_size 1 (U8's)
template<> template<>
void LLSDMessageBuilderTestObject::test<21>()
{
/* U8 binData[] = "abcdefghijklmnop";
addValue(messageBlockData, "testBinData", &binData, MVT_VARIABLE, sizeof(binData), 1);
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
builder.copyFromMessageData(*messageData);
LLSD output = builder.getMessage();
std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
ensure("Ensure MVT_S16Array data copied from legacy to llsd give a valid vector", v.size() > 0);
ensure_memory_matches("Ensure MVT_VARIABLE U8 binary data works in a message copied from legacy to llsd",
&v[0], sizeof(binData), binData, sizeof(binData));*/
}
// MVT_VARIABLE data_size 2 (U16's)
template<> template<>
void LLSDMessageBuilderTestObject::test<22>()
{
U16 binData[] = {1,2,3,4,5,6,7,8,9}; //9 shorts
addValue(messageBlockData, (char *)"testBinData", &binData, MVT_VARIABLE, sizeof(binData) >> 1, 2);
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
builder.copyFromMessageData(*messageData);
LLSD output = builder.getMessage();
std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
ensure("Ensure MVT_S16Array data copied from legacy to llsd give a valid vector", v.size() > 0);
ensure_memory_matches("Ensure MVT_VARIABLE U16 binary data works in a message copied from legacy to llsd",
&v[0], sizeof(binData) >> 1, binData, sizeof(binData) >> 1);
}
// MVT_VARIABLE data_size 4 (S32's)
template<> template<>
void LLSDMessageBuilderTestObject::test<23>()
{
U32 binData[] = {9,8,7,6,5,4,3,2,1};
addValue(messageBlockData, (char *)"testBinData", &binData, MVT_VARIABLE, sizeof(binData) >> 2, 4);
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
builder.copyFromMessageData(*messageData);
LLSD output = builder.getMessage();
std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
ensure("Ensure MVT_S16Array data copied from legacy to llsd give a valid vector", v.size() > 0);
ensure_memory_matches("Ensure MVT_VARIABLE S32 binary data works in a message copied from legacy to llsd",
&v[0], sizeof(binData) >> 2, binData, sizeof(binData) >> 2);
}
// MVT_U8
template<> template<>
void LLSDMessageBuilderTestObject::test<24>()
{
U8 data = 0xa5;
addValue(messageBlockData, (char *)"testBinData", &data, MVT_U8, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
builder.copyFromMessageData(*messageData);
LLSD output = builder.getMessage();
ensure_equals("Ensure MVT_U8 data works in a message copied from legacy to llsd",
output["testBlock"][0]["testBinData"].asInteger(), data);
}
// MVT_U16
template<> template<>
void LLSDMessageBuilderTestObject::test<25>()
{
U16 data = 0xa55a;
addValue(messageBlockData, (char *)"testBinData", &data, MVT_U16, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
builder.copyFromMessageData(*messageData);
LLSD output = builder.getMessage();
ensure_equals("Ensure MVT_U16 data works in a message copied from legacy to llsd",
output["testBlock"][0]["testBinData"].asInteger(), data);
}
// MVT_U32
template<> template<>
void LLSDMessageBuilderTestObject::test<26>()
{
U32 data = 0xa55a7117;
addValue(messageBlockData, (char *)"testBinData", &data, MVT_U32, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
builder.copyFromMessageData(*messageData);
LLSD output = builder.getMessage();
ensure_equals("Ensure MVT_U32 data works in a message copied from legacy to llsd",
ll_U32_from_sd(output["testBlock"][0]["testBinData"]), data);
}
// MVT_U64 - crush into an s32: LLSD does not support 64 bit values
template<> template<>
void LLSDMessageBuilderTestObject::test<27>()
{
U64 data = U64L(0xa55a711711223344);
addValue(messageBlockData, (char *)"testBinData", &data, MVT_U64, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
builder.copyFromMessageData(*messageData);
LLSD output = builder.getMessage();
ensure_equals("Ensure MVT_U64 data works in a message copied from legacy to llsd",
ll_U64_from_sd(output["testBlock"][0]["testBinData"]), data);
}
// MVT_S8
template<> template<>
void LLSDMessageBuilderTestObject::test<28>()
{
S8 data = -31;
addValue(messageBlockData, (char *)"testBinData", &data, MVT_S8, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
builder.copyFromMessageData(*messageData);
LLSD output = builder.getMessage();
ensure_equals("Ensure MVT_S8 data works in a message copied from legacy to llsd",
output["testBlock"][0]["testBinData"].asInteger(), data);
}
// MVT_S16
template<> template<>
void LLSDMessageBuilderTestObject::test<29>()
{
S16 data = -31;
addValue(messageBlockData, (char *)"testBinData", &data, MVT_S16, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
builder.copyFromMessageData(*messageData);
LLSD output = builder.getMessage();
ensure_equals("Ensure MVT_S16 data works in a message copied from legacy to llsd",
output["testBlock"][0]["testBinData"].asInteger(), data);
}
// MVT_S32
template<> template<>
void LLSDMessageBuilderTestObject::test<30>()
{
S32 data = -3100;
addValue(messageBlockData, (char *)"testBinData", &data, MVT_S32, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
builder.copyFromMessageData(*messageData);
LLSD output = builder.getMessage();
ensure_equals("Ensure MVT_S32 data works in a message copied from legacy to llsd",
output["testBlock"][0]["testBinData"].asInteger(), data);
}
// MVT_S64 - crush into an s32: LLSD does not support 64 bit values
template<> template<>
void LLSDMessageBuilderTestObject::test<31>()
{
S64 data = -31003100;
addValue(messageBlockData, (char *)"testBinData", &data, MVT_S64, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
builder.copyFromMessageData(*messageData);
LLSD output = builder.getMessage();
ensure_equals("Ensure MVT_S64 data works in a message copied from legacy to llsd",
output["testBlock"][0]["testBinData"].asInteger(), (S32)data);
}
// MVT_F32
template<> template<>
void LLSDMessageBuilderTestObject::test<32>()
{
F32 data = 1234.1234f;
addValue(messageBlockData, (char *)"testBinData", &data, MVT_F32, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
builder.copyFromMessageData(*messageData);
LLSD output = builder.getMessage();
ensure_equals("Ensure MVT_F32 data works in a message copied from legacy to llsd",
output["testBlock"][0]["testBinData"].asReal(), data);
}
// MVT_F64
template<> template<>
void LLSDMessageBuilderTestObject::test<33>()
{
F64 data = 1234.1234;
addValue(messageBlockData, (char *)"testBinData", &data, MVT_F64, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
builder.copyFromMessageData(*messageData);
LLSD output = builder.getMessage();
ensure_equals("Ensure MVT_F64 data works in a message copied from legacy to llsd",
output["testBlock"][0]["testBinData"].asReal(), data);
}
// MVT_LLVector3
template<> template<>
void LLSDMessageBuilderTestObject::test<34>()
{
LLVector3 data(1,2,3);
addValue(messageBlockData, (char *)"testBinData", &data, MVT_LLVector3, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
builder.copyFromMessageData(*messageData);
LLSD output = builder.getMessage();
ensure_equals("Ensure MVT_LLVector3 data works in a message copied from legacy to llsd",
ll_vector3_from_sd(output["testBlock"][0]["testBinData"]), data);
}
// MVT_LLVector3d
template<> template<>
void LLSDMessageBuilderTestObject::test<35>()
{
LLVector3d data(1,2,3);
addValue(messageBlockData, (char *)"testBinData", &data, MVT_LLVector3d, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
builder.copyFromMessageData(*messageData);
LLSD output = builder.getMessage();
ensure_equals("Ensure MVT_LLVector3 data works in a message copied from legacy to llsd",
ll_vector3d_from_sd(output["testBlock"][0]["testBinData"]), data);
}
// MVT_LLVector4
template<> template<>
void LLSDMessageBuilderTestObject::test<36>()
{
LLVector4 data(1,2,3,4);
LLSD v = ll_sd_from_vector4(data);
addValue(messageBlockData, (char *)"testBinData", &data, MVT_LLVector4, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
builder.copyFromMessageData(*messageData);
LLSD output = builder.getMessage();
ensure_equals("Ensure MVT_LLVector4 data works in a message copied from legacy to llsd",
output["testBlock"][0]["testBinData"], v);
}
// MVT_LLQuaternion
template<> template<>
void LLSDMessageBuilderTestObject::test<37>()
{
LLQuaternion data(0.3713907f, 0.5570861f, 0.7427813f,0.0f);
//we send a quaternion packed into a vec3 (w is infered) - so sizeof(vec) == 12 bytes not 16.
LLVector3 vec = data.packToVector3();
addValue(messageBlockData, (char *)"testBinData", &vec, MVT_LLQuaternion, sizeof(vec));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
builder.copyFromMessageData(*messageData);
LLSD output = builder.getMessage();
ensure_equals("Ensure MVT_LLQuaternion data works in a message copied from legacy to llsd",
ll_quaternion_from_sd(output["testBlock"][0]["testBinData"]), data);
}
// MVT_LLUUID
template<> template<>
void LLSDMessageBuilderTestObject::test<38>()
{
LLUUID data("01234567-0123-0123-0123-234567abcdef");
addValue(messageBlockData, (char *)"testBinData", &data, MVT_LLUUID, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
builder.copyFromMessageData(*messageData);
LLSD output = builder.getMessage();
std::string v = output["testBlock"][0]["testBinData"].asUUID().asString();
ensure_equals("Ensure MVT_LLUUID data works in a message copied from legacy to llsd",
output["testBlock"][0]["testBinData"].asUUID(), data);
}
// MVT_BOOL
template<> template<>
void LLSDMessageBuilderTestObject::test<39>()
{
bool valueTrue = true;
bool valueFalse = false;
LLMsgData* md = new LLMsgData("testMessage");
LLMsgBlkData* mbd = new LLMsgBlkData("testBlock", 0);
addValue(mbd, (char *)"testBoolFalse", &valueFalse, MVT_BOOL, sizeof(bool));
addValue(mbd, (char *)"testBoolTrue", &valueTrue, MVT_BOOL, sizeof(bool));
md->addBlock(mbd);
LLSDMessageBuilder builder = defaultBuilder();
builder.copyFromMessageData(*md);
LLSD output = builder.getMessage();
ensure("Ensure bools work in a message copied from legacy to llsd",
output["testBlock"][0]["testBoolTrue"].asBoolean() && !output["testBlock"][0]["testBoolFalse"].asBoolean());
}
// MVT_IP_ADDR
template<> template<>
void LLSDMessageBuilderTestObject::test<40>()
{
U32 data(0xff887766);
LLSD v = ll_sd_from_ipaddr(data);
addValue(messageBlockData, (char *)"testBinData", &data, MVT_IP_ADDR, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
builder.copyFromMessageData(*messageData);
LLSD output = builder.getMessage();
ensure_equals("Ensure MVT_IP_ADDR data works in a message copied from legacy to llsd",
output["testBlock"][0]["testBinData"], v);
}
// MVT_IP_PORT
template<> template<>
void LLSDMessageBuilderTestObject::test<41>()
{
U16 data = 0xff88;
addValue(messageBlockData, (char *)"testBinData", &data, MVT_IP_PORT, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
builder.copyFromMessageData(*messageData);
LLSD output = builder.getMessage();
ensure_equals("Ensure MVT_IP_PORT data works in a message copied from legacy to llsd",
output["testBlock"][0]["testBinData"].asInteger(), data);
}
// MVT_U16Vec3
template<> template<>
void LLSDMessageBuilderTestObject::test<42>()
{
U16 data[3] = {0,1,2};
addValue(messageBlockData, (char *)"testBinData", &data, MVT_U16Vec3, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
builder.copyFromMessageData(*messageData);
LLSD output = builder.getMessage();
std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
ensure("Ensure MVT_U16Vec3 data copied from legacy to llsd give a valid vector", v.size() > 0);
ensure_memory_matches("Ensure MVT_U16Vec3 data works in a message copied from legacy to llsd",
(U16*)&v[0], 6, data, 6);
}
// MVT_U16Quat
template<> template<>
void LLSDMessageBuilderTestObject::test<43>()
{
U16 data[4] = {0,1,2,4};
addValue(messageBlockData, (char *)"testBinData", &data, MVT_U16Quat, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
builder.copyFromMessageData(*messageData);
LLSD output = builder.getMessage();
std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
ensure("Ensure MVT_U16Quat data copied from legacy to llsd give a valid vector", v.size() > 0);
ensure_memory_matches("Ensure MVT_U16Quat data works in a message copied from legacy to llsd",
(U16*)&v[0], 8, data, 8);
}
// MVT_S16Array
template<> template<>
void LLSDMessageBuilderTestObject::test<44>()
{
S16 data[19] = {0,-1,2,-4,5,-6,7,-8,9,-10,11,-12,13,-14,15,16,17,18};
addValue(messageBlockData, (char *)"testBinData", &data, MVT_S16Array, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
builder.copyFromMessageData(*messageData);
LLSD output = builder.getMessage();
std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
ensure("Ensure MVT_S16Array data copied from legacy to llsd give a valid vector", v.size() > 0);
ensure_memory_matches("Ensure MVT_S16Array data works in a message copied from legacy to llsd",
(U16*)&v[0], 19, data, 19);
}
template<> template<>
void LLSDMessageBuilderTestObject::test<45>()
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultTemplateBlock(MVT_U8, 1));
U8 inValue = 2;
LLTemplateMessageBuilder* template_builder = defaultTemplateBuilder(messageTemplate);
template_builder->addU8(_PREHASH_Test0, inValue);
LLSDMessageBuilder builder;
builder.copyFromMessageData(*template_builder->getCurrentMessage());
LLSD output = builder.getMessage();
ensure_equals(output["Test0"][0]["Test0"].asInteger(), 2);
}
template<> template<>
void LLSDMessageBuilderTestObject::test<46>()
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultTemplateBlock(MVT_VARIABLE, 1));
std::string inValue = "testing";
LLTemplateMessageBuilder* builder = defaultTemplateBuilder(messageTemplate);
builder->addString(_PREHASH_Test0, inValue.c_str());
LLSDMessageBuilder sd_builder;
sd_builder.copyFromMessageData(*builder->getCurrentMessage());
LLSD output = sd_builder.getMessage();
ensure_equals(output["Test0"][0]["Test0"].asString(), std::string("testing"));
}
}
+324
View File
@@ -0,0 +1,324 @@
/**
* @file llsdmessagereader_tut.cpp
* @date February 2006
* @brief LLSDMessageReader unit tests
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include <tut/tut.hpp>
#include "linden_common.h"
#include "lltut.h"
#include "v3dmath.h"
#include "v3math.h"
#include "v4math.h"
#include "llquaternion.h"
#include "message.h"
#include "llsdmessagereader.h"
#include "llsdutil.h"
#include "llsdutil_math.h"
namespace tut
{
struct LLSDMessageReaderTestData {
static void ensureMessageName(const std::string& msg_name,
const LLSD& msg_data,
const std::string& expected_name)
{
LLSDMessageReader msg;
msg.setMessage(LLMessageStringTable::getInstance()->getString(msg_name.c_str()), msg_data);
ensure_equals("Ensure name", std::string(msg.getMessageName()),
expected_name);
}
static void ensureNumberOfBlocks(const LLSD& msg_data,
const std::string& block,
S32 expected_number)
{
LLSDMessageReader msg;
msg.setMessage("fakename", msg_data);
ensure_equals("Ensure number of blocks", msg.getNumberOfBlocks(block.c_str()),
expected_number);
}
static void ensureMessageSize(const LLSD& msg_data,
S32 expected_size)
{
LLSDMessageReader msg;
msg.setMessage("fakename", msg_data);
ensure_equals( "Ensure size", msg.getMessageSize(), expected_size);
}
static void ensureBool(const LLSD& msg_data,
const std::string& block,
const std::string& var,
S32 blocknum,
bool expected)
{
LLSDMessageReader msg;
msg.setMessage("fakename", msg_data);
bool test_data;
msg.getBOOL(block.c_str(), var.c_str(), test_data, blocknum);
ensure_equals( "Ensure bool field", test_data, expected);
}
};
typedef test_group<LLSDMessageReaderTestData> LLSDMessageReaderTestGroup;
typedef LLSDMessageReaderTestGroup::object LLSDMessageReaderTestObject;
LLSDMessageReaderTestGroup llsdMessageReaderTestGroup("LLSDMessageReader");
template<> template<>
void LLSDMessageReaderTestObject::test<1>()
// construction and test of empty LLSD
{
LLSD message = LLSD::emptyMap();
ensureMessageName("", message, "");
ensureNumberOfBlocks(message, "Fakeblock", 0);
ensureMessageSize(message, 0);
}
template<> template<>
void LLSDMessageReaderTestObject::test<2>()
// construction and test of simple message with one block
{
LLSD message = LLSD::emptyMap();
message["block1"] = LLSD::emptyArray();
message["block1"][0] = LLSD::emptyMap();
message["block1"][0]["Field1"] = 0;
ensureMessageName("name2", message, "name2");
ensureNumberOfBlocks(message, "block1", 1);
ensureMessageSize(message, 0);
}
template<> template<>
void LLSDMessageReaderTestObject::test<3>()
// multiple blocks
{
LLSD message = LLSD::emptyMap();
message["block1"] = LLSD::emptyArray();
bool bool_true = true;
bool bool_false = false;
message["block1"][0] = LLSD::emptyMap();
message["block1"][0]["BoolField1"] = bool_true;
message["block1"][1] = LLSD::emptyMap();
message["block1"][1]["BoolField1"] = bool_false;
message["block1"][1]["BoolField2"] = bool_true;
ensureMessageName("name3", message, "name3");
ensureBool(message, "block1", "BoolField1", 0, true);
ensureBool(message, "block1", "BoolField1", 1, false);
ensureBool(message, "block1", "BoolField2", 1, true);
ensureNumberOfBlocks(message, "block1", 2);
ensureMessageSize(message, 0);
}
template<typename T>
LLSDMessageReader testType(const T& value)
{
LLSD message = LLSD::emptyMap();
message["block"][0]["var"] = value;
LLSDMessageReader msg;
msg.setMessage("fakename", message);
return msg;
}
template<> template<>
void LLSDMessageReaderTestObject::test<4>()
// S8
{
S8 outValue, inValue = -3;
LLSDMessageReader msg = testType(inValue);
msg.getS8("block", "var", outValue);
ensure_equals("Ensure S8", outValue, inValue);
}
template<> template<>
void
LLSDMessageReaderTestObject::test<5>()
// U8
{
U8 outValue, inValue = 2;
LLSDMessageReader msg = testType(inValue);
msg.getU8("block", "var", outValue);
ensure_equals("Ensure U8", outValue, inValue);
}
template<> template<>
void LLSDMessageReaderTestObject::test<6>()
// S16
{
S16 outValue, inValue = 90;
LLSDMessageReader msg = testType(inValue);
msg.getS16("block", "var", outValue);
ensure_equals("Ensure S16", outValue, inValue);
}
template<> template<>
void LLSDMessageReaderTestObject::test<7>()
// U16
{
U16 outValue, inValue = 3;
LLSDMessageReader msg = testType(inValue);
msg.getU16("block", "var", outValue);
ensure_equals("Ensure S16", outValue, inValue);
}
template<> template<>
void LLSDMessageReaderTestObject::test<8>()
// S32
{
S32 outValue, inValue = 44;
LLSDMessageReader msg = testType(inValue);
msg.getS32("block", "var", outValue);
ensure_equals("Ensure S32", outValue, inValue);
}
template<> template<>
void LLSDMessageReaderTestObject::test<9>()
// F32
{
F32 outValue, inValue = 121.44f;
LLSDMessageReader msg = testType(inValue);
msg.getF32("block", "var", outValue);
ensure_equals("Ensure F32", outValue, inValue);
}
template<> template<>
void LLSDMessageReaderTestObject::test<10>()
// U32
{
U32 outValue, inValue = 88;
LLSD sdValue = ll_sd_from_U32(inValue);
LLSDMessageReader msg = testType(sdValue);
msg.getU32("block", "var", outValue);
ensure_equals("Ensure U32", outValue, inValue);
}
template<> template<>
void LLSDMessageReaderTestObject::test<11>()
// U64
{
U64 outValue, inValue = 121;
LLSD sdValue = ll_sd_from_U64(inValue);
LLSDMessageReader msg = testType(sdValue);
msg.getU64("block", "var", outValue);
ensure_equals("Ensure U64", outValue, inValue);
}
template<> template<>
void LLSDMessageReaderTestObject::test<12>()
// F64
{
F64 outValue, inValue = 3232143.33;
LLSDMessageReader msg = testType(inValue);
msg.getF64("block", "var", outValue);
ensure_equals("Ensure F64", outValue, inValue);
}
template<> template<>
void LLSDMessageReaderTestObject::test<13>()
// String
{
std::string outValue, inValue = "testing";
LLSDMessageReader msg = testType<std::string>(inValue.c_str());
char buffer[MAX_STRING];
msg.getString("block", "var", MAX_STRING, buffer);
outValue = buffer;
ensure_equals("Ensure String", outValue, inValue);
}
template<> template<>
void LLSDMessageReaderTestObject::test<14>()
// Vector3
{
LLVector3 outValue, inValue = LLVector3(1,2,3);
LLSD sdValue = ll_sd_from_vector3(inValue);
LLSDMessageReader msg = testType(sdValue);
msg.getVector3("block", "var", outValue);
ensure_equals("Ensure Vector3", outValue, inValue);
}
template<> template<>
void LLSDMessageReaderTestObject::test<15>()
// Vector4
{
LLVector4 outValue, inValue = LLVector4(1,2,3,4);
LLSD sdValue = ll_sd_from_vector4(inValue);
LLSDMessageReader msg = testType(sdValue);
msg.getVector4("block", "var", outValue);
ensure_equals("Ensure Vector4", outValue, inValue);
}
template<> template<>
void LLSDMessageReaderTestObject::test<16>()
// Vector3d
{
LLVector3d outValue, inValue = LLVector3d(1,2,3);
LLSD sdValue = ll_sd_from_vector3d(inValue);
LLSDMessageReader msg = testType(sdValue);
msg.getVector3d("block", "var", outValue);
ensure_equals("Ensure Vector3d", outValue, inValue);
}
template<> template<>
void LLSDMessageReaderTestObject::test<17>()
// Quaternion
{
LLQuaternion outValue, inValue = LLQuaternion(1,LLVector3(2,3,4));
LLSD sdValue = ll_sd_from_quaternion(inValue);
LLSDMessageReader msg = testType(sdValue);
msg.getQuat("block", "var", outValue);
ensure_equals("Ensure Quaternion", outValue, inValue);
}
template<> template<>
void LLSDMessageReaderTestObject::test<18>()
// UUID
{
LLUUID outValue, inValue;
inValue.generate();
LLSDMessageReader msg = testType(inValue);
msg.getUUID("block", "var", outValue);
ensure_equals("Ensure UUID", outValue, inValue);
}
template<> template<>
void LLSDMessageReaderTestObject::test<19>()
// IPAddr
{
U32 outValue, inValue = 12344556;
LLSD sdValue = ll_sd_from_ipaddr(inValue);
LLSDMessageReader msg = testType(sdValue);
msg.getIPAddr("block", "var", outValue);
ensure_equals("Ensure IPAddr", outValue, inValue);
}
template<> template<>
void LLSDMessageReaderTestObject::test<20>()
// IPPort
{
U16 outValue, inValue = 80;
LLSDMessageReader msg = testType(inValue);
msg.getIPPort("block", "var", outValue);
ensure_equals("Ensure IPPort", outValue, inValue);
}
template<> template<>
void LLSDMessageReaderTestObject::test<21>()
// Binary
{
std::vector<U8> outValue(2), inValue(2);
inValue[0] = 0;
inValue[1] = 1;
LLSDMessageReader msg = testType(inValue);
msg.getBinaryData("block", "var", &(outValue[0]), static_cast<S32>(inValue.size()));
ensure_equals("Ensure Binary", outValue, inValue);
}
}
+100
View File
@@ -0,0 +1,100 @@
/**
* @file llsdtraits.h
* @brief Unit test helpers
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LLSDTRAITS_H
#define LLSDTRAITS_H
#include "llsd.h"
#include "llstring.h"
template<class T>
class LLSDTraits
{
protected:
typedef T (LLSD::*Getter)() const;
LLSD::Type type;
Getter getter;
public:
LLSDTraits();
T get(const LLSD& actual)
{
return (actual.*getter)();
}
bool checkType(const LLSD& actual)
{
return actual.type() == type;
}
};
template<> inline
LLSDTraits<LLSD::Boolean>::LLSDTraits()
: type(LLSD::TypeBoolean), getter(&LLSD::asBoolean)
{ }
template<> inline
LLSDTraits<LLSD::Integer>::LLSDTraits()
: type(LLSD::TypeInteger), getter(&LLSD::asInteger)
{ }
template<> inline
LLSDTraits<LLSD::Real>::LLSDTraits()
: type(LLSD::TypeReal), getter(&LLSD::asReal)
{ }
template<> inline
LLSDTraits<LLSD::UUID>::LLSDTraits()
: type(LLSD::TypeUUID), getter(&LLSD::asUUID)
{ }
template<> inline
LLSDTraits<LLSD::String>::LLSDTraits()
: type(LLSD::TypeString), getter(&LLSD::asString)
{ }
template<>
class LLSDTraits<const char*> : public LLSDTraits<LLSD::String>
{ };
template<> inline
LLSDTraits<LLSD::Date>::LLSDTraits()
: type(LLSD::TypeDate), getter(&LLSD::asDate)
{ }
template<> inline
LLSDTraits<LLSD::URI>::LLSDTraits()
: type(LLSD::TypeURI), getter(&LLSD::asURI)
{ }
template<> inline
LLSDTraits<const LLSD::Binary&>::LLSDTraits()
: type(LLSD::TypeBinary), getter(&LLSD::asBinary)
{ }
#endif // LLSDTRAITS_H
+434
View File
@@ -0,0 +1,434 @@
/**
* @file llsdutil_tut.cpp
* @author Adroit
* @date 2007-02
* @brief LLSD conversion routines test cases.
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "lltut.h"
#include "m4math.h"
#include "v2math.h"
#include "v2math.h"
#include "v3color.h"
#include "v3math.h"
#include "v3dmath.h"
#include "v4coloru.h"
#include "v4math.h"
#include "llquaternion.h"
#include "llsdutil.h"
#include "llsdutil_math.h"
#include "stringize.h"
#include <set>
#include <boost/range.hpp>
namespace tut
{
struct llsdutil_data
{
void test_matches(const std::string& proto_key, const LLSD& possibles,
const char** begin, const char** end)
{
std::set<std::string> succeed(begin, end);
LLSD prototype(possibles[proto_key]);
for (LLSD::map_const_iterator pi(possibles.beginMap()), pend(possibles.endMap());
pi != pend; ++pi)
{
std::string match(llsd_matches(prototype, pi->second));
std::set<std::string>::const_iterator found = succeed.find(pi->first);
if (found != succeed.end())
{
// This test is supposed to succeed. Comparing to the
// empty string ensures that if the test fails, it will
// display the string received so we can tell what failed.
ensure_equals("match", match, "");
}
else
{
// This test is supposed to fail. If we get a false match,
// the string 'match' will be empty, which doesn't tell us
// much about which case went awry. So construct a more
// detailed description string.
ensure(proto_key + " shouldn't match " + pi->first, ! match.empty());
}
}
}
};
typedef test_group<llsdutil_data> llsdutil_test;;
typedef llsdutil_test::object llsdutil_object;
tut::llsdutil_test tutil("llsdutil");
template<> template<>
void llsdutil_object::test<1>()
{
LLSD sd;
U64 valueIn , valueOut;
valueIn = U64L(0xFEDCBA9876543210);
sd = ll_sd_from_U64(valueIn);
valueOut = ll_U64_from_sd(sd);
ensure_equals("U64 valueIn->sd->valueOut", valueIn, valueOut);
}
template<> template<>
void llsdutil_object::test<2>()
{
LLSD sd;
U32 valueIn, valueOut;
valueIn = 0x87654321;
sd = ll_sd_from_U32(valueIn);
valueOut = ll_U32_from_sd(sd);
ensure_equals("U32 valueIn->sd->valueOut", valueIn, valueOut);
}
template<> template<>
void llsdutil_object::test<3>()
{
U32 valueIn, valueOut;
valueIn = 0x87654321;
LLSD sd;
sd = ll_sd_from_ipaddr(valueIn);
valueOut = ll_ipaddr_from_sd(sd);
ensure_equals("valueIn->sd->valueOut", valueIn, valueOut);
}
template<> template<>
void llsdutil_object::test<4>()
{
LLSD sd;
LLVector3 vec1(-1.0, 2.0, -3.0);
sd = ll_sd_from_vector3(vec1);
LLVector3 vec2 = ll_vector3_from_sd(sd);
ensure_equals("vector3 -> sd -> vector3: 1", vec1, vec2);
LLVector3 vec3(sd);
ensure_equals("vector3 -> sd -> vector3: 2", vec1, vec3);
sd.clear();
vec1.setVec(0., 0., 0.);
sd = ll_sd_from_vector3(vec1);
vec2 = ll_vector3_from_sd(sd);
ensure_equals("vector3 -> sd -> vector3: 3", vec1, vec2);
sd.clear();
}
template<> template<>
void llsdutil_object::test<5>()
{
LLSD sd;
LLVector3d vec1((F64)(U64L(0xFEDCBA9876543210) << 2), -1., 0);
sd = ll_sd_from_vector3d(vec1);
LLVector3d vec2 = ll_vector3d_from_sd(sd);
ensure_equals("vector3d -> sd -> vector3d: 1", vec1, vec2);
LLVector3d vec3(sd);
ensure_equals("vector3d -> sd -> vector3d : 2", vec1, vec3);
}
template<> template<>
void llsdutil_object::test<6>()
{
LLSD sd;
LLVector2 vec((F32) -3., (F32) 4.2);
sd = ll_sd_from_vector2(vec);
LLVector2 vec1 = ll_vector2_from_sd(sd);
ensure_equals("vector2 -> sd -> vector2", vec, vec1);
LLSD sd2 = ll_sd_from_vector2(vec1);
ensure_equals("sd -> vector2 -> sd: 2", sd, sd2);
}
template<> template<>
void llsdutil_object::test<7>()
{
LLSD sd;
LLQuaternion quat((F32) 1., (F32) -0.98, (F32) 2.3, (F32) 0xffff);
sd = ll_sd_from_quaternion(quat);
LLQuaternion quat1 = ll_quaternion_from_sd(sd);
ensure_equals("LLQuaternion -> sd -> LLQuaternion", quat, quat1);
LLSD sd2 = ll_sd_from_quaternion(quat1);
ensure_equals("sd -> LLQuaternion -> sd ", sd, sd2);
}
template<> template<>
void llsdutil_object::test<8>()
{
LLSD sd;
LLColor4 c(1.0f, 2.2f, 4.0f, 7.f);
sd = ll_sd_from_color4(c);
LLColor4 c1 =ll_color4_from_sd(sd);
ensure_equals("LLColor4 -> sd -> LLColor4", c, c1);
LLSD sd1 = ll_sd_from_color4(c1);
ensure_equals("sd -> LLColor4 -> sd", sd, sd1);
}
template<> template<>
void llsdutil_object::test<9>()
{
set_test_name("llsd_matches");
// for this test, construct a map of all possible LLSD types
LLSD map;
map.insert("empty", LLSD());
map.insert("Boolean", LLSD::Boolean());
map.insert("Integer", LLSD::Integer(0));
map.insert("Real", LLSD::Real(0.0));
map.insert("String", LLSD::String("bah"));
map.insert("NumString", LLSD::String("1"));
map.insert("UUID", LLSD::UUID());
map.insert("Date", LLSD::Date());
map.insert("URI", LLSD::URI());
map.insert("Binary", LLSD::Binary());
map.insert("Map", LLSD().with("foo", LLSD()));
// Only an empty array can be constructed on the fly
LLSD array;
array.append(LLSD());
map.insert("Array", array);
// These iterators are declared outside our various for loops to avoid
// fatal MSVC warning: "I used to be broken, but I'm all better now!"
LLSD::map_const_iterator mi, mend(map.endMap());
/*-------------------------- llsd_matches --------------------------*/
// empty prototype matches anything
for (mi = map.beginMap(); mi != mend; ++mi)
{
ensure_equals(std::string("empty matches ") + mi->first, llsd_matches(LLSD(), mi->second), "");
}
LLSD proto_array, data_array;
for (int i = 0; i < 3; ++i)
{
proto_array.append(LLSD());
data_array.append(LLSD());
}
// prototype array matches only array
for (mi = map.beginMap(); mi != mend; ++mi)
{
ensure(std::string("array doesn't match ") + mi->first,
! llsd_matches(proto_array, mi->second).empty());
}
// data array must be at least as long as prototype array
proto_array.append(LLSD());
ensure_equals("data array too short", llsd_matches(proto_array, data_array),
"Array size 4 required instead of Array size 3");
data_array.append(LLSD());
ensure_equals("data array just right", llsd_matches(proto_array, data_array), "");
data_array.append(LLSD());
ensure_equals("data array longer", llsd_matches(proto_array, data_array), "");
// array element matching
data_array[0] = LLSD::String();
ensure_equals("undefined prototype array entry", llsd_matches(proto_array, data_array), "");
proto_array[0] = LLSD::Binary();
ensure_equals("scalar prototype array entry", llsd_matches(proto_array, data_array),
"[0]: Binary required instead of String");
data_array[0] = LLSD::Binary();
ensure_equals("matching prototype array entry", llsd_matches(proto_array, data_array), "");
// build a coupla maps
LLSD proto_map, data_map;
data_map["got"] = LLSD();
data_map["found"] = LLSD();
for (LLSD::map_const_iterator dmi(data_map.beginMap()), dmend(data_map.endMap());
dmi != dmend; ++dmi)
{
proto_map[dmi->first] = dmi->second;
}
proto_map["foo"] = LLSD();
proto_map["bar"] = LLSD();
// prototype map matches only map
for (mi = map.beginMap(); mi != mend; ++mi)
{
ensure(std::string("map doesn't match ") + mi->first,
! llsd_matches(proto_map, mi->second).empty());
}
// data map must contain all keys in prototype map
std::string error(llsd_matches(proto_map, data_map));
ensure_contains("missing keys", error, "missing keys");
ensure_contains("missing foo", error, "foo");
ensure_contains("missing bar", error, "bar");
ensure_does_not_contain("found found", error, "found");
ensure_does_not_contain("got got", error, "got");
data_map["bar"] = LLSD();
error = llsd_matches(proto_map, data_map);
ensure_contains("missing foo", error, "foo");
ensure_does_not_contain("got bar", error, "bar");
data_map["foo"] = LLSD();
ensure_equals("data map just right", llsd_matches(proto_map, data_map), "");
data_map["extra"] = LLSD();
ensure_equals("data map with extra", llsd_matches(proto_map, data_map), "");
// map element matching
data_map["foo"] = LLSD::String();
ensure_equals("undefined prototype map entry", llsd_matches(proto_map, data_map), "");
proto_map["foo"] = LLSD::Binary();
ensure_equals("scalar prototype map entry", llsd_matches(proto_map, data_map),
"['foo']: Binary required instead of String");
data_map["foo"] = LLSD::Binary();
ensure_equals("matching prototype map entry", llsd_matches(proto_map, data_map), "");
// String
{
static const char* matches[] = { "String", "NumString", "Boolean", "Integer",
"Real", "UUID", "Date", "URI" };
test_matches("String", map, boost::begin(matches), boost::end(matches));
}
// Boolean, Integer, Real
static const char* numerics[] = { "Boolean", "Integer", "Real" };
for (const char **ni = boost::begin(numerics), **nend = boost::end(numerics);
ni != nend; ++ni)
{
static const char* matches[] = { "Boolean", "Integer", "Real", "String", "NumString" };
test_matches(*ni, map, boost::begin(matches), boost::end(matches));
}
// UUID
{
static const char* matches[] = { "UUID", "String", "NumString" };
test_matches("UUID", map, boost::begin(matches), boost::end(matches));
}
// Date
{
static const char* matches[] = { "Date", "String", "NumString" };
test_matches("Date", map, boost::begin(matches), boost::end(matches));
}
// URI
{
static const char* matches[] = { "URI", "String", "NumString" };
test_matches("URI", map, boost::begin(matches), boost::end(matches));
}
// Binary
{
static const char* matches[] = { "Binary" };
test_matches("Binary", map, boost::begin(matches), boost::end(matches));
}
/*-------------------------- llsd_equals ---------------------------*/
// Cross-product of each LLSD type with every other
for (LLSD::map_const_iterator lmi(map.beginMap()), lmend(map.endMap());
lmi != lmend; ++lmi)
{
for (LLSD::map_const_iterator rmi(map.beginMap()), rmend(map.endMap());
rmi != rmend; ++rmi)
{
// Name this test based on the map keys naming the types of
// interest, e.g "String::Integer".
// We expect the values (xmi->second) to be equal if and only
// if the type names (xmi->first) are equal.
ensure(STRINGIZE(lmi->first << "::" << rmi->first),
bool(lmi->first == rmi->first) ==
bool(llsd_equals(lmi->second, rmi->second)));
}
}
// Array cases
LLSD rarray;
rarray.append(1.0);
rarray.append(2);
rarray.append("3");
LLSD larray(rarray);
ensure("llsd_equals(equal arrays)", llsd_equals(larray, rarray));
rarray[2] = "4";
ensure("llsd_equals(different [2])", ! llsd_equals(larray, rarray));
rarray = larray;
rarray.append(LLSD::Date());
ensure("llsd_equals(longer right array)", ! llsd_equals(larray, rarray));
rarray = larray;
rarray.erase(2);
ensure("llsd_equals(shorter right array)", ! llsd_equals(larray, rarray));
// Map cases
LLSD rmap;
rmap["San Francisco"] = 65;
rmap["Phoenix"] = 92;
rmap["Boston"] = 77;
LLSD lmap(rmap);
ensure("llsd_equals(equal maps)", llsd_equals(lmap, rmap));
rmap["Boston"] = 80;
ensure("llsd_equals(different [\"Boston\"])", ! llsd_equals(lmap, rmap));
rmap = lmap;
rmap["Atlanta"] = 95;
ensure("llsd_equals(superset right map)", ! llsd_equals(lmap, rmap));
rmap = lmap;
lmap["Seattle"] = 72;
ensure("llsd_equals(superset left map)", ! llsd_equals(lmap, rmap));
}
template<> template<>
void llsdutil_object::test<10>()
{
set_test_name("llsd_hashing");
{
LLSD data_s1 = LLSD::String("The quick brown aardvark jumped over the lazy lemming.");
LLSD data_s2 = LLSD::String("The quick brown aardvark jumped over the lazy lemming.");
ensure("hash: Identical string hashes match.", boost::hash<LLSD>{}(data_s1) == boost::hash<LLSD>{}(data_s2));
}
{
LLSD data_r1 = LLSD::Real(3.0f);
LLSD data_i1 = LLSD::Integer(3);
ensure("hash: equivalent values but different types do not match.", boost::hash<LLSD>{}(data_r1) != boost::hash<LLSD>{}(data_i1));
}
{
LLSD data_a1 = llsd::array("A", "B", "C");
LLSD data_a2 = llsd::array("A", "B", "C");
ensure("hash: identical arrays produce identical results", boost::hash<LLSD>{}(data_a1) == boost::hash<LLSD>{}(data_a2));
data_a2.append(llsd::array(1, 2));
ensure("hash: changing the array changes the hash.", boost::hash<LLSD>{}(data_a1) != boost::hash<LLSD>{}(data_a2));
data_a1.append(llsd::array(1, 2));
ensure("hash: identical arrays produce identical results with nested arrays", boost::hash<LLSD>{}(data_a1) == boost::hash<LLSD>{}(data_a2));
}
{
LLSD data_m1 = LLSDMap("key1", LLSD::Real(3.0))("key2", "value2")("key3", llsd::array(1, 2, 3));
LLSD data_m2 = LLSDMap("key1", LLSD::Real(3.0))("key2", "value2")("key3", llsd::array(1, 2, 3));
ensure("hash: identical maps produce identical results", boost::hash<LLSD>{}(data_m1) == boost::hash<LLSD>{}(data_m2));
LLSD data_m3 = LLSDMap("key1", LLSD::Real(5.0))("key2", "value2")("key3", llsd::array(1, 2, 3));
ensure("hash: Different values in the map produce different hashes.", boost::hash<LLSD>{}(data_m1) != boost::hash<LLSD>{}(data_m3));
LLSD data_m4 = LLSDMap("keyA", LLSD::Real(3.0))("key2", "value2")("key3", llsd::array(1, 2, 3));
ensure("hash: Different keys in the map produce different hashes.", boost::hash<LLSD>{}(data_m1) != boost::hash<LLSD>{}(data_m4));
}
}
}
+173
View File
@@ -0,0 +1,173 @@
/**
* @file llservicebuilder_tut.cpp
* @brief LLServiceBuilder unit tests
* @date March 2007
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include <tut/tut.hpp>
#include "linden_common.h"
#include "lltut.h"
#include "llsd.h"
#include "llservicebuilder.h"
namespace tut
{
struct ServiceBuilderTestData {
LLServiceBuilder mServiceBuilder;
};
typedef test_group<ServiceBuilderTestData> ServiceBuilderTestGroup;
typedef ServiceBuilderTestGroup::object ServiceBuilderTestObject;
ServiceBuilderTestGroup serviceBuilderTestGroup("ServiceBuilder");
template<> template<>
void ServiceBuilderTestObject::test<1>()
{
//Simple service build and reply with no mapping
LLSD test_block;
test_block["service-builder"] = "/agent/name";
mServiceBuilder.createServiceDefinition("ServiceBuilderTest", test_block["service-builder"]);
std::string test_url = mServiceBuilder.buildServiceURI("ServiceBuilderTest");
ensure_equals("Basic URL Creation", test_url , "/agent/name");
}
template<> template<>
void ServiceBuilderTestObject::test<2>()
{
//Simple replace test
LLSD test_block;
test_block["service-builder"] = "/agent/{$agent-id}/name";
mServiceBuilder.createServiceDefinition("ServiceBuilderTest", test_block["service-builder"]);
LLSD data_map;
data_map["agent-id"] = "257c631f-a0c5-4f29-8a9f-9031feaae6c6";
std::string test_url = mServiceBuilder.buildServiceURI("ServiceBuilderTest", data_map);
ensure_equals("Replacement URL Creation", test_url , "/agent/257c631f-a0c5-4f29-8a9f-9031feaae6c6/name");
}
template<> template<>
void ServiceBuilderTestObject::test<3>()
{
//Incorrect service test
LLSD test_block;
test_block["service-builder"] = "/agent/{$agent-id}/name";
mServiceBuilder.createServiceDefinition("ServiceBuilderTest", test_block["service-builder"]);
std::string test_url = mServiceBuilder.buildServiceURI("ServiceBuilder");
ensure_equals("Replacement URL Creation for Non-existant Service", test_url , "");
}
template<> template<>
void ServiceBuilderTestObject::test<4>()
{
//Incorrect service test
LLSD test_block;
test_block["service-builder"] = "/agent/{$agent-id}/name";
mServiceBuilder.createServiceDefinition("ServiceBuilderTest", test_block["service-builder"]);
LLSD data_map;
data_map["agent_id"] = "257c631f-a0c5-4f29-8a9f-9031feaae6c6";
std::string test_url = mServiceBuilder.buildServiceURI("ServiceBuilderTest", data_map);
ensure_equals("Replacement URL Creation for Non-existant Service", test_url , "/agent/{$agent-id}/name");
}
template<> template<>
void ServiceBuilderTestObject::test<5>()
{
LLSD test_block;
test_block["service-builder"] = "/proc/{$proc}{%params}";
mServiceBuilder.createServiceDefinition("ServiceBuilderTest", test_block["service-builder"]);
LLSD data_map;
data_map["proc"] = "do/something/useful";
data_map["params"]["estate_id"] = 1;
data_map["params"]["query"] = "public";
std::string test_url = mServiceBuilder.buildServiceURI("ServiceBuilderTest", data_map);
ensure_equals(
"two part URL Creation",
test_url ,
"/proc/do/something/useful?estate_id=1&query=public");
}
template<> template<>
void ServiceBuilderTestObject::test<6>()
{
LLSD test_block;
test_block["service-builder"] = "Which way to the {${$baz}}?";
mServiceBuilder.createServiceDefinition(
"ServiceBuilderTest",
test_block["service-builder"]);
LLSD data_map;
data_map["foo"] = "bar";
data_map["baz"] = "foo";
std::string test_url = mServiceBuilder.buildServiceURI(
"ServiceBuilderTest",
data_map);
ensure_equals(
"recursive url creation",
test_url ,
"Which way to the bar?");
}
template<> template<>
void ServiceBuilderTestObject::test<7>()
{
LLSD test_block;
test_block["service-builder"] = "Which way to the {$foo}?";
mServiceBuilder.createServiceDefinition(
"ServiceBuilderTest",
test_block["service-builder"]);
LLSD data_map;
data_map["baz"] = "foo";
std::string test_url = mServiceBuilder.buildServiceURI(
"ServiceBuilderTest",
data_map);
ensure_equals(
"fails to do replacement",
test_url ,
"Which way to the {$foo}?");
}
template<> template<>
void ServiceBuilderTestObject::test<8>()
{
LLSD test_block;
test_block["service-builder"] = "/proc/{$proc}{%params}";
mServiceBuilder.createServiceDefinition(
"ServiceBuilderTest",
test_block["service-builder"]);
LLSD data_map;
data_map["proc"] = "do/something/useful";
data_map["params"] = LLSD();
std::string test_url = mServiceBuilder.buildServiceURI(
"ServiceBuilderTest",
data_map);
ensure_equals(
"strip params",
test_url ,
"/proc/do/something/useful");
}
}
+883
View File
@@ -0,0 +1,883 @@
/**
* @file llstreamtools_tut.cpp
* @author Adroit
* @date February 2007
* @brief llstreamtools test cases.
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include <tut/tut.hpp>
#include "linden_common.h"
#include "llstreamtools.h"
#include "lltut.h"
namespace tut
{
struct streamtools_data
{
};
typedef test_group<streamtools_data> streamtools_test;
typedef streamtools_test::object streamtools_object;
tut::streamtools_test streamtools_testcase("streamtools");
//test cases for skip_whitespace()
template<> template<>
void streamtools_object::test<1>()
{
char arr[255];
std::string str;
std::string expected_result;
std::string actual_result;
std::istringstream is;
is.str(str = "");
ensure("skip_whitespace: empty string", (false == skip_whitespace(is)));
is.clear();
is.str(str = " SecondLife is a 3D World");
skip_whitespace(is);
is.get(arr, 255, '\0');
expected_result = "SecondLife is a 3D World";
ensure_equals("skip_whitespace: space", arr, expected_result);
is.clear();
is.str(str = "\t \tSecondLife is a 3D World");
skip_whitespace(is);
is.get(arr, 255, '\0');
expected_result = "SecondLife is a 3D World";
ensure_equals("skip_whitespace: space and tabs", arr, expected_result);
is.clear();
is.str(str = "\t \tSecondLife is a 3D World ");
skip_whitespace(is);
is.get(arr, 255, '\0');
expected_result = "SecondLife is a 3D World ";
ensure_equals("skip_whitespace: space at end", arr, expected_result);
is.clear();
is.str(str = "\t \r\nSecondLife is a 3D World");
skip_whitespace(is);
is.get(arr, 255, '\0');
expected_result = "\r\nSecondLife is a 3D World";
ensure_equals("skip_whitespace: space at end", arr, expected_result);
}
//testcases for skip_emptyspaces()
template<> template<>
void streamtools_object::test<2>()
{
char arr[255];
std::string str;
std::string expected_result;
std::string actual_result;
std::istringstream is;
bool ret;
is.clear();
is.str(str = " \tSecondLife is a 3D World.\n");
skip_emptyspace(is);
is.get(arr, 255, '\0');
expected_result = "SecondLife is a 3D World.\n";
ensure_equals("skip_emptyspace: space and tabs", arr, expected_result);
is.clear();
is.str(str = " \t\r\n \r SecondLife is a 3D World.\n");
skip_emptyspace(is);
is.get(arr, 255, '\0');
expected_result = "SecondLife is a 3D World.\n";
ensure_equals("skip_emptyspace: space, tabs, carriage return, newline", arr, expected_result);
is.clear();
is.str(str = "");
ret = skip_emptyspace(is);
is.get(arr, 255, '\0');
ensure("skip_emptyspace: empty string", ret == false);
is.clear();
is.str(str = " \r\n \t ");
ret = skip_emptyspace(is);
is.get(arr, 255, '\0');
ensure("skip_emptyspace: space newline empty", ret == false);
}
//testcases for skip_comments_and_emptyspace()
template<> template<>
void streamtools_object::test<3>()
{
char arr[255];
std::string str;
std::string expected_result;
std::string actual_result;
std::istringstream is;
bool ret;
is.clear();
is.str(str = " \t\r\n \r SecondLife is a 3D World.\n");
skip_comments_and_emptyspace(is);
is.get(arr, 255, '\0');
expected_result = "SecondLife is a 3D World.\n";
ensure_equals("skip_comments_and_emptyspace: space, tabs, carriage return, newline", arr, expected_result);
is.clear();
is.str(str = "# \r\n SecondLife is a 3D World.");
skip_comments_and_emptyspace(is);
is.get(arr, 255, '\0');
expected_result = "SecondLife is a 3D World.";
ensure_equals("skip_comments_and_emptyspace: skip comment - 1", arr, expected_result);
is.clear();
is.str(str = "# \r\n # SecondLife is a 3D World. ##");
ensure("should not be good()", ! skip_comments_and_emptyspace(is));
ensure("should be at eof()", is.eof());
// don't get(): given bad state, we can't rely on results
is.clear();
is.str(str = " \r\n SecondLife is a 3D World. ##");
skip_comments_and_emptyspace(is);
is.get(arr, 255, '\0');
expected_result = "SecondLife is a 3D World. ##";
ensure_equals("skip_comments_and_emptyspace: skip comment - 3", arr, expected_result);
is.clear();
is.str(str = "");
ret = skip_comments_and_emptyspace(is);
ensure("skip_comments_and_emptyspace: empty string", ! ret);
is.clear();
is.str(str = " \r\n \t # SecondLife is a 3D World");
ret = skip_comments_and_emptyspace(is);
ensure("skip_comments_and_emptyspace: space newline comment empty", ! ret);
}
//testcases for skip_line()
template<> template<>
void streamtools_object::test<4>()
{
char arr[255];
std::string str;
std::string expected_result;
std::string actual_result;
std::istringstream is;
bool ret;
is.clear();
is.str(str = "SecondLife is a 3D World.\n\n It provides an opportunity to the site \nuser to perform real life activities in virtual world.");
skip_line(is);
is.get(arr, 255, '\0');
expected_result = "\n It provides an opportunity to the site \nuser to perform real life activities in virtual world.";
ensure_equals("skip_line: 1 newline", arr, expected_result);
is.clear();
is.str(expected_result);
skip_line(is);
is.get(arr, 255, '\0');
expected_result = " It provides an opportunity to the site \nuser to perform real life activities in virtual world.";
ensure_equals("skip_line: 2 newline", arr, expected_result);
is.clear();
is.str(expected_result);
skip_line(is);
is.get(arr, 255, '\0');
expected_result = "user to perform real life activities in virtual world.";
ensure_equals("skip_line: 3 newline", arr, expected_result);
is.clear();
is.str(str = "");
ret = skip_line(is);
ensure("skip_line: empty string", ret == false);
}
// testcases for skip_to_next_word()
template<> template<>
void streamtools_object::test<5>()
{
char arr[255];
std::string str;
std::string expected_result;
std::string actual_result;
std::istringstream is;
bool ret;
is.clear();
is.str(str = "SecondLife is a 3D_World.\n\n It-provides an opportunity to the site \nuser to perform real life activities in virtual world.");
skip_to_next_word(is); // get past SecondLife
is.get(arr, 255, '\0');
expected_result = "is a 3D_World.\n\n It-provides an opportunity to the site \nuser to perform real life activities in virtual world.";
ensure_equals("skip_to_next_word: 1", arr, expected_result);
is.clear();
is.str(expected_result);
skip_to_next_word(is); // get past is
skip_to_next_word(is); // get past a
skip_to_next_word(is); // get past 3D_World.\n\n
is.get(arr, 255, '\0');
expected_result = "It-provides an opportunity to the site \nuser to perform real life activities in virtual world.";
ensure_equals("skip_to_next_word: get past .\n\n 2", arr, expected_result);
is.clear();
is.str(expected_result);
skip_to_next_word(is); // get past It-
expected_result = "provides an opportunity to the site \nuser to perform real life activities in virtual world.";
is.get(arr, 255, '\0');
ensure_equals("skip_to_next_word: get past -", arr, expected_result);
is.clear();
is.str(str = "");
ret = skip_to_next_word(is);
ensure("skip_line: empty string", ret == false);
is.clear();
is.str(str = " \r\n\r\n");
ret = skip_to_next_word(is);
ensure("skip_line: space new lines", ret == false);
}
//testcases for skip_to_end_of_next_keyword()
template<> template<>
void streamtools_object::test<6>()
{
char arr[255];
std::string str;
std::string expected_result;
std::string actual_result;
std::istringstream is;
bool ret;
is.clear();
is.str(str = "FIRSTKEY followed by second delimiter\nSECONDKEY\t SecondValue followed by third delimiter \nSECONDKEY\nFOURTHKEY FOURTHVALUEis a 3DWorld.");
ret = skip_to_end_of_next_keyword("FIRSTKEY", is);
is.get(arr, 255, '\0');
expected_result = " followed by second delimiter\nSECONDKEY\t SecondValue followed by third delimiter \nSECONDKEY\nFOURTHKEY FOURTHVALUEis a 3DWorld.";
ensure_equals("skip_to_end_of_next_keyword: 1", arr, expected_result);
is.clear();
is.str(expected_result);
ret = skip_to_end_of_next_keyword("SECONDKEY", is);
is.get(arr, 255, '\0');
expected_result = "\t SecondValue followed by third delimiter \nSECONDKEY\nFOURTHKEY FOURTHVALUEis a 3DWorld.";
ensure_equals("skip_to_end_of_next_keyword: 2", arr, expected_result);
is.clear();
is.str(expected_result);
ret = skip_to_end_of_next_keyword("SECONDKEY", is);
is.get(arr, 255, '\0');
expected_result = "\nFOURTHKEY FOURTHVALUEis a 3DWorld.";
ensure_equals("skip_to_end_of_next_keyword: 3", arr, expected_result);
is.clear();
is.str(expected_result);
ret = skip_to_end_of_next_keyword("FOURTHKEY", is);
is.get(arr, 255, '\0');
expected_result = " FOURTHVALUEis a 3DWorld.";
ensure_equals("skip_to_end_of_next_keyword: 4", arr, expected_result);
is.clear();
is.str(str = "{should be skipped as newline/space/tab does not follow but this one should be picked\n { Does it?\n");
ret = skip_to_end_of_next_keyword("{", is);
is.get(arr, 255, '\0');
expected_result = " Does it?\n";
ensure_equals("skip_to_end_of_next_keyword: multiple delim matches on same line", arr, expected_result);
is.clear();
is.str(str = "Delim { could not be found at start");
ret = skip_to_end_of_next_keyword("{", is);
ensure("skip_to_end_of_next_keyword: delim should not be present", ret == false);
is.clear();
is.str(str = "Empty Delim");
ret = skip_to_end_of_next_keyword("", is);
ensure("skip_to_end_of_next_keyword: empty delim should not be valid", ret == false);
is.clear();
is.str(str = "");
ret = skip_to_end_of_next_keyword("}", is);
ensure("skip_to_end_of_next_keyword: empty string", ret == false);
}
//testcases for get_word(std::string& output_string, std::istream& input_stream)
template<> template<>
void streamtools_object::test<7>()
{
std::string str;
std::string expected_result;
std::string actual_result;
std::istringstream is;
bool ret;
is.clear();
is.str(str = " First Second \t \r \n Third Fourth-ShouldThisBePartOfFourth Fifth\n");
actual_result = "";
ret = get_word(actual_result, is);
expected_result = "First";
ensure_equals("get_word: 1", actual_result, expected_result);
actual_result = "";
ret = get_word(actual_result, is);
expected_result = "Second";
ensure_equals("get_word: 2", actual_result, expected_result);
actual_result = "";
ret = get_word(actual_result, is);
expected_result = "Third";
ensure_equals("get_word: 3", actual_result, expected_result);
// the current implementation of get_word seems inconsistent with
// skip_to_next_word. skip_to_next_word treats any character other
// than alhpa-numeric and '_' as a delimter, while get_word()
// treats only isspace() (i.e. space, form-feed('\f'), newline ('\n'),
// carriage return ('\r'), horizontal tab ('\t'), and vertical tab ('\v')
// as delimiters
actual_result = "";
ret = get_word(actual_result, is); // will copy Fourth-ShouldThisBePartOfFourth
expected_result = "Fourth-ShouldThisBePartOfFourth"; // as per current impl.
ensure_equals("get_word: 4", actual_result, expected_result);
actual_result = "";
ret = get_word(actual_result, is); // will copy Fifth
expected_result = "Fifth"; // as per current impl.
ensure_equals("get_word: 5", actual_result, expected_result);
is.clear();
is.str(str = " \t \r \n ");
actual_result = "";
ret = get_word(actual_result, is);
ensure("get_word: empty all spaces, newline tabs", ret == false);
is.clear();
is.str(str = "");
actual_result = "";
ret = get_word(actual_result, is);
ensure("get_word: empty string", ret == false);
}
// testcase for get_word and skip_to_next_word compatibility
template<> template<>
void streamtools_object::test<8>()
{
std::string str;
std::string expected_result;
std::string actual_result;
std::istringstream is;
is.clear();
is.str(str = " First Second \t \r \n Third Fourth-ShouldThisBePartOfFourth Fifth\n");
actual_result = "";
get_word(actual_result, is); // First
actual_result = "";
get_word(actual_result, is); // Second
actual_result = "";
get_word(actual_result, is); // Third
// the current implementation of get_word seems inconsistent with
// skip_to_next_word. skip_to_next_word treats any character other
// than alhpa-numeric and '_' as a delimter, while get_word()
// treats only isspace() (i.e. space, form-feed('\f'), newline ('\n'),
// carriage return ('\r'), horizontal tab ('\t'), and vertical tab ('\v')
// as delimiters
actual_result = "";
get_word(actual_result, is); // will copy Fourth-ShouldThisBePartOfFourth
actual_result = "";
get_word(actual_result, is); // will copy Fifth
is.clear();
is.str(str = " First Second \t \r \n Third Fourth_ShouldThisBePartOfFourth Fifth\n");
skip_to_next_word(is); // should now point to First
skip_to_next_word(is); // should now point to Second
skip_to_next_word(is); // should now point to Third
skip_to_next_word(is); // should now point to Fourth
skip_to_next_word(is); // should now point to ShouldThisBePartOfFourth
expected_result = "";
// will copy ShouldThisBePartOfFourth, the fifth word,
// while using get_word above five times result in getting "Fifth"
get_word(expected_result, is);
ensure_equals("get_word: skip_to_next_word compatibility", actual_result, expected_result);
}
//testcases for get_word(std::string& output_string, std::istream& input_stream, int n)
template<> template<>
void streamtools_object::test<9>()
{
std::string str;
std::string expected_result;
std::string actual_result;
std::istringstream is;
bool ret;
is.clear();
is.str(str = " First Second \t \r \n Third Fourth-ShouldThisBePartOfFourth Fifth\n");
actual_result = "";
ret = get_word(actual_result, is, 255);
expected_result = "First";
ensure_equals("get_word: 1", actual_result, expected_result);
actual_result = "";
ret = get_word(actual_result, is, 4);
expected_result = "Seco"; // should be cut short
ensure_equals("get_word: 2", actual_result, expected_result);
actual_result = "";
ret = get_word(actual_result, is, 255);
expected_result = "nd"; // get remainder of Second
ensure_equals("get_word: 3", actual_result, expected_result);
actual_result = "";
ret = get_word(actual_result, is, 0); // 0 size string
expected_result = ""; // get remainder of Second
ensure_equals("get_word: 0 sized output", actual_result, expected_result);
actual_result = "";
ret = get_word(actual_result, is, 255);
expected_result = "Third";
ensure_equals("get_word: 4", actual_result, expected_result);
is.clear();
is.str(str = " \t \r \n ");
actual_result = "";
ret = get_word(actual_result, is, 255);
ensure("get_word: empty all spaces, newline tabs", ret == false);
is.clear();
is.str(str = "");
actual_result = "";
ret = get_word(actual_result, is, 255);
ensure("get_word: empty string", ret == false);
}
//test cases for get_line(std::string& output_string, std::istream& input_stream)
template<> template<>
void streamtools_object::test<10>()
{
std::string str;
std::string expected_result;
std::string actual_result;
std::istringstream is;
is.clear();
is.str(str = "First Second \t \r\n Third Fourth-ShouldThisBePartOfFourth IsThisFifth\n");
actual_result = "";
get_line(actual_result, is);
expected_result = "First Second \t \r\n";
ensure_equals("get_line: 1", actual_result, expected_result);
actual_result = "";
get_line(actual_result, is);
expected_result = " Third Fourth-ShouldThisBePartOfFourth IsThisFifth\n";
ensure_equals("get_line: 2", actual_result, expected_result);
is.clear();
is.str(str = "\nFirst Line.\n\nSecond Line.\n");
actual_result = "";
get_line(actual_result, is);
expected_result = "\n";
ensure_equals("get_line: First char as newline", actual_result, expected_result);
actual_result = "";
get_line(actual_result, is);
expected_result = "First Line.\n";
ensure_equals("get_line: 3", actual_result, expected_result);
actual_result = "";
get_line(actual_result, is);
expected_result = "\n";
ensure_equals("get_line: 4", actual_result, expected_result);
actual_result = "";
get_line(actual_result, is);
expected_result = "Second Line.\n";
ensure_equals("get_line: 5", actual_result, expected_result);
}
//test cases for get_line(std::string& output_string, std::istream& input_stream)
template<> template<>
void streamtools_object::test<11>()
{
std::string str;
std::string expected_result;
std::string actual_result;
std::istringstream is;
bool ret;
is.clear();
is.str(str = "One Line only with no newline");
actual_result = "";
ret = get_line(actual_result, is);
expected_result = "One Line only with no newline";
ensure_equals("get_line: No newline", actual_result, expected_result);
ensure_equals("return value is good state of stream", ret, is.good());
}
//test cases for get_line(std::string& output_string, std::istream& input_stream)
template<> template<>
void streamtools_object::test<12>()
{
std::string str;
std::string expected_result;
std::string actual_result;
std::istringstream is;
// need to be check if this test case is wrong or the implementation is wrong.
is.clear();
is.str(str = "Should not skip lone \r.\r\n");
actual_result = "";
get_line(actual_result, is);
expected_result = "Should not skip lone \r.\r\n";
ensure_equals("get_line: carriage return skipped even though not followed by newline", actual_result, expected_result);
}
//test cases for get_line(std::string& output_string, std::istream& input_stream)
template<> template<>
void streamtools_object::test<13>()
{
std::string str;
std::string expected_result;
std::string actual_result;
std::istringstream is;
is.clear();
is.str(str = "\n");
actual_result = "";
get_line(actual_result, is);
expected_result = "\n";
ensure_equals("get_line: Just newline", actual_result, expected_result);
}
//testcases for get_line(std::string& output_string, std::istream& input_stream, int n)
template<> template<>
void streamtools_object::test<14>()
{
std::string str;
std::string expected_result;
std::string actual_result;
std::istringstream is;
is.clear();
is.str(str = "First Line.\nSecond Line.\n");
actual_result = "";
get_line(actual_result, is, 255);
expected_result = "First Line.\n";
ensure_equals("get_line: Basic Operation", actual_result, expected_result);
actual_result = "";
get_line(actual_result, is, sizeof("Second")-1);
expected_result = "Second\n";
ensure_equals("get_line: Insufficient length 1", actual_result, expected_result);
actual_result = "";
get_line(actual_result, is, 255);
expected_result = " Line.\n";
ensure_equals("get_line: Remainder after earlier insufficient length", actual_result, expected_result);
is.clear();
is.str(str = "One Line only with no newline with limited length");
actual_result = "";
get_line(actual_result, is, sizeof("One Line only with no newline with limited length")-1);
expected_result = "One Line only with no newline with limited length\n";
ensure_equals("get_line: No newline with limited length", actual_result, expected_result);
is.clear();
is.str(str = "One Line only with no newline");
actual_result = "";
get_line(actual_result, is, 255);
expected_result = "One Line only with no newline";
ensure_equals("get_line: No newline", actual_result, expected_result);
}
//testcases for get_line(std::string& output_string, std::istream& input_stream, int n)
template<> template<>
void streamtools_object::test<15>()
{
std::string str;
std::string expected_result;
std::string actual_result;
std::istringstream is;
bool ret;
is.clear();
is.str(str = "One Line only with no newline");
actual_result = "";
ret = get_line(actual_result, is, 255);
expected_result = "One Line only with no newline";
ensure_equals("get_line: No newline", actual_result, expected_result);
ensure_equals("return value is good state of stream", ret, is.good());
}
//testcases for remove_last_char()
template<> template<>
void streamtools_object::test<16>()
{
std::string str;
std::string expected_result;
bool ret;
str = "SecondLife is a 3D World";
ret = remove_last_char('d',str);
expected_result = "SecondLife is a 3D Worl";
ensure_equals("remove_last_char: should remove last char", str, expected_result);
str = "SecondLife is a 3D World";
ret = remove_last_char('W',str);
expected_result = "SecondLife is a 3D World";
ensure_equals("remove_last_char: should not remove as it is not last char", str, expected_result);
ensure("remove_last_char: should return false", ret == false);
str = "SecondLife is a 3D World\n";
ret = remove_last_char('\n',str);
expected_result = "SecondLife is a 3D World";
ensure_equals("remove_last_char: should remove last newline", str, expected_result);
ensure("remove_last_char: should remove newline and return true", ret == true);
}
//testcases for unescaped_string()
template<> template<>
void streamtools_object::test<17>()
{
std::string str;
std::string expected_result;
str = "SecondLife is a 3D world \\n";
unescape_string(str);
expected_result = "SecondLife is a 3D world \n";
ensure_equals("unescape_string: newline", str, expected_result);
str = "SecondLife is a 3D world \\\\t \\n";
unescape_string(str);
expected_result = "SecondLife is a 3D world \\t \n";
ensure_equals("unescape_string: backslash and newline", str, expected_result);
str = "SecondLife is a 3D world \\ ";
unescape_string(str);
expected_result = "SecondLife is a 3D world \\ ";
ensure_equals("unescape_string: insufficient to unescape", str, expected_result);
str = "SecondLife is a 3D world \\n \\n \\n \\\\\\n";
unescape_string(str);
expected_result = "SecondLife is a 3D world \n \n \n \\\n";
ensure_equals("unescape_string: multipel newline and backslash", str, expected_result);
str = "SecondLife is a 3D world \\t";
unescape_string(str);
expected_result = "SecondLife is a 3D world \\t";
ensure_equals("unescape_string: leaves tab as is", str, expected_result);
str = "\\n";
unescape_string(str);
expected_result = "\n";
ensure_equals("unescape_string: only a newline", str, expected_result);
}
//testcases for escape_string()
template<> template<>
void streamtools_object::test<18>()
{
std::string str;
std::string expected_result;
str = "SecondLife is a 3D world \n";
escape_string(str);
expected_result = "SecondLife is a 3D world \\n";
ensure_equals("escape_string: newline", str, expected_result);
str = "SecondLife is a 3D world \\t \n";
escape_string(str);
expected_result = "SecondLife is a 3D world \\\\t \\n";
ensure_equals("escape_string: backslash and newline", str, expected_result);
str = "SecondLife is a 3D world \n \n \n \\\n";
escape_string(str);
expected_result = "SecondLife is a 3D world \\n \\n \\n \\\\\\n";
ensure_equals("escape_string: multipel newline and backslash", str, expected_result);
str = "SecondLife is a 3D world \t";
escape_string(str);
expected_result = "SecondLife is a 3D world \t";
ensure_equals("unescape_string: leaves tab as is", str, expected_result);
str = "\n";
escape_string(str);
expected_result = "\\n";
ensure_equals("unescape_string: only a newline", str, expected_result);
// serialization/deserialization escape->unescape
str = "SecondLife is a 3D world \n \n \n \\\n";
escape_string(str);
unescape_string(str);
expected_result = "SecondLife is a 3D world \n \n \n \\\n";
ensure_equals("escape_string: should preserve with escape/unescape", str, expected_result);
// serialization/deserialization unescape->escape
str = "SecondLife is a 3D world \\n \\n \\n \\\\";
unescape_string(str);
escape_string(str);
expected_result = "SecondLife is a 3D world \\n \\n \\n \\\\";
ensure_equals("escape_string: should preserve with unescape/escape", str, expected_result);
}
// testcases for replace_newlines_with_whitespace()
template<> template<>
void streamtools_object::test<19>()
{
std::string str;
std::string expected_result;
str = "SecondLife is a 3D \n\nworld\n";
replace_newlines_with_whitespace(str);
expected_result = "SecondLife is a 3D world ";
ensure_equals("replace_newlines_with_whitespace: replace all newline", str, expected_result);
str = "\nSecondLife is a 3D world\n";
replace_newlines_with_whitespace(str);
expected_result = " SecondLife is a 3D world ";
ensure_equals("replace_newlines_with_whitespace: begin and newline", str, expected_result);
str = "SecondLife is a 3D world\r\t";
replace_newlines_with_whitespace(str);
expected_result = "SecondLife is a 3D world\r\t";
ensure_equals("replace_newlines_with_whitespace: should only replace newline", str, expected_result);
str = "";
replace_newlines_with_whitespace(str);
expected_result = "";
ensure_equals("replace_newlines_with_whitespace: empty string", str, expected_result);
}
//testcases for remove_double_quotes()
template<> template<>
void streamtools_object::test<20>()
{
std::string str;
std::string expected_result;
str = "SecondLife is a \"\"3D world";
remove_double_quotes(str);
expected_result = "SecondLife is a 3D world";
ensure_equals("remove_double_quotes: replace empty doube quotes", str, expected_result);
str = "SecondLife is a \"3D world";
remove_double_quotes(str);
expected_result = "SecondLife is a 3D world";
ensure_equals("remove_double_quotes: keep as is it matching quote not found", str, expected_result);
}
// testcases for get_brace_count()
template<> template<>
void streamtools_object::test<21>()
{
}
//testcases for get_keyword_and_value()
template<> template<>
void streamtools_object::test<22>()
{
std::string s = "SecondLife is a 3D World";
std::string keyword;
std::string value;
get_keyword_and_value(keyword, value, s);
ensure("get_keyword_and_value: Unable to get Keyword and Value", ((keyword == "SecondLife") && (value == "is a 3D World")));
s = "SecondLife";
get_keyword_and_value(keyword, value, s);
ensure("get_keyword_and_value: value should be empty", ((keyword == "SecondLife") && (value == "")));
s = "SecondLife \t is cool! \n";
get_keyword_and_value(keyword, value, s);
ensure("get_keyword_and_value: remove space before value but not after", ((keyword == "SecondLife") && (value == "is cool! ")));
}
//testcases for get_keyword_and_value()
template<> template<>
void streamtools_object::test<23>()
{
std::string s;
std::string keyword = "SOME PRIOR KEYWORD";
std::string value = "SOME PRIOR VALUE";
s = "SecondLife\n";
get_keyword_and_value(keyword, value, s);
ensure("get_keyword_and_value: terminated with newline. value should be empty", ((keyword == "SecondLife") && (value == "")));
}
//testcases for get_keyword_and_value()
template<> template<>
void streamtools_object::test<24>()
{
std::string s;
std::string keyword = "SOME PRIOR KEYWORD";
std::string value = "SOME PRIOR VALUE";
s = "";
get_keyword_and_value(keyword, value, s);
ensure("get_keyword_and_value: empty string. keyword value should empty", ((keyword == "") && (value == "")));
}
//testcase for fullread()
template<> template<>
void streamtools_object::test<25>()
{
std::string str = "First Line.\nSecond Line\n";
std::istringstream is(str);
char buf[255] = {0};
fullread(is, buf, 255);
ensure_memory_matches("fullread: read with newlines", (void*) buf, static_cast<U32>(str.size())-1, (void*) str.c_str(), static_cast<U32>(str.size())-1);
is.clear();
is.str(str = "First Line.\nSecond Line\n");
memset(buf, 0, 255);
char expected_string[] = "First Line.\nSecond";
int len = sizeof(expected_string)-1;
fullread(is, buf, len);
ensure_memory_matches("fullread: read with newlines", (void*) buf, len, (void*) &expected_string, len);
}
// testcases for operator >>
template<> template<>
void streamtools_object::test<26>()
{
char arr[255];
std::string str;
std::string toCheck = "SecondLife" ;
std::string expected_result;
std::istringstream stream("SecondLife is a 3D World");
stream >> toCheck.c_str();
stream.get(arr, 255, '\0');
expected_result = " is a 3D World";
ensure_equals("istream << operator", arr, expected_result);
stream.clear();
stream.str(str = "SecondLife is a 3D World");
toCheck = "is";
stream >> toCheck.c_str();
ensure("istream << operator should have failed", stream.good() == false);
}
}
+971
View File
@@ -0,0 +1,971 @@
/**
* @file lltemplatemessagebuilder_tut.cpp
* @date 2007-04
* @brief Tests for building messages.
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include <tut/tut.hpp>
#include "linden_common.h"
#include "lltut.h"
#include "llapr.h"
#include "llmessagetemplate.h"
#include "llmath.h"
#include "llquaternion.h"
#include "lltemplatemessagebuilder.h"
#include "lltemplatemessagereader.h"
#include "message_prehash.h"
#include "u64.h"
#include "v3dmath.h"
#include "v3math.h"
#include "v4math.h"
namespace tut
{
static LLTemplateMessageBuilder::message_template_name_map_t nameMap;
static LLTemplateMessageReader::message_template_number_map_t numberMap;
struct LLTemplateMessageBuilderTestData
{
static LLMessageTemplate defaultTemplate()
{
static bool init = false;
if(! init)
{
ll_init_apr();
const F32 circuit_heartbeat_interval=5;
const F32 circuit_timeout=100;
start_messaging_system("notafile", 13035,
1,
0,
0,
false,
"notasharedsecret",
NULL,
false,
circuit_heartbeat_interval,
circuit_timeout);
//init_prehash_data();
init = true;
}
return LLMessageTemplate(_PREHASH_TestMessage, 1, MFT_HIGH);
}
static LLMessageBlock* defaultBlock(const EMsgVariableType type = MVT_NULL, const S32 size = 0, EMsgBlockType block = MBT_VARIABLE)
{
return createBlock(const_cast<char*>(_PREHASH_Test0), type, size, block);
}
static LLMessageBlock* createBlock(char* name, const EMsgVariableType type = MVT_NULL, const S32 size = 0, EMsgBlockType block = MBT_VARIABLE)
{
LLMessageBlock* result = new LLMessageBlock(name, block);
if(type != MVT_NULL)
{
result->addVariable(const_cast<char*>(_PREHASH_Test0), type, size);
}
return result;
}
static LLTemplateMessageBuilder* defaultBuilder(LLMessageTemplate& messageTemplate, char* name = const_cast<char*>(_PREHASH_Test0))
{
nameMap[_PREHASH_TestMessage] = &messageTemplate;
LLTemplateMessageBuilder* builder = new LLTemplateMessageBuilder(nameMap);
builder->newMessage(_PREHASH_TestMessage);
builder->nextBlock(name);
return builder;
}
/** Takes ownership of builder */
static LLTemplateMessageReader* setReader(
LLMessageTemplate& messageTemplate,
LLTemplateMessageBuilder* builder,
U8 offset = 0)
{
numberMap[1] = &messageTemplate;
const U32 bufferSize = 1024;
U8 buffer[bufferSize];
// zero out the packet ID field
memset(buffer, 0, LL_PACKET_ID_SIZE);
U32 builtSize = builder->buildMessage(buffer, bufferSize, offset);
delete builder;
LLTemplateMessageReader* reader = new LLTemplateMessageReader(numberMap);
reader->validateMessage(buffer, builtSize, LLHost());
reader->readMessage(buffer, LLHost());
return reader;
}
};
typedef test_group<LLTemplateMessageBuilderTestData> LLTemplateMessageBuilderTestGroup;
typedef LLTemplateMessageBuilderTestGroup::object LLTemplateMessageBuilderTestObject;
LLTemplateMessageBuilderTestGroup templateMessageBuilderTestGroup("LLTemplateMessageBuilder");
template<> template<>
void LLTemplateMessageBuilderTestObject::test<1>()
// construction and test of undefined
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock());
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<2>()
// bool
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_BOOL, 1));
bool outValue, inValue = true;
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addBOOL(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
reader->getBOOL(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure bool", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<3>()
// U8
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_U8, 1));
U8 outValue, inValue = 2;
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addU8(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
reader->getU8(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure U8", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<4>()
// S16
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_S16, 2));
S16 outValue, inValue = 90;
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addS16(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
reader->getS16(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure S16", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<5>()
// U16
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_U16, 2));
U16 outValue, inValue = 3;
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addU16(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
reader->getU16(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure U16", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<6>()
// S32
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_S32, 4));
S32 outValue, inValue = 44;
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addS32(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
reader->getS32(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure S32", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<7>()
// F32
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_F32, 4));
F32 outValue, inValue = 121.44f;
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addF32(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
reader->getF32(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure F32", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<8>()
// U32
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_U32, 4));
U32 outValue, inValue = 88;
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addU32(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure U32", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<9>()
// U64
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_U64, 8));
U64 outValue, inValue = 121;
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addU64(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
reader->getU64(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure U64", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<10>()
// F64
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_F64, 8));
F64 outValue, inValue = 3232143.33;
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addF64(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
reader->getF64(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure F64", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<11>()
// Vector3
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_LLVector3, 12));
LLVector3 outValue, inValue = LLVector3(1,2,3);
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addVector3(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
reader->getVector3(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure LLVector3", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<12>()
// Vector4
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_LLVector4, 16));
LLVector4 outValue, inValue = LLVector4(1,2,3,4);
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addVector4(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
reader->getVector4(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure LLVector4", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<13>()
// Vector3d
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_LLVector3d, 24));
LLVector3d outValue, inValue = LLVector3d(1,2,3);
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addVector3d(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
reader->getVector3d(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure LLVector3d", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<14>()
// Quaternion
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_LLQuaternion, 12));
LLQuaternion outValue, inValue = LLQuaternion(0.0f, LLVector3(0.3713907f, 0.5570861f, 0.7427813f));
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addQuat(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
reader->getQuat(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure LLQuaternion", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<15>()
// UUID
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_LLUUID, 16));
LLUUID outValue, inValue;
inValue.generate();
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addUUID(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
reader->getUUID(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure UUID", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<16>()
// IPAddr
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_IP_ADDR, 4));
U32 outValue, inValue = 12344556;
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addIPAddr(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
reader->getIPAddr(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure IPAddr", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<17>()
// IPPort
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_IP_PORT, 2));
U16 outValue, inValue = 80;
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addIPPort(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
reader->getIPPort(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure IPPort", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<18>()
// String
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_VARIABLE, 1));
std::string outValue, inValue = "testing";
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addString(_PREHASH_Test0, inValue.c_str());
LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
char buffer[MAX_STRING];
reader->getString(_PREHASH_Test0, _PREHASH_Test0, MAX_STRING, buffer);
outValue = buffer;
ensure_equals("Ensure String", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<19>()
// block name !-> binary order
{
U8 buffer1[MAX_BUFFER_SIZE];
memset(buffer1, 0, MAX_BUFFER_SIZE);
U8 buffer2[MAX_BUFFER_SIZE];
memset(buffer2, 0, MAX_BUFFER_SIZE);
U32 bufferSize1, bufferSize2;
// build template: Test0 before Test1
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test0), MVT_U32, 4, MBT_SINGLE));
messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_U32, 4, MBT_SINGLE));
// build message: 1st declared block var == 0xaaaa, 2nd declared block var == 0xbbbb
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate, const_cast<char*>(_PREHASH_Test0));
builder->addU32(_PREHASH_Test0, 0xaaaa);
builder->nextBlock(_PREHASH_Test1);
builder->addU32(_PREHASH_Test0, 0xbbbb);
bufferSize1 = builder->buildMessage(buffer1, MAX_BUFFER_SIZE, 0);
delete builder;
// build template: Test1 before Test0
messageTemplate = defaultTemplate();
messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_U32, 4, MBT_SINGLE));
messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test0), MVT_U32, 4, MBT_SINGLE));
// build message: 1st declared block var == 0xaaaa, 2nd declared block var == 0xbbbb
builder = defaultBuilder(messageTemplate, const_cast<char*>(_PREHASH_Test1));
builder->addU32(_PREHASH_Test0, 0xaaaa);
builder->nextBlock(_PREHASH_Test0);
builder->addU32(_PREHASH_Test0, 0xbbbb);
bufferSize2 = builder->buildMessage(buffer2, MAX_BUFFER_SIZE, 0);
delete builder;
ensure_equals("Ensure Buffer Sizes Equal", bufferSize1, bufferSize2);
ensure_equals("Ensure Buffer Contents Equal", memcmp(buffer1, buffer2, bufferSize1), 0);
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<20>()
// block build order !-> binary order
{
U8 buffer1[MAX_BUFFER_SIZE];
memset(buffer1, 0, MAX_BUFFER_SIZE);
U8 buffer2[MAX_BUFFER_SIZE];
memset(buffer2, 0, MAX_BUFFER_SIZE);
U32 bufferSize1, bufferSize2;
// build template: Test0 before Test1
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test0), MVT_U32, 4, MBT_SINGLE));
messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_U32, 4, MBT_SINGLE));
// build message: 1st declared block var == 0xaaaa, 2nd declared block var == 0xbbbb
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate, const_cast<char*>(_PREHASH_Test0));
builder->addU32(_PREHASH_Test0, 0xaaaa);
builder->nextBlock(_PREHASH_Test1);
builder->addU32(_PREHASH_Test0, 0xbbbb);
bufferSize1 = builder->buildMessage(buffer1, MAX_BUFFER_SIZE, 0);
delete builder;
// build message: 1st declared block var == 0xaaaa, 2nd declared block var == 0xbbbb
builder = defaultBuilder(messageTemplate, const_cast<char*>(_PREHASH_Test1));
builder->addU32(_PREHASH_Test0, 0xbbbb);
builder->nextBlock(_PREHASH_Test0);
builder->addU32(_PREHASH_Test0, 0xaaaa);
bufferSize2 = builder->buildMessage(buffer2, MAX_BUFFER_SIZE, 0);
delete builder;
ensure_equals("Ensure Buffer Sizes Equal", bufferSize1, bufferSize2);
ensure_equals("Ensure Buffer Contents Equal", memcmp(buffer1, buffer2, bufferSize1), 0);
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<21>()
// block appended in declaration -> data appended in binary
{
U8 buffer1[MAX_BUFFER_SIZE];
memset(buffer1, 0, MAX_BUFFER_SIZE);
U8 buffer2[MAX_BUFFER_SIZE];
memset(buffer2, 0, MAX_BUFFER_SIZE);
U32 bufferSize1, bufferSize2;
// Build template: Test0 only
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test0), MVT_U32, 4, MBT_SINGLE));
// Build message
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate, const_cast<char*>(_PREHASH_Test0));
builder->addU32(_PREHASH_Test0, 0xaaaa);
bufferSize1 = builder->buildMessage(buffer1, MAX_BUFFER_SIZE, 0);
delete builder;
// Build template: Test0 before Test1
messageTemplate = defaultTemplate();
messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test0), MVT_U32, 4, MBT_SINGLE));
messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_U32, 4, MBT_SINGLE));
// Build message
builder = defaultBuilder(messageTemplate, const_cast<char*>(_PREHASH_Test0));
builder->addU32(_PREHASH_Test0, 0xaaaa);
builder->nextBlock(_PREHASH_Test1);
builder->addU32(_PREHASH_Test0, 0xbbbb);
bufferSize2 = builder->buildMessage(buffer2, MAX_BUFFER_SIZE, 0);
delete builder;
ensure_not_equals("Ensure Buffer Sizes Not Equal", bufferSize1, bufferSize2);
ensure_equals("Ensure Buffer Prefix Equal", memcmp(buffer1, buffer2, bufferSize1), 0);
ensure_not_equals("Ensure Buffer Contents Not Equal", memcmp(buffer1, buffer2, bufferSize2), 0);
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<22>()
// repeated penultimate block (crashes when data in LLDynamicArrayIndexed)
{
U32 inTest00 = 0, inTest01 = 1, inTest1 = 2;
U32 outTest00, outTest01, outTest1;
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test0), MVT_U32, 4));
messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_U32, 4));
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addU32(_PREHASH_Test0, inTest00);
builder->nextBlock(_PREHASH_Test0);
builder->addU32(_PREHASH_Test0, inTest01);
builder->nextBlock(_PREHASH_Test1);
builder->addU32(_PREHASH_Test0, inTest1);
LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outTest00, 0);
reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outTest01, 1);
reader->getU32(_PREHASH_Test1, _PREHASH_Test0, outTest1);
ensure_equals("Ensure Test0[0]", inTest00, outTest00);
ensure_equals("Ensure Test0[1]", inTest01, outTest01);
ensure_equals("Ensure Test1", inTest1, outTest1);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<23>()
// variable repeated block name never accessed
{
U32 inTest = 1, outTest;
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(
createBlock(const_cast<char*>(_PREHASH_Test0), MVT_U32, 4, MBT_SINGLE));
messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_U32, 4));
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addU32(_PREHASH_Test0, inTest);
LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outTest);
S32 blockCount = reader->getNumberOfBlocks(const_cast<char*>(_PREHASH_Test1));
ensure_equals("Ensure block count", blockCount, 0);
ensure_equals("Ensure Test0", inTest, outTest);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<24>()
// forwarding message
{
// build template
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test0), MVT_U32, 4));
// build message
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addU32(_PREHASH_Test0, 42);
// read message
LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
// forward message
builder = defaultBuilder(messageTemplate);
builder->newMessage(_PREHASH_TestMessage);
reader->copyToBuilder(*builder);
U8 buffer[MAX_BUFFER_SIZE];
builder->buildMessage(buffer, MAX_BUFFER_SIZE, 0);
delete builder;
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<25>()
// non-zero offset with undefined
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock());
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
LLTemplateMessageReader* reader = setReader(
messageTemplate, builder, 10);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<26>()
// non-zero offset with bool
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_BOOL, 1));
bool outValue, inValue = true;
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addBOOL(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(
messageTemplate, builder, 1);
reader->getBOOL(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure bool", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<27>()
// non-zero offset with U8
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_U8, 1));
U8 outValue, inValue = 2;
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addU8(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(
messageTemplate, builder, 255);
reader->getU8(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure U8", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<28>()
// non-zero offset with S16
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_S16, 2));
S16 outValue, inValue = 90;
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addS16(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(
messageTemplate, builder, 2);
reader->getS16(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure S16", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<29>()
// non-zero offset with U16
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_U16, 2));
U16 outValue, inValue = 3;
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addU16(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(
messageTemplate, builder, 4);
reader->getU16(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure U16", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<30>()
// non-zero offset with S32
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_S32, 4));
S32 outValue, inValue = 44;
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addS32(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(
messageTemplate, builder, 4);
reader->getS32(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure S32", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<31>()
// non-zero offset with F32
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_F32, 4));
F32 outValue, inValue = 121.44f;
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addF32(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(
messageTemplate, builder, 16);
reader->getF32(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure F32", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<32>()
// non-zero offset with U32
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_U32, 4));
U32 outValue, inValue = 88;
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addU32(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(
messageTemplate, builder, 127);
reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure U32", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<33>()
// non-zero offset with U64
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_U64, 8));
U64 outValue, inValue = 121;
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addU64(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(
messageTemplate, builder, 32);
reader->getU64(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure U64", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<34>()
// non-zero offset with F64
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_F64, 8));
F64 outValue, inValue = 3232143.33;
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addF64(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(
messageTemplate, builder, 128);
reader->getF64(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure F64", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<35>()
// non-zero offset with Vector3
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_LLVector3, 12));
LLVector3 outValue, inValue = LLVector3(1,2,3);
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addVector3(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(
messageTemplate, builder, 63);
reader->getVector3(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure LLVector3", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<36>()
// non-zero offset with Vector4
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_LLVector4, 16));
LLVector4 outValue, inValue = LLVector4(1,2,3,4);
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addVector4(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(
messageTemplate, builder, 64);
reader->getVector4(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure LLVector4", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<37>()
// non-zero offset with Vector3d
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_LLVector3d, 24));
LLVector3d outValue, inValue = LLVector3d(1,2,3);
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addVector3d(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(
messageTemplate, builder, 64);
reader->getVector3d(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure LLVector3d", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<38>()
// non-zero offset with Quaternion
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_LLQuaternion, 12));
LLQuaternion outValue, inValue = LLQuaternion(0.0f, LLVector3(0.3713907f, 0.5570861f, 0.7427813f));
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addQuat(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(
messageTemplate, builder, 12);
reader->getQuat(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure LLQuaternion", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<39>()
// non-zero offset with UUID
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_LLUUID, 16));
LLUUID outValue, inValue;
inValue.generate();
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addUUID(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(
messageTemplate, builder, 31);
reader->getUUID(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure UUID", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<40>()
// non-zero offset with IPAddr
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_IP_ADDR, 4));
U32 outValue, inValue = 12344556;
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addIPAddr(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(
messageTemplate, builder, 32);
reader->getIPAddr(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure IPAddr", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<41>()
// non-zero offset with IPPort
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_IP_PORT, 2));
U16 outValue, inValue = 80;
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addIPPort(_PREHASH_Test0, inValue);
LLTemplateMessageReader* reader = setReader(
messageTemplate, builder, 6);
reader->getIPPort(_PREHASH_Test0, _PREHASH_Test0, outValue);
ensure_equals("Ensure IPPort", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<42>()
// non-zero offset with String
{
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_VARIABLE, 1));
std::string outValue, inValue = "testing";
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addString(_PREHASH_Test0, inValue.c_str());
LLTemplateMessageReader* reader = setReader(
messageTemplate, builder, 255);
char buffer[MAX_STRING];
reader->getString(_PREHASH_Test0, _PREHASH_Test0, MAX_STRING, buffer);
outValue = buffer;
ensure_equals("Ensure String", inValue, outValue);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<43>()
// read past end of message -> default values (forward compatibility)
{
// build message with single block
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_U32, 4, MBT_SINGLE));
U32 outValue, outValue2, inValue = 0xbbbbbbbb;
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addU32(_PREHASH_Test0, inValue);
const U32 bufferSize = 1024;
U8 buffer[bufferSize];
memset(buffer, 0xaa, bufferSize);
memset(buffer, 0, LL_PACKET_ID_SIZE);
U32 builtSize = builder->buildMessage(buffer, bufferSize, 0);
delete builder;
// add block to reader template
messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_U32, 4, MBT_SINGLE));
// read message value and default value
numberMap[1] = &messageTemplate;
LLTemplateMessageReader* reader =
new LLTemplateMessageReader(numberMap);
reader->validateMessage(buffer, builtSize, LLHost());
reader->readMessage(buffer, LLHost());
reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outValue);
reader->getU32(_PREHASH_Test1, _PREHASH_Test0, outValue2);
ensure_equals("Ensure present value ", outValue, inValue);
ensure_equals("Ensure default value ", outValue2, 0);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<44>()
// read variable block past end of message -> 0 repeats
{
// build message with single block
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_U32, 4, MBT_SINGLE));
U32 outValue, outValue2, inValue = 0xbbbbbbbb;
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addU32(_PREHASH_Test0, inValue);
const U32 bufferSize = 1024;
U8 buffer[bufferSize];
memset(buffer, 0xaa, bufferSize);
memset(buffer, 0, LL_PACKET_ID_SIZE);
U32 builtSize = builder->buildMessage(buffer, bufferSize, 0);
delete builder;
// add variable block to reader template
messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_U32, 4));
// read message value and check block repeat count
numberMap[1] = &messageTemplate;
LLTemplateMessageReader* reader =
new LLTemplateMessageReader(numberMap);
reader->validateMessage(buffer, builtSize, LLHost());
reader->readMessage(buffer, LLHost());
reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outValue);
outValue2 = reader->getNumberOfBlocks(_PREHASH_Test1);
ensure_equals("Ensure present value ", outValue, inValue);
ensure_equals("Ensure 0 repeats ", outValue2, 0);
delete reader;
}
template<> template<>
void LLTemplateMessageBuilderTestObject::test<45>()
// read variable length data past end of message -> 0 length
{
// build message with single block
LLMessageTemplate messageTemplate = defaultTemplate();
messageTemplate.addBlock(defaultBlock(MVT_U32, 4, MBT_SINGLE));
U32 outValue, inValue = 0xbbbbbbbb;
LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
builder->addU32(_PREHASH_Test0, inValue);
const U32 bufferSize = 1024;
U8 buffer[bufferSize];
memset(buffer, 0xaa, bufferSize);
memset(buffer, 0, LL_PACKET_ID_SIZE);
U32 builtSize = builder->buildMessage(buffer, bufferSize, 0);
delete builder;
// add variable block to reader template
messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_VARIABLE, 4,
MBT_SINGLE));
// read message value and default string
numberMap[1] = &messageTemplate;
LLTemplateMessageReader* reader =
new LLTemplateMessageReader(numberMap);
reader->validateMessage(buffer, builtSize, LLHost());
reader->readMessage(buffer, LLHost());
reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outValue);
(void)outValue;
char outBuffer[bufferSize];
memset(buffer, 0xcc, bufferSize);
reader->getString(_PREHASH_Test1, _PREHASH_Test0, bufferSize,
outBuffer);
ensure_equals("Ensure present value ", outValue, inValue);
ensure_equals("Ensure unchanged buffer ", strlen(outBuffer), 0);
delete reader;
}
}
+34
View File
@@ -0,0 +1,34 @@
/**
* @file lltestapp.h
* @author Nat Goodspeed
* @date 2019-10-21
* @brief LLApp subclass useful for testing.
*
* $LicenseInfo:firstyear=2019&license=viewerlgpl$
* Copyright (c) 2019, Linden Research, Inc.
* $/LicenseInfo$
*/
#if ! defined(LL_LLTESTAPP_H)
#define LL_LLTESTAPP_H
#include "llapp.h"
/**
* LLTestApp is a dummy LLApp that simply sets LLApp::isRunning() for anyone
* who cares.
*/
class LLTestApp: public LLApp
{
public:
LLTestApp()
{
setStatus(APP_STATUS_RUNNING);
}
bool init() { return true; }
bool cleanup() { return true; }
bool frame() { return true; }
};
#endif /* ! defined(LL_LLTESTAPP_H) */
+124
View File
@@ -0,0 +1,124 @@
/**
* @file lltimestampcache_tut.cpp
* @author James Tess
* @date 2008-12-03
*
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include <tut/tut.hpp>
#include "linden_common.h"
#include "../mapserver/lltimestampcache.h"
#include "lltut.h"
namespace tut
{
struct LLTimestampCacheTestData
{
};
typedef test_group<LLTimestampCacheTestData> LLTimestampCacheTestGroup;
typedef LLTimestampCacheTestGroup::object LLTimestampCacheTestObject;
LLTimestampCacheTestGroup timestampCacheTestGroup("LLTimestampCache");
// Most common usage
template<> template<>
void LLTimestampCacheTestObject::test<1>()
{
LLTimestampCache<std::string, std::string> cache;
// put in some data
cache.insert("key1", "val1", 1);
cache.insert("key2", "val2", 2);
cache.insert("key3", "val3", 3);
ensure_equals("size is 3", cache.size(), 3);
// check some items
ensure("has key1", cache.has("key1"));
ensure("no invalid key", !cache.has("invalid key"));
// get some items
ensure_equals("get key1", cache.get("key1", 4), "val1");
ensure_equals("get invalid key",
cache.get("invalid key", 4), std::string() );
// timestamps
ensure_equals("key1 timestamp updated", cache.getTimestamp("key1"), 4);
ensure_equals("invalid key timestamp",
cache.getTimestamp("invalid key"), 0);
}
// New empty cache shouldn't have any entries
template<> template<>
void LLTimestampCacheTestObject::test<2>()
{
LLTimestampCache<std::string, std::string> cache;
ensure_equals("starts empty", cache.size(), 0);
ensure_equals("has nothing", cache.has("foo"), false);
ensure_equals("gets nothing", cache.get("foo", 0), std::string() );
U32 max_time = 0xFFFFFFFF;
ensure_equals("erases nothing", cache.eraseBefore(max_time), 0);
}
// Non empty cache
template<> template<>
void LLTimestampCacheTestObject::test<3>()
{
LLTimestampCache<std::string, std::string> cache;
cache.insert("foo", "bar", 123);
ensure_equals("size one", cache.size(), 1);
ensure_equals("has it", cache.has("foo"), true);
ensure_equals("timestamp correct", cache.getTimestamp("foo"), 123);
std::string value = cache.get("foo", 456);
ensure_equals("get value", value, "bar");
ensure_equals("timestamp updated", cache.getTimestamp("foo"), 456);
ensure_equals("erase nothing", cache.eraseBefore(0), 0);
ensure_equals("erase one", cache.eraseBefore(789), 1);
ensure_equals("empty after erase", cache.size(), 0);
}
// Recache of item should update timestamp
template<> template<>
void LLTimestampCacheTestObject::test<4>()
{
LLTimestampCache<std::string, std::string> cache;
cache.insert("foo", "bar", 123);
cache.insert("foo", "bar", 456);
ensure_equals("duplicate suppressed", cache.size(), 1);
ensure_equals("timestamp replaced", cache.getTimestamp("foo"), 456);
}
// Erasing some items
template<> template<>
void LLTimestampCacheTestObject::test<5>()
{
LLTimestampCache<std::string, std::string> cache;
cache.insert("key1", "val1", 1);
cache.insert("key2", "val2", 2);
cache.insert("key3", "val3", 3);
cache.insert("key4", "val4", 4);
size_t erased = cache.eraseBefore(3);
ensure_equals("erase range", erased, 2);
ensure_equals("cache post erase", cache.size(), 2);
ensure_equals("has key3", cache.has("key3"), true);
ensure_equals("not has key2", cache.has("key2"), false);
}
}
+86
View File
@@ -0,0 +1,86 @@
/**
* @file llscriptresource_tut.cpp
* @brief Test LLScriptResource
*
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
//#include <tut/tut.h>
#include "linden_common.h"
#include "lltut.h"
#include "../newsim/lltranscode.cpp" // include TU to pull in newsim implementation.
static const char test_utf8[] = "Edelwei\xc3\x9f";
static const char test_utf7[] = "Edelwei+AN8-";
static const char test_latin1[] = "Edelwei\xdf";
static const char test_latin2[] = "Edelwei\xdf";
namespace tut
{
class LLTranscodeTestData
{
};
typedef test_group<LLTranscodeTestData> LLTranscodeTestGroup;
typedef LLTranscodeTestGroup::object LLTranscodeTestObject;
LLTranscodeTestGroup transcodeTestGroup("transcode");
template<> template<>
void LLTranscodeTestObject::test<1>()
{
// Test utf8
std::stringstream input;
std::stringstream output;
input.str(test_utf7);
output.clear();
LLTranscode::transcode("charset=UTF-7", input, output);
ensure_equals("UTF-7 to UTF-8 transcoding", output.str(),
std::string(test_utf8));
input.str(test_latin1);
output.clear();
LLTranscode::transcode("", input, output);
ensure_equals("Default (latin_1) to UTF8 transcoding", output.str(),
std::string(test_utf8));
input.str(test_latin1);
output.clear();
LLTranscode::transcode("charset=iso-8859-1", input, output);
ensure_equals("latin_1 (ISO-8859-1) to UTF8 transcoding", output.str(),
std::string(test_utf8));
input.str(test_latin2);
output.clear();
LLTranscode::transcode("charset=iso-8859-2", input, output);
ensure_equals("latin_2 (ISO-8859-2) to UTF8 transcoding", output.str(),
std::string(test_utf8));
input.str(test_utf8);
output.clear();
LLTranscode::transcode("charset=utf-8", input, output);
ensure_equals("UTF8 to UTF8 transcoding", output.str(),
std::string(test_utf8));
}
}
+206
View File
@@ -0,0 +1,206 @@
/**
* @file lltut.cpp
* @author Mark Lentczner
* @date 5/16/06
* @brief MacTester
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "lltut.h"
#include "lldate.h"
#include "llformat.h"
#include "llsd.h"
#include "lluri.h"
#include "stringize.h"
namespace tut
{
void ensure_equals(const std::string& msg, const LLDate& actual,
const LLDate& expected)
{
ensure_equals(msg,
actual.secondsSinceEpoch(), expected.secondsSinceEpoch());
}
void ensure_equals(const std::string& msg, const LLURI& actual,
const LLURI& expected)
{
ensure_equals(msg,
actual.asString(), expected.asString());
}
// The lexical param types here intentionally diverge from the declaration
// in our header file. In lltut.h, LLSD is only a forward-declared type;
// we have no access to its LLSD::Binary nested type, and so must restate
// it explicitly to declare this overload. However, an overload that does
// NOT match LLSD::Binary does us no good whatsoever: it would never be
// engaged. Stating LLSD::Binary for this definition at least means that
// if the LLSD::Binary type ever diverges from what we expect in lltut.h,
// that divergence will produce an error: no definition will match that
// declaration.
void ensure_equals(const std::string& msg,
const LLSD::Binary& actual, const LLSD::Binary& expected)
{
ensure_equals(msg + " size", actual.size(), expected.size());
LLSD::Binary::const_iterator i, j;
int k;
for (i = actual.begin(), j = expected.begin(), k = 0;
i != actual.end();
++i, ++j, ++k)
{
ensure_equals(msg + " field", *i, *j);
}
}
void ensure_equals(const std::string& msg, const LLSD& actual,
const LLSD& expected)
{
ensure_equals(msg + " type", actual.type(), expected.type());
switch (actual.type())
{
case LLSD::TypeUndefined:
return;
case LLSD::TypeBoolean:
ensure_equals(msg + " boolean", actual.asBoolean(), expected.asBoolean());
return;
case LLSD::TypeInteger:
ensure_equals(msg + " integer", actual.asInteger(), expected.asInteger());
return;
case LLSD::TypeReal:
ensure_equals(msg + " real", actual.asReal(), expected.asReal());
return;
case LLSD::TypeString:
ensure_equals(msg + " string", actual.asString(), expected.asString());
return;
case LLSD::TypeUUID:
ensure_equals(msg + " uuid", actual.asUUID(), expected.asUUID());
return;
case LLSD::TypeDate:
ensure_equals(msg + " date", actual.asDate(), expected.asDate());
return;
case LLSD::TypeURI:
ensure_equals(msg + " uri", actual.asURI(), expected.asURI());
return;
case LLSD::TypeBinary:
ensure_equals(msg + " binary", actual.asBinary(), expected.asBinary());
return;
case LLSD::TypeMap:
{
ensure_equals(msg + " map size", actual.size(), expected.size());
LLSD::map_const_iterator actual_iter = actual.beginMap();
LLSD::map_const_iterator expected_iter = expected.beginMap();
while(actual_iter != actual.endMap())
{
ensure_equals(msg + " map keys",
actual_iter->first, expected_iter->first);
ensure_equals(msg + "[" + actual_iter->first + "]",
actual_iter->second, expected_iter->second);
++actual_iter;
++expected_iter;
}
return;
}
case LLSD::TypeArray:
{
ensure_equals(msg + " array size", actual.size(), expected.size());
for(int i = 0; i < actual.size(); ++i)
{
ensure_equals(msg + llformat("[%d]", i),
actual[i], expected[i]);
}
return;
}
default:
// should never get here, but compiler produces warning if we
// don't cover this case, and at Linden warnings are fatal.
throw failure(STRINGIZE("invalid type field " << actual.type()));
}
}
void ensure_starts_with(const std::string& msg,
const std::string& actual, const std::string& expectedStart)
{
if( actual.find(expectedStart, 0) != 0 )
{
std::stringstream ss;
ss << msg << ": " << "expected to find '" << expectedStart
<< "' at start of actual '" << actual << "'";
throw failure(ss.str().c_str());
}
}
void ensure_ends_with(const std::string& msg,
const std::string& actual, const std::string& expectedEnd)
{
if( actual.size() < expectedEnd.size()
|| actual.rfind(expectedEnd)
!= (actual.size() - expectedEnd.size()) )
{
std::stringstream ss;
ss << msg << ": " << "expected to find '" << expectedEnd
<< "' at end of actual '" << actual << "'";
throw failure(ss.str().c_str());
}
}
void ensure_contains(const std::string& msg,
const std::string& actual, const std::string& expectedSubString)
{
if( actual.find(expectedSubString, 0) == std::string::npos )
{
std::stringstream ss;
ss << msg << ": " << "expected to find '" << expectedSubString
<< "' in actual '" << actual << "'";
throw failure(ss.str().c_str());
}
}
void ensure_does_not_contain(const std::string& msg,
const std::string& actual, const std::string& expectedSubString)
{
if( actual.find(expectedSubString, 0) != std::string::npos )
{
std::stringstream ss;
ss << msg << ": " << "expected not to find " << expectedSubString
<< " in actual " << actual;
throw failure(ss.str().c_str());
}
}
}
+167
View File
@@ -0,0 +1,167 @@
/**
* @file lltut.h
* @author Phoenix
* @date 2005-09-26
* @brief helper tut methods
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLTUT_H
#define LL_LLTUT_H
#include "is_approx_equal_fraction.h" // instead of llmath.h
#include <cstring>
class LLDate;
class LLSD;
class LLURI;
namespace tut
{
void ensure_equals(const std::string& msg,
const LLDate& actual, const LLDate& expected);
void ensure_equals(const std::string& msg,
const LLURI& actual, const LLURI& expected);
// std::vector<U8> is the current definition of LLSD::Binary. Because
// we're only forward-declaring LLSD in this header file, we can't
// directly reference that nested type. If the build complains that
// there's no definition for this declaration, it could be that
// LLSD::Binary has changed, and that this declaration must be adjusted to
// match.
void ensure_equals(const std::string& msg,
const std::vector<U8>& actual, const std::vector<U8>& expected);
void ensure_equals(const std::string& msg,
const LLSD& actual, const LLSD& expected);
void ensure_starts_with(const std::string& msg,
const std::string& actual, const std::string& expectedStart);
void ensure_ends_with(const std::string& msg,
const std::string& actual, const std::string& expectedEnd);
void ensure_contains(const std::string& msg,
const std::string& actual, const std::string& expectedSubString);
void ensure_does_not_contain(const std::string& msg,
const std::string& actual, const std::string& expectedSubString);
}
// This is an odd place to #include an important contributor -- but the usual
// rules are reversed here. Instead of the overloads above referencing tut.hpp
// features, we need calls in tut.hpp template functions to dispatch to our
// overloads declared above.
// turn off warnings about unused functions from clang for tut package
#if __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-function"
#endif
#if __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
#include <tut/tut.hpp>
#if __clang__
#pragma clang diagnostic pop
#endif
#if __GNUC__
#pragma GCC diagnostic pop
#endif
// The functions BELOW this point actually consume tut.hpp functionality.
namespace tut
{
inline void ensure_approximately_equals(const char* msg, F64 actual, F64 expected, U32 frac_bits)
{
if(!is_approx_equal_fraction(actual, expected, frac_bits))
{
std::stringstream ss;
ss << (msg?msg:"") << (msg?": ":"") << "not equal actual: " << actual << " expected: " << expected;
throw tut::failure(ss.str().c_str());
}
}
inline void ensure_approximately_equals(const char* msg, F32 actual, F32 expected, U32 frac_bits)
{
if(!is_approx_equal_fraction(actual, expected, frac_bits))
{
std::stringstream ss;
ss << (msg?msg:"") << (msg?": ":"") << "not equal actual: " << actual << " expected: " << expected;
throw tut::failure(ss.str().c_str());
}
}
inline void ensure_approximately_equals(F32 actual, F32 expected, U32 frac_bits)
{
ensure_approximately_equals(NULL, actual, expected, frac_bits);
}
inline void ensure_approximately_equals_range(const char *msg, F32 actual, F32 expected, F32 delta)
{
if (fabs(actual-expected)>delta)
{
std::stringstream ss;
ss << (msg?msg:"") << (msg?": ":"") << "not equal actual: " << actual << " expected: " << expected << " tolerance: " << delta;
throw tut::failure(ss.str().c_str());
}
}
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) ||
(std::memcmp(actual, expected, actual_len) != 0))
{
std::stringstream ss;
ss << (msg?msg:"") << (msg?": ":"") << "not equal";
throw tut::failure(ss.str().c_str());
}
}
inline void ensure_memory_matches(const void* actual, U32 actual_len, const void* expected,U32 expected_len)
{
ensure_memory_matches("", actual, actual_len, expected, expected_len);
}
template <class T,class Q>
void ensure_not_equals(const char* msg,const Q& actual,const T& expected)
{
if( expected == actual )
{
std::stringstream ss;
ss << (msg?msg:"") << (msg?": ":"") << "both equal " << expected;
throw tut::failure(ss.str().c_str());
}
}
template <class T,class Q>
void ensure_not_equals(const Q& actual,const T& expected)
{
ensure_not_equals(NULL, actual, expected);
}
}
#endif // LL_LLTUT_H
+156
View File
@@ -0,0 +1,156 @@
/**
* @file lluserrelations_tut.cpp
* @author Phoenix
* @date 2006-10-12
* @brief Unit tests for the LLRelationship class.
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include <tut/tut.hpp>
#include "linden_common.h"
#include "lluserrelations.h"
namespace tut
{
struct user_relationship
{
LLRelationship mRelationship;
};
typedef test_group<user_relationship> user_relationship_t;
typedef user_relationship_t::object user_relationship_object_t;
tut::user_relationship_t tut_user_relationship("relationships");
template<> template<>
void user_relationship_object_t::test<1>()
{
// Test the default construction
ensure(
"No granted rights to",
!mRelationship.isRightGrantedTo(
LLRelationship::GRANT_ONLINE_STATUS));
ensure(
"No granted rights from",
!mRelationship.isRightGrantedFrom(
LLRelationship::GRANT_ONLINE_STATUS));
ensure("No online status",!mRelationship.isOnline());
}
template<> template<>
void user_relationship_object_t::test<2>()
{
// Test some granting
mRelationship.grantRights(
LLRelationship::GRANT_ONLINE_STATUS,
LLRelationship::GRANT_MODIFY_OBJECTS);
ensure(
"Granted rights to has online",
mRelationship.isRightGrantedTo(
LLRelationship::GRANT_ONLINE_STATUS));
ensure(
"Granted rights from does not have online",
!mRelationship.isRightGrantedFrom(
LLRelationship::GRANT_ONLINE_STATUS));
ensure(
"Granted rights to does not have modify",
!mRelationship.isRightGrantedTo(
LLRelationship::GRANT_MODIFY_OBJECTS));
ensure(
"Granted rights from has modify",
mRelationship.isRightGrantedFrom(
LLRelationship::GRANT_MODIFY_OBJECTS));
}
template<> template<>
void user_relationship_object_t::test<3>()
{
// Test revoking
mRelationship.grantRights(
LLRelationship::GRANT_ONLINE_STATUS
| LLRelationship::GRANT_MAP_LOCATION,
LLRelationship::GRANT_ONLINE_STATUS);
ensure(
"Granted rights to has online and map",
mRelationship.isRightGrantedTo(
LLRelationship::GRANT_ONLINE_STATUS
| LLRelationship::GRANT_MAP_LOCATION));
ensure(
"Granted rights from has online",
mRelationship.isRightGrantedFrom(
LLRelationship::GRANT_ONLINE_STATUS));
mRelationship.revokeRights(
LLRelationship::GRANT_MAP_LOCATION,
LLRelationship::GRANT_NONE);
ensure(
"Granted rights revoked map",
!mRelationship.isRightGrantedTo(
LLRelationship::GRANT_ONLINE_STATUS
| LLRelationship::GRANT_MAP_LOCATION));
ensure(
"Granted rights revoked still has online",
mRelationship.isRightGrantedTo(
LLRelationship::GRANT_ONLINE_STATUS));
mRelationship.grantRights(
LLRelationship::GRANT_NONE,
LLRelationship::GRANT_MODIFY_OBJECTS);
ensure(
"Granted rights from still has online",
mRelationship.isRightGrantedFrom(
LLRelationship::GRANT_ONLINE_STATUS));
ensure(
"Granted rights from has full grant",
mRelationship.isRightGrantedFrom(
LLRelationship::GRANT_ONLINE_STATUS
| LLRelationship::GRANT_MODIFY_OBJECTS));
mRelationship.revokeRights(
LLRelationship::GRANT_NONE,
LLRelationship::GRANT_MODIFY_OBJECTS);
ensure(
"Granted rights from still has online",
mRelationship.isRightGrantedFrom(
LLRelationship::GRANT_ONLINE_STATUS));
ensure(
"Granted rights from no longer modify",
!mRelationship.isRightGrantedFrom(
LLRelationship::GRANT_MODIFY_OBJECTS));
}
template<> template<>
void user_relationship_object_t::test<4>()
{
ensure("No online status", !mRelationship.isOnline());
mRelationship.online(true);
ensure("Online status", mRelationship.isOnline());
mRelationship.online(false);
ensure("No online status", !mRelationship.isOnline());
}
/*
template<> template<>
void user_relationship_object_t::test<>()
{
}
*/
}
+131
View File
@@ -0,0 +1,131 @@
/**
* @file llxorcipher_tut.cpp
* @author Adroit
* @date 2007-03
* @brief llxorcipher, llnullcipher test cases.
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "lltut.h"
#include "llxorcipher.h"
#include "llnullcipher.h"
namespace tut
{
struct cipher
{
};
typedef test_group<cipher> cipher_t;
typedef cipher_t::object cipher_object_t;
tut::cipher_t tut_cipher("cipher");
//encrypt->decrypt
template<> template<>
void cipher_object_t::test<1>()
{
const U32 len = 3;
const U8 pad[] = "abc";
const char str[] = "SecondLife";
const S32 str_len = sizeof(str);
U8 encrypted[str_len];
U8 decrypted[str_len];
LLXORCipher xorCipher(pad, len);
LLXORCipher xorCipher1(pad, len);
U32 length = xorCipher.requiredEncryptionSpace(50);
ensure("requiredEncryptionSpace() function failed", (length == 50));
U32 lenEncrypted = xorCipher.encrypt((U8 *) str, str_len, encrypted, str_len);
ensure("Encryption failed", (lenEncrypted == str_len));
U32 lenDecrypted = xorCipher1.decrypt(encrypted, str_len, decrypted, str_len);
ensure("Decryption failed", (lenDecrypted == str_len));
ensure_memory_matches("LLXORCipher Encrypt/Decrypt failed", str, str_len, decrypted, lenDecrypted);
}
// operator=
template<> template<>
void cipher_object_t::test<2>()
{
const U8 pad[] = "ABCDEFGHIJKLMNOPQ"; // pad len longer than data to be ciphered
const U32 pad_len = sizeof(pad);
const U8 pad1[] = "SecondLife";
const U32 pad_len1 = sizeof(pad1);
const char str[] = "To Be Ciphered";
const S32 str_len = sizeof(str);
U8 encrypted[str_len];
U8 decrypted[str_len];
LLXORCipher xorCipher(pad, pad_len);
LLXORCipher xorCipher1(pad1, pad_len1);
xorCipher.encrypt((U8 *) str, str_len, encrypted, str_len);
// make xorCipher1 same as xorCipher..so that xorCipher1 can decrypt what was
// encrypted using xorCipher
xorCipher1 = xorCipher;
U32 lenDecrypted = xorCipher1.decrypt(encrypted, str_len, decrypted, str_len);
ensure_memory_matches("LLXORCipher operator= failed", str, str_len, decrypted, lenDecrypted);
}
//in place encrypt->decrypt
template<> template<>
void cipher_object_t::test<3>()
{
U32 padNum = 0x12349087;
const U8* pad = (U8*) &padNum;
const U32 pad_len = sizeof(U32);
char str[] = "To Be Ciphered a long string.........!!!.";
char str1[] = "To Be Ciphered a long string.........!!!."; // same as str
const S32 str_len = sizeof(str);
LLXORCipher xorCipher(pad, pad_len);
LLXORCipher xorCipher1(pad, pad_len);
xorCipher.encrypt((U8 *) str, str_len);
// it should not be the same as original data!
ensure("LLXORCipher: In Place encrypt failed", memcmp(str, str1, str_len) != 0);
xorCipher1.decrypt((U8 *) str, str_len);
// it should not be the same as original data!
ensure_memory_matches("LLXORCipher: In Place decrypt failed", str, str_len, str1, str_len);
}
//LLNullCipher encrypt->decrypt
template<> template<>
void cipher_object_t::test<4>()
{
const char str[] = "SecondLife";
const S32 str_len = sizeof(str);
U8 encrypted[str_len];
U8 decrypted[str_len];
LLNullCipher nullCipher;
LLNullCipher nullCipher1;
U32 length = nullCipher.requiredEncryptionSpace(50);
ensure("LLNullCipher::requiredEncryptionSpace() function failed", (length == 50));
U32 len1 = nullCipher.encrypt((U8 *) str, str_len, encrypted, str_len);
ensure_memory_matches("LLNullCipher - Source transformed during encryption.", encrypted, len1, str, str_len);
U32 len2 = nullCipher1.decrypt(encrypted, str_len, decrypted, str_len);
ensure_memory_matches("LLNullCipher - Decryption failed", decrypted, len2, str, str_len);
}
}
+147
View File
@@ -0,0 +1,147 @@
/**
* @file lldatapacker_tut.cpp
* @date 2007-04
* @brief LLDataPacker test cases.
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include <tut/tut.hpp>
#include "linden_common.h"
#include "lltut.h"
#include "llhttpconstants.h"
#include "llapr.h"
#include "llmessageconfig.h"
#include "llsdserialize.h"
#include "message.h"
#include "message_prehash.h"
namespace
{
struct Response : public LLHTTPNode::Response
{
virtual void result(const LLSD&) {}
virtual void status(S32 code, const std::string& message)
{
mStatus = code;
}
virtual void extendedResult(S32 code, const std::string& message, const LLSD& headers) { }
virtual void extendedResult(S32 code, const LLSD& result, const LLSD& headers) { }
S32 mStatus;
};
}
namespace tut
{
struct LLMessageSystemTestData
{
std::string mTestConfigDir;
std::string mSep;
LLMessageSystemTestData()
{
static bool init = false;
if(!init)
{
ll_init_apr();
//init_prehash_data();
init = true;
}
const F32 circuit_heartbeat_interval=5;
const F32 circuit_timeout=100;
// currently test disconnected message system
start_messaging_system("notafile", 13035,
1,
0,
0,
false,
"notasharedsecret",
NULL,
false,
circuit_heartbeat_interval,
circuit_timeout
);
// generate temp dir
std::ostringstream ostr;
#if LL_WINDOWS
mSep = "\\";
ostr << "C:" << mSep;
#else
mSep = "/";
ostr << mSep << "tmp" << mSep;
#endif
LLUUID random;
random.generate();
ostr << "message-test-" << random;
mTestConfigDir = ostr.str();
LLFile::mkdir(mTestConfigDir);
writeConfigFile(LLSD());
LLMessageConfig::initClass("simulator", ostr.str());
}
~LLMessageSystemTestData()
{
// not end_messaging_system()
delete static_cast<LLMessageSystem*>(gMessageSystem);
gMessageSystem = NULL;
// rm contents of temp dir
std::ostringstream ostr;
ostr << mTestConfigDir << mSep << "message.xml";
int rmfile = LLFile::remove(ostr.str());
ensure_equals("rmfile value", rmfile, 0);
// rm temp dir
int rmdir = LLFile::rmdir(mTestConfigDir);
ensure_equals("rmdir value", rmdir, 0);
}
void writeConfigFile(const LLSD& config)
{
std::string ostr(mTestConfigDir + mSep + "message.xml");
llofstream file(ostr.c_str());
if (file.is_open())
{
LLSDSerialize::toPrettyXML(config, file);
}
file.close();
}
};
typedef test_group<LLMessageSystemTestData> LLMessageSystemTestGroup;
typedef LLMessageSystemTestGroup::object LLMessageSystemTestObject;
LLMessageSystemTestGroup messageTestGroup("LLMessageSystem");
template<> template<>
void LLMessageSystemTestObject::test<1>()
// dispatch unknown message
{
const char* name = "notamessasge";
const LLSD message;
const LLPointer<Response> response = new Response();
gMessageSystem->dispatch(name, message, response);
ensure_equals(response->mStatus, HTTP_NOT_FOUND);
}
}
+82
View File
@@ -0,0 +1,82 @@
/**
* @file mock_http_client.cpp
* @brief Framework for testing HTTP requests
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llhttpnode.h"
namespace tut
{
class SuccessNode : public LLHTTPNode
{
public:
void get(ResponsePtr r, const LLSD& context) const
{
LLSD result;
result["state"] = "complete";
result["test"] = "test";
r->result(result);
}
void post(ResponsePtr r, const LLSD& context, const LLSD& input) const
{
LLSD result;
result["state"] = "complete";
result["test"] = "test";
r->result(result);
}
};
class ErrorNode : public LLHTTPNode
{
public:
void get(ResponsePtr r, const LLSD& context) const
{ r->status(599, "Intentional error"); }
void post(ResponsePtr r, const LLSD& context, const LLSD& input) const
{ r->status(input["status"], input["reason"]); }
};
class TimeOutNode : public LLHTTPNode
{
public:
void get(ResponsePtr r, const LLSD& context) const
{
/* do nothing, the request will eventually time out */
}
};
LLSD storage;
class LLSDStorageNode : public LLHTTPNode
{
public:
LLSD get() const{ return storage; }
LLSD put(const LLSD& value) const{ storage = value; return LLSD(); }
};
LLHTTPRegistration<LLSDStorageNode> gStorageNode("/test/storage");
LLHTTPRegistration<SuccessNode> gSuccessNode("/test/success");
LLHTTPRegistration<ErrorNode> gErrorNode("/test/error");
LLHTTPRegistration<TimeOutNode> gTimeOutNode("/test/timeout");
}
+190
View File
@@ -0,0 +1,190 @@
/**
* @file mock_http_client.cpp
* @brief Framework for testing HTTP requests
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llsdhttpserver.h"
#include "lliohttpserver.h"
#include "llhttpclient.h"
#include "llformat.h"
#include "llpipeutil.h"
#include "llpumpio.h"
namespace tut
{
struct MockHttpClient
{
public:
MockHttpClient()
{
apr_pool_create(&mPool, NULL);
mServerPump = new LLPumpIO(mPool);
mClientPump = new LLPumpIO(mPool);
LLHTTPClient::setPump(*mClientPump);
}
~MockHttpClient()
{
delete mServerPump;
delete mClientPump;
apr_pool_destroy(mPool);
}
void setupTheServer()
{
LLHTTPNode& root = LLIOHTTPServer::create(mPool, *mServerPump, 8888);
LLHTTPStandardServices::useServices();
LLHTTPRegistrar::buildAllServices(root);
}
void runThePump(float timeout = 100.0f)
{
LLTimer timer;
timer.setTimerExpirySec(timeout);
while(!mSawCompleted && !timer.hasExpired())
{
if (mServerPump)
{
mServerPump->pump();
mServerPump->callback();
}
if (mClientPump)
{
mClientPump->pump();
mClientPump->callback();
}
}
}
void killServer()
{
delete mServerPump;
mServerPump = NULL;
}
private:
apr_pool_t* mPool;
LLPumpIO* mServerPump;
LLPumpIO* mClientPump;
protected:
void ensureStatusOK()
{
if (mSawError)
{
std::string msg =
llformat("httpFailure() called when not expected, status %d",
mStatus);
fail(msg);
}
}
void ensureStatusError()
{
if (!mSawError)
{
fail("httpFailure() wasn't called");
}
}
LLSD getResult()
{
return mResult;
}
protected:
bool mSawError;
S32 mStatus;
std::string mReason;
bool mSawCompleted;
LLSD mResult;
bool mResultDeleted;
class Result : public LLHTTPClient::Responder
{
protected:
Result(MockHttpClient& client)
: mClient(client)
{
}
public:
static boost::intrusive_ptr<Result> build(MockHttpClient& client)
{
return boost::intrusive_ptr<Result>(new Result(client));
}
~Result()
{
mClient.mResultDeleted = true;
}
protected:
virtual void httpFailure()
{
mClient.mSawError = true;
mClient.mStatus = getStatus();
mClient.mReason = getReason();
}
virtual void httpSuccess()
{
mClient.mResult = getContent();
}
virtual void httpCompleted()
{
LLHTTPClient::Responder::httpCompleted();
mClient.mSawCompleted = true;
}
private:
MockHttpClient& mClient;
};
friend class Result;
protected:
void reset()
{
mSawError = false;
mStatus = 0;
mSawCompleted = false;
mResult.clear();
mResultDeleted = false;
}
LLHTTPClient::ResponderPtr newResult()
{
reset();
return Result::build(*this);
}
};
}
+182
View File
@@ -0,0 +1,182 @@
/**
* @file namedtempfile.h
* @author Nat Goodspeed
* @date 2012-01-13
* @brief NamedTempFile class for tests that need disk files as fixtures.
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Copyright (c) 2012, Linden Research, Inc.
* $/LicenseInfo$
*/
#if ! defined(LL_NAMEDTEMPFILE_H)
#define LL_NAMEDTEMPFILE_H
#include "llerror.h"
#include "llstring.h"
#include "stringize.h"
#include <string>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/noncopyable.hpp>
#include <functional>
#include <iostream>
#include <sstream>
#include <string_view>
/**
* Create a text file with specified content "somewhere in the
* filesystem," cleaning up when it goes out of scope.
*/
class NamedTempFile: public boost::noncopyable
{
LOG_CLASS(NamedTempFile);
public:
NamedTempFile(const std::string_view& pfx,
const std::string_view& content,
const std::string_view& sfx=std::string_view(""))
{
createFile(pfx, [&content](std::ostream& out){ out << content; }, sfx);
}
// Disambiguate when passing string literal -- unclear why a string
// literal should be ambiguous wrt std::string_view and Streamer
NamedTempFile(const std::string_view& pfx,
const char* content,
const std::string_view& sfx=std::string_view(""))
{
createFile(pfx, [&content](std::ostream& out){ out << content; }, sfx);
}
// Function that accepts an ostream ref and (presumably) writes stuff to
// it, e.g.:
// (boost::phoenix::placeholders::arg1 << "the value is " << 17 << '\n')
typedef std::function<void(std::ostream&)> Streamer;
NamedTempFile(const std::string_view& pfx,
const Streamer& func,
const std::string_view& sfx=std::string_view(""))
{
createFile(pfx, func, sfx);
}
virtual ~NamedTempFile()
{
boost::filesystem::remove(mPath);
}
std::string getName() const { return mPath.string(); }
template <typename CALLABLE>
void peep_via(CALLABLE&& callable) const
{
std::forward<CALLABLE>(callable)(stringize("File '", mPath, "' contains:"));
boost::filesystem::ifstream reader(mPath, std::ios::binary);
std::string line;
while (std::getline(reader, line))
std::forward<CALLABLE>(callable)(line);
std::forward<CALLABLE>(callable)("---");
}
void peep_log() const
{
peep_via([](const std::string& line){ LL_DEBUGS() << line << LL_ENDL; });
}
void peep(std::ostream& out=std::cout) const
{
peep_via([&out](const std::string& line){ out << line << '\n'; });
}
friend std::ostream& operator<<(std::ostream& out, const NamedTempFile& self)
{
self.peep(out);
return out;
}
static boost::filesystem::path temp_path(const std::string_view& pfx="",
const std::string_view& sfx="")
{
// This variable is set by GitHub actions and is the recommended place
// to put temp files belonging to an actions job.
const char* RUNNER_TEMP = getenv("RUNNER_TEMP");
boost::filesystem::path tempdir{
// if RUNNER_TEMP is set and not empty
(RUNNER_TEMP && *RUNNER_TEMP)?
boost::filesystem::path(RUNNER_TEMP) : // use RUNNER_TEMP if available
boost::filesystem::temp_directory_path()}; // else canonical temp dir
boost::filesystem::path tempname{
// use filename template recommended by unique_path() doc, but
// with underscores instead of hyphens: some use cases involve
// temporary Python scripts
tempdir / stringize(pfx, "%%%%_%%%%_%%%%_%%%%", sfx) };
return boost::filesystem::unique_path(tempname);
}
protected:
void createFile(const std::string_view& pfx,
const Streamer& func,
const std::string_view& sfx)
{
// Create file in a temporary place.
mPath = temp_path(pfx, sfx);
boost::filesystem::ofstream out{ mPath, std::ios::binary };
// Write desired content.
func(out);
}
boost::filesystem::path mPath;
};
/**
* Create a NamedTempFile with a specified filename extension. This is useful
* when, for instance, you must be able to use the file in a Python import
* statement.
*/
class NamedExtTempFile: public NamedTempFile
{
LOG_CLASS(NamedExtTempFile);
public:
NamedExtTempFile(const std::string& ext, const std::string_view& content):
NamedTempFile(remove_dot(ext), content, ensure_dot(ext))
{}
// Disambiguate when passing string literal
NamedExtTempFile(const std::string& ext, const char* content):
NamedTempFile(remove_dot(ext), content, ensure_dot(ext))
{}
NamedExtTempFile(const std::string& ext, const Streamer& func):
NamedTempFile(remove_dot(ext), func, ensure_dot(ext))
{}
static std::string ensure_dot(const std::string& ext)
{
if (ext.empty())
{
// What SHOULD we do when the caller makes a point of using
// NamedExtTempFile to generate a file with a particular
// extension, then passes an empty extension? Use just "."? That
// sounds like a Bad Idea, especially on Windows. Treat that as a
// coding error.
LL_ERRS("NamedExtTempFile") << "passed empty extension" << LL_ENDL;
}
if (ext[0] == '.')
{
return ext;
}
return "." + ext;
}
static std::string remove_dot(const std::string& ext)
{
std::string::size_type found = ext.find_first_not_of(".");
if (found == std::string::npos)
{
return ext;
}
return ext.substr(found);
}
};
#endif /* ! defined(LL_NAMEDTEMPFILE_H) */
+495
View File
@@ -0,0 +1,495 @@
/**
* @file linkability.cpp
* @author andrew@lindenlab.com
* @date 2007-04-23
* @brief Tests for the LLPrimLinkInfo template which computes the linkability of prims
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "lltut.h"
#include "llprimlinkinfo.h"
#include "llrand.h"
// helper function
void randomize_sphere(LLSphere& sphere, F32 center_range, F32 radius_range)
{
F32 radius = ll_frand(2.f * radius_range) - radius_range;
LLVector3 center;
for (S32 i=0; i<3; ++i)
{
center.mV[i] = ll_frand(2.f * center_range) - center_range;
}
sphere.setRadius(radius);
sphere.setCenter(center);
}
// helper function. Same as above with a min and max radius.
void randomize_sphere(LLSphere& sphere, F32 center_range, F32 minimum_radius, F32 maximum_radius)
{
F32 radius = ll_frand(maximum_radius - minimum_radius) + minimum_radius;
LLVector3 center;
for (S32 i=0; i<3; ++i)
{
center.mV[i] = ll_frand(2.f * center_range) - center_range;
}
sphere.setRadius(radius);
sphere.setCenter(center);
}
// helper function
bool random_sort( const LLPrimLinkInfo< S32 >&, const LLPrimLinkInfo< S32 >& b)
{
return (ll_rand(64) < 32);
}
namespace tut
{
struct linkable_data
{
LLPrimLinkInfo<S32> info;
};
typedef test_group<linkable_data> linkable_test;
typedef linkable_test::object linkable_object;
tut::linkable_test wtf("prim linkability");
template<> template<>
void linkable_object::test<1>()
{
// Here we test the boundary of the LLPrimLinkInfo::canLink() method
// between semi-random middle-sized objects.
S32 number_of_tests = 100;
for (S32 test = 0; test < number_of_tests; ++test)
{
// compute the radii that would provide the above max link distance
F32 first_radius = 0.f;
F32 second_radius = 0.f;
// compute a random center for the first sphere
// compute some random max link distance
F32 max_link_span = ll_frand(MAX_OBJECT_SPAN);
if (max_link_span < OBJECT_SPAN_BONUS)
{
max_link_span += OBJECT_SPAN_BONUS;
}
LLVector3 first_center(
ll_frand(2.f * max_link_span) - max_link_span,
ll_frand(2.f * max_link_span) - max_link_span,
ll_frand(2.f * max_link_span) - max_link_span);
// put the second sphere at the right distance from the origin
// such that it is within the max_link_distance of the first
LLVector3 direction(ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f);
direction.normalize();
F32 half_milimeter = 0.0005f;
LLVector3 second_center;
// max_span = 3 * (first_radius + second_radius) + OBJECT_SPAN_BONUS
// make sure they link at short distances
{
second_center = first_center + (OBJECT_SPAN_BONUS - half_milimeter) * direction;
LLPrimLinkInfo<S32> first_info(0, LLSphere(first_center, first_radius) );
LLPrimLinkInfo<S32> second_info(1, LLSphere(second_center, second_radius) );
ensure("these nearby objects should link", first_info.canLink(second_info) );
}
// make sure they fail to link if we move them apart just a little bit
{
second_center = first_center + (OBJECT_SPAN_BONUS + half_milimeter) * direction;
LLPrimLinkInfo<S32> first_info(0, LLSphere(first_center, first_radius) );
LLPrimLinkInfo<S32> second_info(1, LLSphere(second_center, second_radius) );
ensure("these nearby objects should NOT link", !first_info.canLink(second_info) );
}
// make sure the objects link or not at medium distances
{
first_radius = 0.3f * ll_frand(max_link_span - OBJECT_SPAN_BONUS);
// This is the exact second radius that will link at exactly our random max_link_distance
second_radius = ((max_link_span - OBJECT_SPAN_BONUS) / 3.f) - first_radius;
second_center = first_center + (max_link_span - first_radius - second_radius - half_milimeter) * direction;
LLPrimLinkInfo<S32> first_info(0, LLSphere(first_center, first_radius) );
LLPrimLinkInfo<S32> second_info(1, LLSphere(second_center, second_radius) );
ensure("these objects should link", first_info.canLink(second_info) );
}
// make sure they fail to link if we move them apart just a little bit
{
// move the second sphere such that it is a little too far from the first
second_center += (2.f * half_milimeter) * direction;
LLPrimLinkInfo<S32> first_info(0, LLSphere(first_center, first_radius) );
LLPrimLinkInfo<S32> second_info(1, LLSphere(second_center, second_radius) );
ensure("these objects should NOT link", !first_info.canLink(second_info) );
}
// make sure things don't link at far distances
{
second_center = first_center + (MAX_OBJECT_SPAN + 2.f * half_milimeter) * direction;
second_radius = 0.3f * MAX_OBJECT_SPAN;
LLPrimLinkInfo<S32> first_info(0, LLSphere(first_center, first_radius) );
LLPrimLinkInfo<S32> second_info(1, LLSphere(second_center, second_radius) );
ensure("these objects should NOT link", !first_info.canLink(second_info) );
}
}
}
template<> template<>
void linkable_object::test<2>()
{
// Consider a row of eight spheres in a row, each 10m in diameter and centered
// at 10m intervals: 01234567.
F32 radius = 5.f;
F32 spacing = 10.f;
LLVector3 line_direction(ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f);
line_direction.normalize();
LLVector3 first_center(ll_frand(2.f * spacing) -spacing, ll_frand(2.f * spacing) - spacing, ll_frand(2.f * spacing) - spacing);
LLPrimLinkInfo<S32> infos[8];
for (S32 index = 0; index < 8; ++index)
{
LLVector3 center = first_center + ((F32)(index) * spacing) * line_direction;
infos[index].set(index, LLSphere(center, radius));
}
// Max span for 2 spheres of 5m radius is 3 * (5 + 5) + 1 = 31m
// spheres 0&2 have a 30m span (from outside edge to outside edge) and should link
{
LLPrimLinkInfo<S32> root_info = infos[0];
std::list< LLPrimLinkInfo<S32> > info_list;
info_list.push_back(infos[2]);
root_info.mergeLinkableSet(info_list);
S32 prim_count = root_info.getPrimCount();
ensure_equals("0&2 prim count should be 2", prim_count, 2);
ensure_equals("0&2 unlinkable list should have length 0", (S32) info_list.size(), 0);
}
// spheres 0&3 have a 40 meter span and should NOT link outright
{
LLPrimLinkInfo<S32> root_info = infos[0];
std::list< LLPrimLinkInfo<S32> > info_list;
info_list.push_back(infos[3]);
root_info.mergeLinkableSet(info_list);
S32 prim_count = root_info.getPrimCount();
ensure_equals("0&4 prim count should be 1", prim_count, 1);
ensure_equals("0&4 unlinkable list should have length 1", (S32) info_list.size(), 1);
}
// spheres 0-4 should link no matter what order : 01234
// Total span = 50m, 012 link with a r=15.5 giving max span of 3 * (15.5 + 5) + 1 = 62.5, but the cap is 54m
{
LLPrimLinkInfo<S32> root_info = infos[0];
std::list< LLPrimLinkInfo<S32> > info_list;
for (S32 index = 1; index < 5; ++index)
{
info_list.push_back(infos[index]);
}
root_info.mergeLinkableSet(info_list);
S32 prim_count = root_info.getPrimCount();
ensure_equals("01234 prim count should be 5", prim_count, 5);
ensure_equals("01234 unlinkable list should have length 0", (S32) info_list.size(), 0);
}
// spheres 0-5 should link no matter what order : 04321
{
LLPrimLinkInfo<S32> root_info = infos[0];
std::list< LLPrimLinkInfo<S32> > info_list;
for (S32 index = 4; index > 0; --index)
{
info_list.push_back(infos[index]);
}
root_info.mergeLinkableSet(info_list);
S32 prim_count = root_info.getPrimCount();
ensure_equals("04321 prim count should be 5", prim_count, 5);
ensure_equals("04321 unlinkable list should have length 0", (S32) info_list.size(), 0);
}
// spheres 0-4 should link no matter what order : 01423
{
LLPrimLinkInfo<S32> root_info = infos[0];
std::list< LLPrimLinkInfo<S32> > info_list;
info_list.push_back(infos[1]);
info_list.push_back(infos[4]);
info_list.push_back(infos[2]);
info_list.push_back(infos[3]);
root_info.mergeLinkableSet(info_list);
S32 prim_count = root_info.getPrimCount();
ensure_equals("01423 prim count should be 5", prim_count, 5);
ensure_equals("01423 unlinkable list should have length 0", (S32) info_list.size(), 0);
}
// spheres 0-5 should NOT fully link, only 0-4
{
LLPrimLinkInfo<S32> root_info = infos[0];
std::list< LLPrimLinkInfo<S32> > info_list;
for (S32 index = 1; index < 6; ++index)
{
info_list.push_back(infos[index]);
}
root_info.mergeLinkableSet(info_list);
S32 prim_count = root_info.getPrimCount();
ensure_equals("012345 prim count should be 5", prim_count, 5);
ensure_equals("012345 unlinkable list should have length 1", (S32) info_list.size(), 1);
std::list< LLPrimLinkInfo<S32> >::iterator info_itr = info_list.begin();
if (info_itr != info_list.end())
{
// examine the contents of the unlinked info
std::list<S32> unlinked_indecies;
info_itr->getData(unlinked_indecies);
// make sure there is only one index in the unlinked_info
ensure_equals("012345 unlinkable index count should be 1", (S32) unlinked_indecies.size(), 1);
// make sure its value is 6
std::list<S32>::iterator unlinked_index_itr = unlinked_indecies.begin();
S32 unlinkable_index = *unlinked_index_itr;
ensure_equals("012345 unlinkable index should be 5", (S32) unlinkable_index, 5);
}
}
// spheres 0-7 should NOT fully link, only 0-5
{
LLPrimLinkInfo<S32> root_info = infos[0];
std::list< LLPrimLinkInfo<S32> > info_list;
for (S32 index = 1; index < 8; ++index)
{
info_list.push_back(infos[index]);
}
root_info.mergeLinkableSet(info_list);
S32 prim_count = root_info.getPrimCount();
ensure_equals("01234567 prim count should be 5", prim_count, 5);
// Should be 1 linkinfo on unlinkable that has 2 prims
ensure_equals("01234567 unlinkable list should have length 1", (S32) info_list.size(), 1);
std::list< LLPrimLinkInfo<S32> >::iterator info_itr = info_list.begin();
if (info_itr != info_list.end())
{
// make sure there is only one index in the unlinked_info
std::list<S32> unlinked_indecies;
info_itr->getData(unlinked_indecies);
ensure_equals("0123456 unlinkable index count should be 3", (S32) unlinked_indecies.size(), 3);
// make sure its values are 6 and 7
std::list<S32>::iterator unlinked_index_itr = unlinked_indecies.begin();
S32 unlinkable_index = *unlinked_index_itr;
ensure_equals("0123456 first unlinkable index should be 5", (S32) unlinkable_index, 5);
++unlinked_index_itr;
unlinkable_index = *unlinked_index_itr;
ensure_equals("0123456 second unlinkable index should be 6", (S32) unlinkable_index, 6);
++unlinked_index_itr;
unlinkable_index = *unlinked_index_itr;
ensure_equals("0123456 third unlinkable index should be 7", (S32) unlinkable_index, 7);
}
}
}
template<> template<>
void linkable_object::test<3>()
{
// Here we test the link results between an LLPrimLinkInfo and a set of
// randomized LLPrimLinkInfos where the expected results are known.
S32 number_of_tests = 5;
for (S32 test = 0; test < number_of_tests; ++test)
{
// the radii are known
F32 first_radius = 1.f;
F32 second_radius = 2.f;
F32 third_radius = 3.f;
// compute the distances
F32 half_milimeter = 0.0005f;
F32 max_first_second_span = 3.f * (first_radius + second_radius) + OBJECT_SPAN_BONUS;
F32 linkable_distance = max_first_second_span - first_radius - second_radius - half_milimeter;
F32 max_full_span = 3.f * (0.5f * max_first_second_span + third_radius) + OBJECT_SPAN_BONUS;
F32 unlinkable_distance = max_full_span - 0.5f * linkable_distance - third_radius + half_milimeter;
// compute some random directions
LLVector3 first_direction(ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f);
first_direction.normalize();
LLVector3 second_direction(ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f);
second_direction.normalize();
LLVector3 third_direction(ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f);
third_direction.normalize();
// compute the centers
LLVector3 first_center = ll_frand(10.f) * first_direction;
LLVector3 second_center = first_center + ll_frand(linkable_distance) * second_direction;
LLVector3 first_join_center = 0.5f * (first_center + second_center);
LLVector3 third_center = first_join_center + unlinkable_distance * third_direction;
// make sure the second info links and the third does not
{
// initialize the infos
S32 index = 0;
LLPrimLinkInfo<S32> first_info(index++, LLSphere(first_center, first_radius));
LLPrimLinkInfo<S32> second_info(index++, LLSphere(second_center, second_radius));
LLPrimLinkInfo<S32> third_info(index++, LLSphere(third_center, third_radius));
// put the second and third infos in a list
std::list< LLPrimLinkInfo<S32> > info_list;
info_list.push_back(second_info);
info_list.push_back(third_info);
// merge the list with the first_info
first_info.mergeLinkableSet(info_list);
S32 prim_count = first_info.getPrimCount();
ensure_equals("prim count should be 2", prim_count, 2);
ensure_equals("unlinkable list should have length 1", (S32) info_list.size(), 1);
}
// reverse the order and make sure we get the same results
{
// initialize the infos
S32 index = 0;
LLPrimLinkInfo<S32> first_info(index++, LLSphere(first_center, first_radius));
LLPrimLinkInfo<S32> second_info(index++, LLSphere(second_center, second_radius));
LLPrimLinkInfo<S32> third_info(index++, LLSphere(third_center, third_radius));
// build the list in the reverse order
std::list< LLPrimLinkInfo<S32> > info_list;
info_list.push_back(third_info);
info_list.push_back(second_info);
// merge the list with the first_info
first_info.mergeLinkableSet(info_list);
S32 prim_count = first_info.getPrimCount();
ensure_equals("prim count should be 2", prim_count, 2);
ensure_equals("unlinkable list should have length 1", (S32) info_list.size(), 1);
}
}
}
template<> template<>
void linkable_object::test<4>()
{
// Here we test whether linkability is invarient under permutations
// of link order. To do this we generate a bunch of random spheres
// and then try to link them in different ways.
//
// NOTE: the linkability will only be invarient if there is only one
// linkable solution. Multiple solutions will exist if the set of
// candidates are larger than the maximum linkable distance, or more
// numerous than a single linked object can contain. This is easily
// understood by considering a very large set of link candidates,
// and first linking preferentially to the left until linking fails,
// then doing the same to the right -- the final solutions will differ.
// Hence for this test we must generate candidate sets that lie within
// the linkability envelope of a single object.
//
// NOTE: a random set of objects will tend to either be totally linkable
// or totally not. That is, the random orientations that
F32 root_center_range = 0.f;
F32 min_prim_radius = 0.1f;
F32 max_prim_radius = 2.f;
// Linkability is min(MAX_OBJECT_SPAN,3 *( R1 + R2 ) + BONUS)
// 3 * (min_prim_radius + min_prim_radius) + OBJECT_SPAN_BONUS = 6 * min_prim_radius + OBJECT_SPAN_BONUS;
// Use .45 instead of .5 to gaurantee objects are within the minimum span.
F32 child_center_range = 0.45f * ( (6*min_prim_radius) + OBJECT_SPAN_BONUS );
S32 number_of_tests = 100;
S32 number_of_spheres = 10;
S32 number_of_scrambles = 10;
S32 number_of_random_bubble_sorts = 10;
for (S32 test = 0; test < number_of_tests; ++test)
{
LLSphere sphere;
S32 sphere_index = 0;
// build the root piece
randomize_sphere(sphere, root_center_range, min_prim_radius, max_prim_radius);
info.set( sphere_index++, sphere );
// build the unlinked pieces
std::list< LLPrimLinkInfo<S32> > info_list;
for (; sphere_index < number_of_spheres; ++sphere_index)
{
randomize_sphere(sphere, child_center_range, min_prim_radius, max_prim_radius);
LLPrimLinkInfo<S32> child_info( sphere_index, sphere );
info_list.push_back(child_info);
}
// declare the variables used to store the results
std::list<S32> first_linked_list;
{
// the link attempt will modify our original info's, so we
// have to make copies of the originals for testing
LLPrimLinkInfo<S32> test_info( 0, LLSphere(info.getCenter(), 0.5f * info.getDiameter()) );
std::list< LLPrimLinkInfo<S32> > test_list;
test_list.assign(info_list.begin(), info_list.end());
// try to link
test_info.mergeLinkableSet(test_list);
ensure("All prims should link, but did not.",test_list.empty());
// store the results
test_info.getData(first_linked_list);
first_linked_list.sort();
}
// try to link the spheres in various random orders
for (S32 scramble = 0; scramble < number_of_scrambles; ++scramble)
{
LLPrimLinkInfo<S32> test_info(0, LLSphere(info.getCenter(), 0.5f * info.getDiameter()) );
// scramble the order of the info_list
std::list< LLPrimLinkInfo<S32> > test_list;
test_list.assign(info_list.begin(), info_list.end());
for (S32 i = 0; i < number_of_random_bubble_sorts; i++)
{
test_list.sort(random_sort);
}
// try to link
test_info.mergeLinkableSet(test_list);
// get the results
std::list<S32> linked_list;
test_info.getData(linked_list);
linked_list.sort();
ensure_equals("linked set size should be order independent",linked_list.size(),first_linked_list.size());
}
}
}
}
+42
View File
@@ -0,0 +1,42 @@
/**
* @file print.h
* @author Nat Goodspeed
* @date 2020-01-02
* @brief print() function for debugging
*
* $LicenseInfo:firstyear=2020&license=viewerlgpl$
* Copyright (c) 2020, Linden Research, Inc.
* $/LicenseInfo$
*/
#if ! defined(LL_PRINT_H)
#define LL_PRINT_H
#include <iostream>
// print(..., NONL);
// leaves the output dangling, suppressing the normally appended std::endl
struct NONL_t {};
#define NONL (NONL_t())
// normal recursion end
inline
void print()
{
std::cerr << std::endl;
}
// print(NONL) is a no-op
inline
void print(NONL_t)
{
}
template <typename T, typename... ARGS>
void print(T&& first, ARGS&&... rest)
{
std::cerr << first;
print(std::forward<ARGS>(rest)...);
}
#endif /* ! defined(LL_PRINT_H) */
+66
View File
@@ -0,0 +1,66 @@
/**
* @file setenv.h
* @author Nat Goodspeed
* @date 2020-04-01
* @brief Provide a way for a particular test program to alter the
* environment before entry to main().
*
* $LicenseInfo:firstyear=2020&license=viewerlgpl$
* Copyright (c) 2020, Linden Research, Inc.
* $/LicenseInfo$
*/
#if ! defined(LL_SETENV_H)
#define LL_SETENV_H
#include <stdlib.h> // setenv()
/**
* Our test.cpp main program responds to environment variables LOGTEST and
* LOGFAIL. But if you set (e.g.) LOGTEST=DEBUG before a viewer build, @em
* every test program in the build emits debug log output. This can be so
* voluminous as to slow down the build.
*
* With an integration test program, you can specifically build (e.g.) the
* INTEGRATION_TEST_llstring target, and set any environment variables you
* want for that. But with a unit test program, since executing the program is
* a side effect rather than an explicit target, specifically building (e.g.)
* PROJECT_lllogin_TEST_lllogin only builds the executable without running it.
*
* To set an environment variable for a particular test program, declare a
* static instance of SetEnv in its .cpp file. SetEnv's constructor takes
* pairs of strings, e.g.
*
* @code
* static SetEnv sLOGGING("LOGTEST", "INFO");
* @endcode
*
* Declaring a static instance of SetEnv is important because that ensures
* that the environment variables are set before main() is entered, since it
* is main() that examines LOGTEST and LOGFAIL.
*/
struct SetEnv
{
// degenerate constructor, terminate recursion
SetEnv() {}
/**
* SetEnv() accepts an arbitrary number of pairs of strings: variable
* name, value, variable name, value ... Entering the constructor sets
* those variables in the process environment using Posix setenv(),
* overriding any previous value. If static SetEnv declarations in
* different translation units specify overlapping sets of variable names,
* it is indeterminate which instance will "win."
*/
template <typename VAR, typename VAL, typename... ARGS>
SetEnv(VAR&& var, VAL&& val, ARGS&&... rest):
// constructor forwarding handles the tail of the list
SetEnv(std::forward<ARGS>(rest)...)
{
// set just the first (variable, value) pair
// 1 means override previous value if any
setenv(std::forward<VAR>(var), std::forward<VAL>(val), 1);
}
};
#endif /* ! defined(LL_SETENV_H) */
+117
View File
@@ -0,0 +1,117 @@
/**
* @file sync.h
* @author Nat Goodspeed
* @date 2019-03-13
* @brief Synchronize coroutines within a test program so we can observe side
* effects. Certain test programs test coroutine synchronization
* mechanisms. Such tests usually want to interleave coroutine
* executions in strictly stepwise fashion. This class supports that
* paradigm.
*
* $LicenseInfo:firstyear=2019&license=viewerlgpl$
* Copyright (c) 2019, Linden Research, Inc.
* $/LicenseInfo$
*/
#if ! defined(LL_SYNC_H)
#define LL_SYNC_H
#include "llcond.h"
#include "lltut.h"
#include "stringize.h"
#include "llerror.h"
#include "llcoros.h"
/**
* Instantiate Sync in any test in which we need to suspend one coroutine
* until we're sure that another has had a chance to run. Simply calling
* llcoro::suspend() isn't necessarily enough; that provides a chance for the
* other to run, but doesn't guarantee that it has. If each coroutine is
* consistent about calling Sync::bump() every time it wakes from any
* suspension, Sync::yield() and yield_until() should at least ensure that
* somebody else has had a chance to run.
*/
class Sync
{
LLScalarCond<int> mCond{0};
F32Milliseconds mTimeout;
public:
Sync(F32Milliseconds timeout=F32Milliseconds(10000.0f)):
mTimeout(timeout)
{}
/**
* Bump mCond by n steps -- ideally, do this every time a participating
* coroutine wakes up from any suspension. The choice to bump() after
* resumption rather than just before suspending is worth calling out:
* this practice relies on the fact that condition_variable::notify_all()
* merely marks a suspended coroutine ready to run, rather than
* immediately resuming it. This way, though, even if a coroutine exits
* before reaching its next suspend point, the other coroutine isn't
* left waiting forever.
*/
void bump(int n=1)
{
// Calling mCond.set_all(mCond.get() + n) would be great for
// coroutines -- but not so good between kernel threads -- it would be
// racy. Make the increment atomic by calling update_all(), which runs
// the passed lambda within a mutex lock.
int updated;
mCond.update_all(
[&n, &updated](int& data)
{
data += n;
// Capture the new value for possible logging purposes.
updated = data;
});
// In the multi-threaded case, this log message could be a bit
// misleading, as it will be emitted after waiting threads have
// already awakened. But emitting the log message within the lock
// would seem to hold the lock longer than we really ought.
LL_DEBUGS() << llcoro::logname() << " bump(" << n << ") -> " << updated << LL_ENDL;
}
/**
* Set mCond to a specific n. Use of bump() and yield() is nicely
* maintainable, since you can insert or delete matching operations in a
* test function and have the rest of the Sync operations continue to
* line up as before. But sometimes you need to get very specific, which
* is where set() and yield_until() come in handy: less maintainable,
* more precise.
*/
void set(int n)
{
LL_DEBUGS() << llcoro::logname() << " set(" << n << ")" << LL_ENDL;
mCond.set_all(n);
}
/// suspend until "somebody else" has bumped mCond by n steps
void yield(int n=1)
{
return yield_until("Sync::yield_for", n, mCond.get() + n);
}
/// suspend until "somebody else" has bumped mCond to a specific value
void yield_until(int until)
{
return yield_until("Sync::yield_until", until, until);
}
private:
void yield_until(const char* func, int arg, int until)
{
std::string name(llcoro::logname());
LL_DEBUGS() << name << " yield_until(" << until << ") suspending" << LL_ENDL;
if (! mCond.wait_for_equal(mTimeout, until))
{
tut::fail(STRINGIZE(name << ' ' << func << '(' << arg << ") timed out after "
<< int(mTimeout.value()) << "ms (expected " << until
<< ", actual " << mCond.get() << ')'));
}
// each time we wake up, bump mCond
bump();
}
};
#endif /* ! defined(LL_SYNC_H) */
+669
View File
@@ -0,0 +1,669 @@
/**
* @file test.cpp
* @author Phoenix
* @date 2005-09-26
* @brief Entry point for the test app.
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
/**
*
* You can add tests by creating a new cpp file in this directory, and
* rebuilding. There are at most 50 tests per testgroup without a
* little bit of template parameter and makefile tweaking.
*
*/
#include "linden_common.h"
#include "llerrorcontrol.h"
#include "lltut.h"
#include "chained_callback.h"
#include "stringize.h"
#include "namedtempfile.h"
#include "lltrace.h"
#include "lltracethreadrecorder.h"
#include "apr_pools.h"
#include "apr_getopt.h"
// the CTYPE_WORKAROUND is needed for linux dev stations that don't
// have the broken libc6 packages needed by our out-of-date static
// libs (such as libcrypto and libcurl). -- Leviathan 20060113
#ifdef CTYPE_WORKAROUND
# include "ctype_workaround.h"
#endif
#include <boost/iostreams/tee.hpp>
#include <boost/iostreams/stream.hpp>
#include <fstream>
void wouldHaveCrashed(const std::string& message);
namespace tut
{
std::string sSourceDir;
test_runner_singleton runner;
}
class LLReplayLog
{
public:
LLReplayLog() {}
virtual ~LLReplayLog() {}
virtual void reset() {}
virtual void replay(std::ostream&) {}
};
class RecordToTempFile : public LLError::Recorder, public boost::noncopyable
{
public:
RecordToTempFile()
: LLError::Recorder(),
boost::noncopyable(),
mTempFile("log", ""),
mFile(mTempFile.getName().c_str())
{
}
virtual ~RecordToTempFile()
{
mFile.close();
}
virtual void recordMessage(LLError::ELevel level, const std::string& message)
{
LL_PROFILE_ZONE_SCOPED;
mFile << message << std::endl;
}
void reset()
{
mFile.close();
mFile.open(mTempFile.getName().c_str());
}
void replay(std::ostream& out)
{
mFile.close();
std::ifstream inf(mTempFile.getName().c_str());
std::string line;
while (std::getline(inf, line))
{
out << line << std::endl;
}
}
private:
NamedTempFile mTempFile;
llofstream mFile;
};
class LLReplayLogReal: public LLReplayLog, public boost::noncopyable
{
public:
LLReplayLogReal(LLError::ELevel level)
: LLReplayLog(),
boost::noncopyable(),
mOldSettings(LLError::saveAndResetSettings()),
mRecorder(new RecordToTempFile())
{
LLError::setFatalFunction(wouldHaveCrashed);
LLError::setDefaultLevel(level);
LLError::addRecorder(mRecorder);
}
virtual ~LLReplayLogReal()
{
LLError::removeRecorder(mRecorder);
LLError::restoreSettings(mOldSettings);
}
virtual void reset()
{
std::dynamic_pointer_cast<RecordToTempFile>(mRecorder)->reset();
}
virtual void replay(std::ostream& out)
{
std::dynamic_pointer_cast<RecordToTempFile>(mRecorder)->replay(out);
}
private:
LLError::SettingsStoragePtr mOldSettings;
LLError::RecorderPtr mRecorder;
};
class LLTestCallback : public chained_callback
{
typedef chained_callback super;
public:
LLTestCallback(bool verbose_mode, std::ostream *stream,
std::shared_ptr<LLReplayLog> replayer) :
mVerboseMode(verbose_mode),
mTotalTests(0),
mPassedTests(0),
mFailedTests(0),
mSkippedTests(0),
// By default, capture a shared_ptr to std::cout, with a no-op "deleter"
// so that destroying the shared_ptr makes no attempt to delete std::cout.
mStream(std::shared_ptr<std::ostream>(&std::cout, [](std::ostream*){})),
mReplayer(replayer)
{
if (stream)
{
// We want a boost::iostreams::tee_device that will stream to two
// std::ostreams.
typedef boost::iostreams::tee_device<std::ostream, std::ostream> TeeDevice;
// More than that, though, we want an actual stream using that
// device.
typedef boost::iostreams::stream<TeeDevice> TeeStream;
// Allocate and assign in two separate steps, per Herb Sutter.
// (Until we turn on C++11 support, have to wrap *stream with
// boost::ref() due to lack of perfect forwarding.)
std::shared_ptr<std::ostream> pstream(new TeeStream(std::cout, boost::ref(*stream)));
mStream = pstream;
}
}
~LLTestCallback()
{
}
virtual void run_started()
{
//std::cout << "run_started" << std::endl;
LL_INFOS("TestRunner")<<"Test Started"<< LL_ENDL;
super::run_started();
}
virtual void group_started(const std::string& name) {
LL_INFOS("TestRunner")<<"Unit test group_started name=" << name << LL_ENDL;
*mStream << "Unit test group_started name=" << name << std::endl;
super::group_started(name);
}
virtual void group_completed(const std::string& name) {
LL_INFOS("TestRunner")<<"Unit test group_completed name=" << name << LL_ENDL;
*mStream << "Unit test group_completed name=" << name << std::endl;
super::group_completed(name);
}
virtual void test_completed(const tut::test_result& tr)
{
++mTotalTests;
// If this test failed, dump requested log messages BEFORE stating the
// test result.
if (tr.result != tut::test_result::ok && tr.result != tut::test_result::skip)
{
mReplayer->replay(*mStream);
}
// Either way, clear stored messages in preparation for next test.
mReplayer->reset();
std::ostringstream out;
out << "[" << tr.group << ", " << tr.test;
if (! tr.name.empty())
out << ": " << tr.name;
out << "] ";
switch(tr.result)
{
case tut::test_result::ok:
++mPassedTests;
out << "ok";
break;
case tut::test_result::fail:
++mFailedTests;
out << "fail";
break;
case tut::test_result::ex:
++mFailedTests;
out << "exception: " << LLError::Log::demangle(tr.exception_typeid.c_str());
break;
case tut::test_result::warn:
++mFailedTests;
out << "test destructor throw";
break;
case tut::test_result::term:
++mFailedTests;
out << "abnormal termination";
break;
case tut::test_result::skip:
++mSkippedTests;
out << "skipped known failure";
break;
default:
++mFailedTests;
out << "unknown (tr.result == " << tr.result << ")";
}
if(mVerboseMode || (tr.result != tut::test_result::ok))
{
*mStream << out.str();
if(!tr.message.empty())
{
*mStream << ": '" << tr.message << "'";
LL_WARNS("TestRunner") << "not ok : "<<tr.message << LL_ENDL;
}
*mStream << std::endl;
}
LL_INFOS("TestRunner")<<out.str()<<LL_ENDL;
super::test_completed(tr);
}
virtual int getFailedTests() const { return mFailedTests; }
virtual void run_completed()
{
*mStream << "\tTotal Tests:\t" << mTotalTests << std::endl;
*mStream << "\tPassed Tests:\t" << mPassedTests;
if (mPassedTests == mTotalTests)
{
*mStream << "\tYAY!! \\o/";
}
*mStream << std::endl;
if (mSkippedTests > 0)
{
*mStream << "\tSkipped known failures:\t" << mSkippedTests
<< std::endl;
}
if(mFailedTests > 0)
{
*mStream << "*********************************" << std::endl;
*mStream << "Failed Tests:\t" << mFailedTests << std::endl;
*mStream << "Please report or fix the problem." << std::endl;
*mStream << "*********************************" << std::endl;
}
super::run_completed();
}
protected:
bool mVerboseMode;
int mTotalTests;
int mPassedTests;
int mFailedTests;
int mSkippedTests;
std::shared_ptr<std::ostream> mStream;
std::shared_ptr<LLReplayLog> mReplayer;
};
// TeamCity specific class which emits service messages
// http://confluence.jetbrains.net/display/TCD3/Build+Script+Interaction+with+TeamCity;#BuildScriptInteractionwithTeamCity-testReporting
class LLTCTestCallback : public LLTestCallback
{
public:
LLTCTestCallback(bool verbose_mode, std::ostream *stream,
std::shared_ptr<LLReplayLog> replayer) :
LLTestCallback(verbose_mode, stream, replayer)
{
}
~LLTCTestCallback()
{
}
virtual void group_started(const std::string& name) {
LLTestCallback::group_started(name);
std::cout << "\n##teamcity[testSuiteStarted name='" << escape(name) << "']" << std::endl;
}
virtual void group_completed(const std::string& name) {
LLTestCallback::group_completed(name);
std::cout << "##teamcity[testSuiteFinished name='" << escape(name) << "']" << std::endl;
}
virtual void test_completed(const tut::test_result& tr)
{
std::string testname(STRINGIZE(tr.group << "." << tr.test));
if (! tr.name.empty())
{
testname.append(":");
testname.append(tr.name);
}
testname = escape(testname);
// Sadly, tut::callback doesn't give us control at test start; have to
// backfill start message into TC output.
std::cout << "##teamcity[testStarted name='" << testname << "']" << std::endl;
// now forward call to base class so any output produced there is in
// the right TC context
LLTestCallback::test_completed(tr);
switch(tr.result)
{
case tut::test_result::ok:
break;
case tut::test_result::fail:
case tut::test_result::ex:
case tut::test_result::warn:
case tut::test_result::term:
std::cout << "##teamcity[testFailed name='" << testname
<< "' message='" << escape(tr.message) << "']" << std::endl;
break;
case tut::test_result::skip:
std::cout << "##teamcity[testIgnored name='" << testname << "']" << std::endl;
break;
default:
break;
}
std::cout << "##teamcity[testFinished name='" << testname << "']" << std::endl;
}
static std::string escape(const std::string& str)
{
// Per http://confluence.jetbrains.net/display/TCD65/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ServiceMessages
std::string result;
for (char c : str)
{
switch (c)
{
case '\'':
result.append("|'");
break;
case '\n':
result.append("|n");
break;
case '\r':
result.append("|r");
break;
/*==========================================================================*|
// These are not possible 'char' values from a std::string.
case '\u0085': // next line
result.append("|x");
break;
case '\u2028': // line separator
result.append("|l");
break;
case '\u2029': // paragraph separator
result.append("|p");
break;
|*==========================================================================*/
case '|':
result.append("||");
break;
case '[':
result.append("|[");
break;
case ']':
result.append("|]");
break;
default:
result.push_back(c);
break;
}
}
return result;
}
};
static const apr_getopt_option_t TEST_CL_OPTIONS[] =
{
{"help", 'h', 0, "Print the help message."},
{"list", 'l', 0, "List available test groups."},
{"verbose", 'v', 0, "Verbose output."},
{"group", 'g', 1, "Run test group specified by option argument."},
{"output", 'o', 1, "Write output to the named file."},
{"sourcedir", 's', 1, "Project source file directory from CMake."},
{"touch", 't', 1, "Touch the given file if all tests succeed"},
{"wait", 'w', 0, "Wait for input before exit."},
{"debug", 'd', 0, "Emit full debug logs."},
{"suitename", 'x', 1, "Run tests using this suitename"},
{0, 0, 0, 0}
};
void stream_usage(std::ostream& s, const char* app)
{
s << "Usage: " << app << " [OPTIONS]" << std::endl
<< std::endl;
s << "This application runs the unit tests." << std::endl << std::endl;
s << "Options: " << std::endl;
const apr_getopt_option_t* option = &TEST_CL_OPTIONS[0];
while(option->name)
{
s << " ";
s << " -" << (char)option->optch << ", --" << option->name
<< std::endl;
s << "\t" << option->description << std::endl << std::endl;
++option;
}
s << app << " is also sensitive to environment variables:\n"
<< "LOGTEST=level : for all tests, emit log messages at level 'level'\n"
<< "LOGFAIL=level : only for failed tests, emit log messages at level 'level'\n"
<< "where 'level' is one of ALL, DEBUG, INFO, WARN, ERROR, NONE.\n"
<< "--debug is like LOGTEST=DEBUG, but --debug overrides LOGTEST,\n"
<< "while LOGTEST overrides LOGFAIL.\n\n";
s << "Examples:" << std::endl;
s << " " << app << " --verbose" << std::endl;
s << "\tRun all the tests and report all results." << std::endl;
s << " " << app << " --list" << std::endl;
s << "\tList all available test groups." << std::endl;
s << " " << app << " --group=uuid" << std::endl;
s << "\tRun the test group 'uuid'." << std::endl;
s << "\n\n"
<< "In any event, logs are recorded in the build directory by appending\n"
<< "the suffix '.log' to the full path name of this application.\n"
<< "If no level is specified as described above, these log files are at\n"
<< "DEBUG level.\n"
;
}
void stream_groups(std::ostream& s, const char* app)
{
s << "Registered test groups:" << std::endl;
tut::groupnames gl = tut::runner.get().list_groups();
tut::groupnames::const_iterator it = gl.begin();
tut::groupnames::const_iterator end = gl.end();
for(; it != end; ++it)
{
s << " " << *(it) << std::endl;
}
}
void wouldHaveCrashed(const std::string& message)
{
tut::fail("llerrs message: " + message);
}
static LLTrace::ThreadRecorder* sMasterThreadRecorder = NULL;
int main(int argc, char **argv)
{
ll_init_apr();
apr_getopt_t* os = NULL;
if(APR_SUCCESS != apr_getopt_init(&os, gAPRPoolp, argc, argv))
{
std::cerr << "apr_getopt_init() failed" << std::endl;
return 1;
}
// values used for controlling application
bool verbose_mode = false;
bool wait_at_exit = false;
std::string test_group;
std::string suite_name;
// LOGTEST overrides default, but can be overridden by --debug.
const char* LOGTEST = getenv("LOGTEST");
// values used for options parsing
apr_status_t apr_err;
const char* opt_arg = NULL;
int opt_id = 0;
std::unique_ptr<llofstream> output;
const char *touch = NULL;
while(true)
{
apr_err = apr_getopt_long(os, TEST_CL_OPTIONS, &opt_id, &opt_arg);
if(APR_STATUS_IS_EOF(apr_err)) break;
if(apr_err)
{
char buf[255]; /* Flawfinder: ignore */
std::cerr << "Error parsing options: "
<< apr_strerror(apr_err, buf, 255) << std::endl;
return 1;
}
switch (opt_id)
{
case 'g':
test_group.assign(opt_arg);
break;
case 'h':
stream_usage(std::cout, argv[0]);
return 0;
break;
case 'l':
stream_groups(std::cout, argv[0]);
return 0;
case 'v':
verbose_mode = true;
break;
case 'o':
output.reset(new llofstream);
output->open(opt_arg);
break;
case 's': // --sourcedir
tut::sSourceDir = opt_arg;
// For convenience, so you can use tut::sSourceDir + "myfile"
tut::sSourceDir += '/';
break;
case 't':
touch = opt_arg;
break;
case 'w':
wait_at_exit = true;
break;
case 'd':
LOGTEST = "DEBUG";
break;
case 'x':
suite_name.assign(opt_arg);
break;
default:
stream_usage(std::cerr, argv[0]);
return 1;
break;
}
}
// set up logging
const char* LOGFAIL = getenv("LOGFAIL");
std::shared_ptr<LLReplayLog> replayer{std::make_shared<LLReplayLog>()};
// Testing environment variables for both 'set' and 'not empty' allows a
// user to suppress a pre-existing environment variable by forcing empty.
if (LOGTEST && *LOGTEST)
{
LLError::initForApplication(".", ".", true /* log to stderr */);
LLError::setDefaultLevel(LLError::decodeLevel(LOGTEST));
}
else
{
LLError::initForApplication(".", ".", false /* do not log to stderr */);
LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
if (LOGFAIL && *LOGFAIL)
{
LLError::ELevel level = LLError::decodeLevel(LOGFAIL);
replayer.reset(new LLReplayLogReal(level));
}
}
LLError::setFatalFunction(wouldHaveCrashed);
std::string test_app_name(argv[0]);
std::string test_log = test_app_name + ".log";
LLFile::remove(test_log);
LLError::logToFile(test_log);
#ifdef CTYPE_WORKAROUND
ctype_workaround();
#endif
if (!sMasterThreadRecorder)
{
sMasterThreadRecorder = new LLTrace::ThreadRecorder();
LLTrace::set_master_thread_recorder(sMasterThreadRecorder);
}
// run the tests
LLTestCallback* mycallback;
if (getenv("TEAMCITY_PROJECT_NAME"))
{
mycallback = new LLTCTestCallback(verbose_mode, output.get(), replayer);
}
else
{
mycallback = new LLTestCallback(verbose_mode, output.get(), replayer);
}
// a chained_callback subclass must be linked with previous
mycallback->link();
if(test_group.empty())
{
tut::runner.get().run_tests();
}
else
{
tut::runner.get().run_tests(test_group);
}
bool success = (mycallback->getFailedTests() == 0);
if (wait_at_exit)
{
std::cerr << "Press return to exit..." << std::endl;
std::cin.get();
}
if (touch && success)
{
llofstream s;
s.open(touch);
s << "ok" << std::endl;
s.close();
}
ll_cleanup_apr();
int retval = (success ? 0 : 1);
return retval;
//delete mycallback;
}
+44
View File
@@ -0,0 +1,44 @@
/**
* @file test.h
* @author James
* @date 2009-01-12
*
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef TEST_H
#define TEST_H
#include <string>
namespace tut
{
// Source code directory from CMake, used for loading test data and
// configuration. For example:
//
// loadMyConfig( sSourceDir + "config.dat" );
//
// Use sparingly, as hitting the file system slows down test execution
// and hence every compile. JC
extern std::string sSourceDir;
}
#endif
+134
View File
@@ -0,0 +1,134 @@
#!/usr/bin/env python3
"""
@file test_llmanifest.py
@author Ryan Williams
@brief Test cases for LLManifest library.
$LicenseInfo:firstyear=2006&license=viewerlgpl$
Second Life Viewer Source Code
Copyright (C) 2010, Linden Research, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation;
version 2.1 of the License only.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
$/LicenseInfo$
"""
from indra.util import llmanifest
import os.path
import os
import unittest
class DemoManifest(llmanifest.LLManifest):
def construct(self):
super(DemoManifest, self).construct()
if self.prefix("dir_1"):
self.path("test_a")
self.path(src="test_b", dst="test_dst_b")
self.path("*.test")
self.path("*.tex", "*.jpg")
if self.prefix("nested", dst=""):
self.path("deep")
self.end_prefix()
self.end_prefix("dir_1")
class Demo_ArchManifest(llmanifest.LLManifest):
pass
class TestLLManifest(unittest.TestCase):
mode='static'
def setUp(self):
self.m = llmanifest.LLManifest({'source':'src', 'dest':'dst', 'grid':'default', 'platform':'darwin', 'version':(1,2,3,4),
'artwork':'art', 'build':'build'})
def testproperwindowspath(self):
self.assertEqual(llmanifest.proper_windows_path("C:\Program Files", "cygwin"),"/cygdrive/c/Program Files")
self.assertEqual(llmanifest.proper_windows_path("C:\Program Files", "windows"), "C:\Program Files")
self.assertEqual(llmanifest.proper_windows_path("/cygdrive/c/Program Files/NSIS", "windows"), "C:\Program Files\NSIS")
self.assertEqual(llmanifest.proper_windows_path("/cygdrive/c/Program Files/NSIS", "cygwin"), "/cygdrive/c/Program Files/NSIS")
def testpathancestors(self):
self.assertEqual(["dir"], [p for p in llmanifest.path_ancestors("dir")])
self.assertEqual(["dir/sub", "dir"], [p for p in llmanifest.path_ancestors("dir/sub")])
self.assertEqual(["dir/sub", "dir"], [p for p in llmanifest.path_ancestors("dir/sub/")])
self.assertEqual(["dir/sub/two", "dir/sub", "dir"], [p for p in llmanifest.path_ancestors("dir/sub/two")])
def testforplatform(self):
self.assertEqual(llmanifest.LLManifest.for_platform('demo'), DemoManifest)
def tmp_test():
return llmanifest.LLManifest.for_platform('extant')
self.assertRaises(KeyError, tmp_test)
ExtantManifest = llmanifest.LLManifestRegistry('ExtantManifest', (llmanifest.LLManifest,), {})
self.assertEqual(llmanifest.LLManifest.for_platform('extant'), ExtantManifest)
self.assertEqual(llmanifest.LLManifest.for_platform('demo', 'Arch'), Demo_ArchManifest)
def testprefix(self):
self.assertEqual(self.m.get_src_prefix(), "src")
self.assertEqual(self.m.get_dst_prefix(), "dst")
self.m.prefix("level1")
self.assertEqual(self.m.get_src_prefix(), "src/level1")
self.assertEqual(self.m.get_dst_prefix(), "dst/level1")
self.m.end_prefix()
self.m.prefix(src="src", dst="dst")
self.assertEqual(self.m.get_src_prefix(), "src/src")
self.assertEqual(self.m.get_dst_prefix(), "dst/dst")
self.m.end_prefix()
def testendprefix(self):
self.assertEqual(self.m.get_src_prefix(), "src")
self.assertEqual(self.m.get_dst_prefix(), "dst")
self.m.prefix("levela")
self.m.end_prefix()
self.assertEqual(self.m.get_src_prefix(), "src")
self.assertEqual(self.m.get_dst_prefix(), "dst")
self.m.prefix("level1")
self.m.end_prefix("level1")
self.assertEqual(self.m.get_src_prefix(), "src")
self.assertEqual(self.m.get_dst_prefix(), "dst")
self.m.prefix("level1")
def tmp_test():
self.m.end_prefix("mismatch")
self.assertRaises(ValueError, tmp_test)
def testruncommand(self):
self.assertEqual("Hello\n", self.m.run_command("echo Hello"))
def exit_1_test():
self.m.run_command("exit 1")
self.assertRaises(RuntimeError, exit_1_test)
def not_found_test():
self.m.run_command("test_command_that_should_not_be_found")
self.assertRaises(RuntimeError, not_found_test)
def testpathof(self):
self.assertEqual(self.m.src_path_of("a"), "src/a")
self.assertEqual(self.m.dst_path_of("a"), "dst/a")
self.m.prefix("tmp")
self.assertEqual(self.m.src_path_of("b/c"), "src/tmp/b/c")
self.assertEqual(self.m.dst_path_of("b/c"), "dst/tmp/b/c")
def testcmakedirs(self):
self.m.cmakedirs("test_dir_DELETE/nested/dir")
self.assertTrue(os.path.exists("test_dir_DELETE/nested/dir"))
self.assertTrue(os.path.isdir("test_dir_DELETE"))
self.assertTrue(os.path.isdir("test_dir_DELETE/nested"))
self.assertTrue(os.path.isdir("test_dir_DELETE/nested/dir"))
os.removedirs("test_dir_DELETE/nested/dir")
if __name__ == '__main__':
unittest.main()