merge from latest svn/viewer-2-0 to hg/viewer-2-0

master
Mark Palange (Mani) 2009-10-16 16:42:45 -07:00
commit 3e10fa4d51
523 changed files with 22496 additions and 5081 deletions

View File

@ -1,7 +1,7 @@
Linden Lab would like to acknowledge source code contributions from the
following residents. The Second Life resident name is given below,
following residents. The Second Life resident name is given below,
along with the issue identifier corresponding to the patches we've
received from them. To see more about these contributions, visit the
received from them. To see more about these contributions, visit the
browsable version: http://wiki.secondlife.com/wiki/Source_contributions
Able Whitman
@ -25,19 +25,25 @@ Aimee Trescothick
VWR-6348
VWR-6358
VWR-6360
VWR-6432
VWR-6550
VWR-6583
VWR-6482
VWR-7109
VWR-7383
VWR-7800
VWR-8008
VWR-8341
VWR-8430
VWR-8482
VWR-9255
VWR-10717
VWR-10990
VWR-11100
VWR-11111
VWR-11844
VWR-11844
VWR-14267
VWR-14278
VWR-14087
Alejandro Rosenthal
VWR-1184
@ -45,9 +51,11 @@ Aleric Inglewood
VWR-10001
VWR-10759
VWR-10837
VWR-12691
VWR-13996
VWR-14426
Ales Beaumont
VWR-9352
VWR-9352
Alissa Sabre
VWR-81
VWR-83
@ -69,7 +77,7 @@ Alissa Sabre
VWR-1351
VWR-1353
VWR-1410
VWR-1843
VWR-1843
VWR-2116
VWR-2826
VWR-3290
@ -77,19 +85,25 @@ Alissa Sabre
VWR-3857
VWR-4010
VWR-5575
VWR-5929
VWR-6384
VWR-6385
VWR-5717
VWR-5929
VWR-6384
VWR-6385
VWR-6386
VWR-6430
VWR-6430
VWR-6858
VWR-6668
VWR-7086
VWR-7087
VWR-7153
VWR-7168
VWR-6668
VWR-7086
VWR-7087
VWR-7153
VWR-7168
VWR-9190
VWR-10728
VWR-11172
VWR-12569
VWR-12617
VWR-12620
VWR-12789
Angus Boyd
VWR-592
Ann Congrejo
@ -147,6 +161,7 @@ Carjay McGinnis
VWR-4212
VWR-6154
VWR-9400
VWR-9620
Catherine Pfeffer
VWR-1282
VWR-8624
@ -294,6 +309,7 @@ Kerutsen Sellery
VWR-1350
Khyota Wulluf
VWR-2085
VWR-8885
VWR-9256
VWR-9966
Kunnis Basiat
@ -336,6 +352,7 @@ McCabe Maxsted
VWR-7877
VWR-7893
VWR-8080
VWR-8454
VWR-8689
VWR-9007
Michelle2 Zenovka
@ -350,6 +367,7 @@ Michelle2 Zenovka
VWR-5082
VWR-5659
VWR-7831
VWR-8885
VWR-8889
VWR-8310
VWR-9499
@ -464,7 +482,7 @@ Pf Shan
CT-321
princess niven
VWR-5733
CT-85
CT-85
CT-320
CT-352
Renault Clio
@ -481,7 +499,11 @@ Ringo Tuxing
Robin Cornelius
VWR-2488
VWR-9557
VWR-11128
VWR-12533
VWR-12587
VWR-12763
VWR-12995
Ryozu Kojima
VWR-53
VWR-287
@ -564,12 +586,16 @@ TBBle Kurosawa
VWR-1892
Teardrops Fall
VWR-5366
Techwolf Lupindo
SNOW-92
VWR-12385
tenebrous pau
VWR-247
Tharax Ferraris
VWR-605
Thickbrick Sleaford
VWR-7109
VWR-9287
VWR-13947
Thraxis Epsilon
SVC-371

View File

@ -170,6 +170,8 @@ if (LINUX)
if (NOT STANDALONE)
# this stops us requiring a really recent glibc at runtime
add_definitions(-fno-stack-protector)
# linking can be so slow - give us a chance to figure out why
set(CMAKE_CXX_LINK_FLAGS "-Wl,--stats,--no-keep-memory")
endif (NOT STANDALONE)
endif (VIEWER)

View File

@ -12,7 +12,7 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
#
# More info and examples at: https://wiki.secondlife.com/wiki/How_to_add_unit_tests_to_indra_code
#
# WARNING: do NOT modify this code without working with poppy or daveh -
# WARNING: do NOT modify this code without working with poppy -
# there is another branch that will conflict heavily with any changes here.
INCLUDE(GoogleMock)
@ -26,11 +26,20 @@ INCLUDE(GoogleMock)
# Setup includes, paths, etc
SET(alltest_SOURCE_FILES
${CMAKE_SOURCE_DIR}/test/test.cpp
${CMAKE_SOURCE_DIR}/test/lltut.cpp
)
SET(alltest_DEP_TARGETS
# needed by the test harness itself
${APRUTIL_LIBRARIES}
${APR_LIBRARIES}
llcommon
llmath
)
IF(NOT "${project}" STREQUAL "llmath")
# add llmath as a dep unless the tested module *is* llmath!
LIST(APPEND alltest_DEP_TARGETS
llmath
)
ENDIF(NOT "${project}" STREQUAL "llmath")
SET(alltest_INCLUDE_DIRS
${LLMATH_INCLUDE_DIRS}
${LLCOMMON_INCLUDE_DIRS}

View File

@ -13,9 +13,9 @@ if (STANDALONE)
SDL_LIBRARY
)
else (STANDALONE)
use_prebuilt_binary(SDL)
use_prebuilt_binary(mesa)
if (LINUX AND VIEWER)
use_prebuilt_binary(SDL)
set (SDL_FOUND TRUE)
set (SDL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/i686-linux)
set (SDL_LIBRARY SDL)

View File

@ -13,6 +13,10 @@ if (WINDOWS)
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.3\\InstallPath]
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.6\\InstallPath]
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath]
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath]
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.3\\InstallPath]
)
elseif (EXISTS /etc/debian_version)
# On Debian and Ubuntu, avoid Python 2.4 if possible.

View File

@ -38,7 +38,7 @@ list(APPEND linux_crash_logger_SOURCE_FILES
${linux_crash_logger_HEADER_FILES}
)
list(APPEND CMAKE_EXE_LINKER_FLAGS -Wl,--as-needed)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed")
add_executable(linux-crash-logger ${linux_crash_logger_SOURCE_FILES})

View File

@ -43,6 +43,8 @@
#include "llassetstorage.h"
#include "llrefcount.h"
#include "llvorbisencode.h"
#include "vorbis/codec.h"
#include "vorbis/vorbisfile.h"
@ -218,11 +220,42 @@ BOOL LLVorbisDecodeState::initDecode()
return(FALSE);
}
size_t size_guess = (size_t)ov_pcm_total(&mVF, -1);
S32 sample_count = ov_pcm_total(&mVF, -1);
size_t size_guess = (size_t)sample_count;
vorbis_info* vi = ov_info(&mVF, -1);
size_guess *= vi->channels;
size_guess *= 2;
size_guess += 2048;
bool abort_decode = false;
if( vi->channels < 1 || vi->channels > LLVORBIS_CLIP_MAX_CHANNELS )
{
abort_decode = true;
llwarns << "Bad channel count: " << vi->channels << llendl;
}
if( (size_t)sample_count > LLVORBIS_CLIP_REJECT_SAMPLES )
{
abort_decode = true;
llwarns << "Illegal sample count: " << sample_count << llendl;
}
if( size_guess > LLVORBIS_CLIP_REJECT_SIZE )
{
abort_decode = true;
llwarns << "Illegal sample size: " << size_guess << llendl;
}
if( abort_decode )
{
llwarns << "Canceling initDecode. Bad asset: " << mUUID << llendl;
llwarns << "Bad asset encoded by: " << ov_comment(&mVF,-1)->vendor << llendl;
delete mInFilep;
mInFilep = NULL;
return FALSE;
}
mWAVBuffer.reserve(size_guess);
mWAVBuffer.resize(WAV_HEADER_SIZE);

View File

@ -132,6 +132,7 @@ bool LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata)
bool audio_ok = false;
if (!audio_ok)
{
if (NULL == getenv("LL_BAD_FMOD_ESD")) /*Flawfinder: ignore*/
{
LL_DEBUGS("AppInit") << "Trying ESD audio output..." << LL_ENDL;
@ -148,8 +149,9 @@ bool LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata)
} else {
LL_DEBUGS("AppInit") << "ESD audio output SKIPPED" << LL_ENDL;
}
}
if (!audio_ok)
{
if (NULL == getenv("LL_BAD_FMOD_OSS")) /*Flawfinder: ignore*/
{
LL_DEBUGS("AppInit") << "Trying OSS audio output..." << LL_ENDL;
@ -165,8 +167,9 @@ bool LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata)
} else {
LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL;
}
}
if (!audio_ok)
{
if (NULL == getenv("LL_BAD_FMOD_ALSA")) /*Flawfinder: ignore*/
{
LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL;
@ -182,7 +185,7 @@ bool LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata)
} else {
LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL;
}
}
if (!audio_ok)
{
LL_WARNS("AppInit") << "Overall audio init failure." << LL_ENDL;

View File

@ -162,13 +162,13 @@ S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& erro
return(LLVORBISENC_PCM_FORMAT_ERR);
}
if ((num_channels < 1) || (num_channels > 2))
if ((num_channels < 1) || (num_channels > LLVORBIS_CLIP_MAX_CHANNELS))
{
error_msg = "SoundFileInvalidChannelCount";
return(LLVORBISENC_MULTICHANNEL_ERR);
}
if (sample_rate != 44100)
if (sample_rate != LLVORBIS_CLIP_SAMPLE_RATE)
{
error_msg = "SoundFileInvalidSampleRate";
return(LLVORBISENC_UNSUPPORTED_SAMPLE_RATE);
@ -188,7 +188,7 @@ S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& erro
F32 clip_length = (F32)raw_data_length/(F32)bytes_per_sec;
if (clip_length > 10.0f)
if (clip_length > LLVORBIS_CLIP_MAX_TIME)
{
error_msg = "SoundFileInvalidTooLong";
return(LLVORBISENC_CLIP_TOO_LONG);

View File

@ -45,6 +45,17 @@ const S32 LLVORBISENC_UNSUPPORTED_SAMPLE_RATE = 8; // unsupported sample ra
const S32 LLVORBISENC_UNSUPPORTED_WORD_SIZE = 9; // unsupported word size
const S32 LLVORBISENC_CLIP_TOO_LONG = 10; // source file is too long
const F32 LLVORBIS_CLIP_MAX_TIME = 10.0f;
const U8 LLVORBIS_CLIP_MAX_CHANNELS = 2;
const U32 LLVORBIS_CLIP_SAMPLE_RATE = 44100;
const U32 LLVORBIS_CLIP_MAX_SAMPLES_PER_CHANNEL = (U32)(LLVORBIS_CLIP_MAX_TIME * LLVORBIS_CLIP_SAMPLE_RATE);
const U32 LLVORBIS_CLIP_MAX_SAMPLES = LLVORBIS_CLIP_MAX_SAMPLES_PER_CHANNEL * LLVORBIS_CLIP_MAX_CHANNELS;
const size_t LLVORBIS_CLIP_MAX_SAMPLE_DATA = LLVORBIS_CLIP_MAX_SAMPLES * 2; // 2 = 16-bit
// Treat anything this long as a bad asset. A little fudge factor at the end:
// Make that a lot of fudge factor. We're allowing 30 sec for now - 3x legal upload
const size_t LLVORBIS_CLIP_REJECT_SAMPLES = LLVORBIS_CLIP_MAX_SAMPLES * 3;
const size_t LLVORBIS_CLIP_REJECT_SIZE = LLVORBIS_CLIP_MAX_SAMPLE_DATA * 3;
S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& error_msg);
S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname);

View File

@ -75,3 +75,13 @@ set_source_files_properties(${llcharacter_HEADER_FILES}
list(APPEND llcharacter_SOURCE_FILES ${llcharacter_HEADER_FILES})
add_library (llcharacter ${llcharacter_SOURCE_FILES})
# Add tests
include(LLAddBuildTest)
# UNIT TESTS
SET(llcharacter_TEST_SOURCE_FILES
lljoint.cpp
)
LL_ADD_PROJECT_UNIT_TESTS(llcharacter "${llcharacter_TEST_SOURCE_FILES}")

View File

@ -91,7 +91,9 @@ const char *LLBVHLoader::ST_NO_XLT_EASEIN = "Can't get easeIn values.";
const char *LLBVHLoader::ST_NO_XLT_EASEOUT = "Can't get easeOut values.";
const char *LLBVHLoader::ST_NO_XLT_HAND = "Can't get hand morph value.";
const char *LLBVHLoader::ST_NO_XLT_EMOTE = "Can't read emote name.";
const char *LLBVHLoader::ST_BAD_ROOT = "Illegal ROOT joint.";
*/
//------------------------------------------------------------------------
// find_next_whitespace()
//------------------------------------------------------------------------
@ -777,6 +779,17 @@ ELoadStatus LLBVHLoader::loadBVHFile(const char *buffer, char* error_text, S32 &
return E_ST_NO_NAME;
}
//---------------------------------------------------------------
// we require the root joint be "hip" - DEV-26188
//---------------------------------------------------------------
const char* FORCED_ROOT_NAME = "hip";
if ( (mJoints.size() == 0 ) && ( !strstr(jointName, FORCED_ROOT_NAME) ) )
{
strncpy(error_text, line.c_str(), 127); /* Flawfinder: ignore */
return E_ST_BAD_ROOT;
}
//----------------------------------------------------------------
// add a set of keyframes for this joint
//----------------------------------------------------------------

View File

@ -216,7 +216,8 @@ typedef enum e_load_status
E_ST_NO_XLT_EASEIN,
E_ST_NO_XLT_EASEOUT,
E_ST_NO_XLT_HAND,
E_ST_NO_XLT_EMOTE
E_ST_NO_XLT_EMOTE,
E_ST_BAD_ROOT
} ELoadStatus;
//------------------------------------------------------------------------
@ -235,7 +236,7 @@ public:
/*
// Status Codes
typedef const char *Status;
typedef const char *status_t;
static const char *ST_OK;
static const char *ST_EOF;
static const char *ST_NO_CONSTRAINT;
@ -267,6 +268,7 @@ public:
static const char *ST_NO_XLT_EASEOUT;
static const char *ST_NO_XLT_HAND;
static const char *ST_NO_XLT_EMOTE;
static const char *ST_BAD_ROOT;
*/
// Loads the specified translation table.
ELoadStatus loadTranslationTable(const char *fileName);
@ -325,6 +327,7 @@ protected:
BOOL mInitialized;
ELoadStatus mStatus;
// computed values
F32 mDuration;
};

View File

@ -304,7 +304,7 @@ BOOL LLGestureList::trigger(KEY key, MASK mask)
}
else
{
llwarns << "NULL gesture in gesture list (" << i << ")" << llendl
llwarns << "NULL gesture in gesture list (" << i << ")" << llendl;
}
}
return FALSE;

View File

@ -211,7 +211,7 @@ void LLJointSolverRP3::solve()
//-------------------------------------------------------------------------
LLVector3 abacCompOrthoVec = abVec - acVec * ((abVec * acVec)/(acVec * acVec));
// llinfos << "abacCompOrthoVec : " << abacCompOrthoVec << llendl
// llinfos << "abacCompOrthoVec : " << abacCompOrthoVec << llendl;
//-------------------------------------------------------------------------
// compute the normal of the original ABC plane (and store for later)

View File

@ -0,0 +1,246 @@
/**
* @file lljoint_tut.cpp
* @author Adroit
* @date 2007-03
* @brief lljoint test cases.
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "m4math.h"
#include "v3math.h"
#include "../lljoint.h"
#include "../test/lltut.h"
namespace tut
{
struct lljoint_data
{
};
typedef test_group<lljoint_data> lljoint_test;
typedef lljoint_test::object lljoint_object;
tut::lljoint_test lljoint_testcase("lljoint");
template<> template<>
void lljoint_object::test<1>()
{
LLJoint lljoint;
LLJoint* jnt = lljoint.getParent();
ensure("getParent() failed ", (NULL == jnt));
ensure("getRoot() failed ", (&lljoint == lljoint.getRoot()));
}
template<> template<>
void lljoint_object::test<2>()
{
std::string str = "LLJoint";
LLJoint parent(str), child;
child.setup(str, &parent);
LLJoint* jnt = child.getParent();
ensure("setup() failed ", (&parent == jnt));
}
template<> template<>
void lljoint_object::test<3>()
{
LLJoint parent, child;
std::string str = "LLJoint";
child.setup(str, &parent);
LLJoint* jnt = parent.findJoint(str);
ensure("findJoint() failed ", (&child == jnt));
}
template<> template<>
void lljoint_object::test<4>()
{
LLJoint parent;
std::string str1 = "LLJoint", str2;
parent.setName(str1);
str2 = parent.getName();
ensure("setName() failed ", (str1 == str2));
}
template<> template<>
void lljoint_object::test<5>()
{
LLJoint lljoint;
LLVector3 vec3(2.3f,30.f,10.f);
lljoint.setPosition(vec3);
LLVector3 pos = lljoint.getPosition();
ensure("setPosition()/getPosition() failed ", (vec3 == pos));
}
template<> template<>
void lljoint_object::test<6>()
{
LLJoint lljoint;
LLVector3 vec3(2.3f,30.f,10.f);
lljoint.setWorldPosition(vec3);
LLVector3 pos = lljoint.getWorldPosition();
ensure("1:setWorldPosition()/getWorldPosition() failed ", (vec3 == pos));
LLVector3 lastPos = lljoint.getLastWorldPosition();
ensure("2:getLastWorldPosition failed ", (vec3 == lastPos));
}
template<> template<>
void lljoint_object::test<7>()
{
LLJoint lljoint("LLJoint");
LLQuaternion q(2.3f,30.f,10.f,1.f);
lljoint.setRotation(q);
LLQuaternion rot = lljoint.getRotation();
ensure("setRotation()/getRotation() failed ", (q == rot));
}
template<> template<>
void lljoint_object::test<8>()
{
LLJoint lljoint("LLJoint");
LLQuaternion q(2.3f,30.f,10.f,1.f);
lljoint.setWorldRotation(q);
LLQuaternion rot = lljoint.getWorldRotation();
ensure("1:setWorldRotation()/getWorldRotation() failed ", (q == rot));
LLQuaternion lastRot = lljoint.getLastWorldRotation();
ensure("2:getLastWorldRotation failed ", (q == lastRot));
}
template<> template<>
void lljoint_object::test<9>()
{
LLJoint lljoint;
LLVector3 vec3(2.3f,30.f,10.f);
lljoint.setScale(vec3);
LLVector3 scale = lljoint.getScale();
ensure("setScale()/getScale failed ", (vec3 == scale));
}
template<> template<>
void lljoint_object::test<10>()
{
LLJoint lljoint("LLJoint");
LLMatrix4 mat;
mat.setIdentity();
lljoint.setWorldMatrix(mat);//giving warning setWorldMatrix not correctly implemented;
LLMatrix4 mat4 = lljoint.getWorldMatrix();
ensure("setWorldMatrix()/getWorldMatrix failed ", (mat4 == mat));
}
template<> template<>
void lljoint_object::test<11>()
{
LLJoint lljoint("parent");
S32 joint_num = 12;
lljoint.setJointNum(joint_num);
S32 jointNum = lljoint.getJointNum();
ensure("setJointNum()/getJointNum failed ", (jointNum == joint_num));
}
template<> template<>
void lljoint_object::test<12>()
{
LLJoint lljoint;
LLVector3 vec3(2.3f,30.f,10.f);
lljoint.setSkinOffset(vec3);
LLVector3 offset = lljoint.getSkinOffset();
ensure("1:setSkinOffset()/getSkinOffset() failed ", (vec3 == offset));
}
template<> template<>
void lljoint_object::test<13>()
{
LLJoint lljointgp("gparent");
LLJoint lljoint("parent");
LLJoint lljoint1("child1");
lljoint.addChild(&lljoint1);
LLJoint lljoint2("child2");
lljoint.addChild(&lljoint2);
LLJoint lljoint3("child3");
lljoint.addChild(&lljoint3);
LLJoint* jnt = NULL;
jnt = lljoint2.getParent();
ensure("addChild() failed ", (&lljoint == jnt));
LLJoint* jnt1 = lljoint.findJoint("child3");
ensure("findJoint() failed ", (&lljoint3 == jnt1));
lljoint.removeChild(&lljoint3);
LLJoint* jnt2 = lljoint.findJoint("child3");
ensure("removeChild() failed ", (NULL == jnt2));
lljointgp.addChild(&lljoint);
ensure("GetParent() failed ", (&lljoint== lljoint2.getParent()));
ensure("getRoot() failed ", (&lljointgp == lljoint2.getRoot()));
ensure("getRoot() failed ", &lljoint1 == lljoint.findJoint("child1"));
lljointgp.removeAllChildren();
// parent removed from grandparent - so should not be able to locate child
ensure("removeAllChildren() failed ", (NULL == lljointgp.findJoint("child1")));
// it should still exist in parent though
ensure("removeAllChildren() failed ", (&lljoint1 == lljoint.findJoint("child1")));
}
template<> template<>
void lljoint_object::test<14>()
{
LLJoint lljointgp("gparent");
LLJoint llparent1("parent1");
LLJoint llparent2("parent2");
LLJoint llchild("child1");
LLJoint lladoptedchild("child2");
llparent1.addChild(&llchild);
llparent1.addChild(&lladoptedchild);
llparent2.addChild(&lladoptedchild);
ensure("1. addChild failed to remove prior parent", lladoptedchild.getParent() == &llparent2);
ensure("2. addChild failed to remove prior parent", llparent1.findJoint("child2") == NULL);
}
/*
Test cases for the following not added. They perform operations
on underlying LLXformMatrix and LLVector3 elements which have
been unit tested separately.
Unit Testing these functions will basically require re-implementing
logic of these function in the test case itself
1) void WorldMatrixChildren();
2) void updateWorldMatrixParent();
3) void updateWorldPRSParent();
4) void updateWorldMatrix();
5) LLXformMatrix *getXform() { return &mXform; }
6) void setConstraintSilhouette(LLDynamicArray<LLVector3>& silhouette);
7) void clampRotation(LLQuaternion old_rot, LLQuaternion new_rot);
*/
}

View File

@ -3,7 +3,6 @@
project(llcommon)
include(00-Common)
include(LLAddBuildTest)
include(LLCommon)
include(Linking)
include(Boost)
@ -291,16 +290,27 @@ add_dependencies(llcommon stage_third_party_libs)
include(LLAddBuildTest)
SET(llcommon_TEST_SOURCE_FILES
# unit-testing llcommon is not possible right now as the test-harness *itself* depends upon llcommon, causing a circular dependency. Add your 'unit' tests as integration tests for now.
)
LL_ADD_PROJECT_UNIT_TESTS(llcommon "${llcommon_TEST_SOURCE_FILES}")
#set(TEST_DEBUG on)
set(test_libs llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES} ${GOOGLEMOCK_LIBRARIES})
# Have to treat lllazy test as an integration test until this issue is resolved:
# https://jira.lindenlab.com/jira/browse/DEV-29456
LL_ADD_INTEGRATION_TEST(lllazy lllazy.cpp "${test_libs}")
LL_ADD_INTEGRATION_TEST(commonmisc "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(bitpack "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llbase64 "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(lldate "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llerror "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llframetimer "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(lllazy "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(lluri "" "${test_libs}")
# *TODO - reenable these once tcmalloc libs no longer break the build.
#ADD_BUILD_TEST(llallocator llcommon)
#ADD_BUILD_TEST(llallocator_heap_profile llcommon)
#ADD_BUILD_TEST(llmemtype llcommon)

View File

@ -0,0 +1,36 @@
/**
* @file bitpack.cpp
* @brief LLBitPack class implementation
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
// implementation is all in the header, this include dep ensures the unit test is rerun if the implementation changes.
#include "bitpack.h"

View File

@ -35,6 +35,8 @@
#ifndef LL_LLDATE_H
#define LL_LLDATE_H
#include "linden_common.h"
#include <iosfwd>
#include <string>

View File

@ -239,7 +239,7 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
*/
#define lllog(level, broadTag, narrowTag, once) \
{ \
do { \
static LLError::CallSite _site( \
level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, broadTag, narrowTag, once);\
if (_site.shouldLog()) \
@ -252,7 +252,7 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
LLError::End(); \
LLError::Log::flush(_out, _site); \
} \
}
} while(0)
// DEPRECATED: Use the new macros that allow tags and *look* like macros.
#define lldebugs lllog(LLError::LEVEL_DEBUG, NULL, NULL, false)

View File

@ -37,7 +37,75 @@
#define FAST_TIMER_ON 1
LL_COMMON_API U64 get_cpu_clock_count();
#if LL_WINDOWS
// shift off lower 8 bits for lower resolution but longer term timing
// on 1Ghz machine, a 32-bit word will hold ~1000 seconds of timing
inline U32 get_cpu_clock_count_32()
{
U32 ret_val;
__asm
{
_emit 0x0f
_emit 0x31
shr eax,8
shl edx,24
or eax, edx
mov dword ptr [ret_val], eax
}
return ret_val;
}
// return full timer value, still shifted by 8 bits
inline U64 get_cpu_clock_count_64()
{
U64 ret_val;
__asm
{
_emit 0x0f
_emit 0x31
mov eax,eax
mov edx,edx
mov dword ptr [ret_val+4], edx
mov dword ptr [ret_val], eax
}
return ret_val >> 8;
}
#endif // LL_WINDOWS
#if (LL_LINUX || LL_SOLARIS || LL_DARWIN) && (defined(__i386__) || defined(__amd64__))
inline U32 get_cpu_clock_count_32()
{
U64 x;
__asm__ volatile (".byte 0x0f, 0x31": "=A"(x));
return (U32)x >> 8;
}
inline U32 get_cpu_clock_count_64()
{
U64 x;
__asm__ volatile (".byte 0x0f, 0x31": "=A"(x));
return x >> 8;
}
#endif
#if ( LL_DARWIN && !(defined(__i386__) || defined(__amd64__))) || (LL_SOLARIS && defined(__sparc__))
//
// Mac PPC (deprecated) & Solaris SPARC implementation of CPU clock
//
// Just use gettimeofday implementation for now
inline U32 get_cpu_clock_count_32()
{
return (U32)get_clock_count();
}
inline U32 get_cpu_clock_count_64()
{
return get_clock_count();
}
#endif
class LLMutex;
@ -52,13 +120,14 @@ public:
class LL_COMMON_API NamedTimer
: public LLInstanceTracker<NamedTimer>
{
friend class DeclareTimer;
public:
~NamedTimer();
enum { HISTORY_NUM = 60 };
const std::string& getName() { return mName; }
NamedTimer* getParent() { return mParent; }
const std::string& getName() const { return mName; }
NamedTimer* getParent() const { return mParent; }
void setParent(NamedTimer* parent);
S32 getDepth();
std::string getToolTip(S32 history_index = -1);
@ -71,11 +140,11 @@ public:
void setCollapsed(bool collapsed) { mCollapsed = collapsed; }
bool getCollapsed() const { return mCollapsed; }
U64 getCountAverage() const { return mCountAverage; }
U64 getCallAverage() const { return mCallAverage; }
U32 getCountAverage() const { return mCountAverage; }
U32 getCallAverage() const { return mCallAverage; }
U64 getHistoricalCount(S32 history_index = 0) const;
U64 getHistoricalCalls(S32 history_index = 0) const;
U32 getHistoricalCount(S32 history_index = 0) const;
U32 getHistoricalCalls(S32 history_index = 0) const;
static NamedTimer& getRootNamedTimer();
@ -83,8 +152,7 @@ public:
{
FrameState(NamedTimer* timerp);
U64 mSelfTimeCounter;
U64 mLastStartTime; // most recent time when this timer was started
U32 mSelfTimeCounter;
U32 mCalls;
FrameState* mParent; // info for caller timer
FrameState* mLastCaller; // used to bootstrap tree construction
@ -93,11 +161,6 @@ public:
bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame
};
FrameState& getFrameStateFast() const
{
return (*sTimerInfos)[mFrameStateIndex];
}
S32 getFrameStateIndex() const { return mFrameStateIndex; }
FrameState& getFrameState() const;
@ -122,10 +185,7 @@ public:
static void resetFrame();
static void reset();
typedef std::vector<FrameState> info_list_t;
static info_list_t& getFrameStateList();
static void createFrameStateList(); // must call before any call to getFrameStateList()
//
// members
//
@ -133,13 +193,13 @@ public:
std::string mName;
U64 mTotalTimeCounter;
U32 mTotalTimeCounter;
U64 mCountAverage;
U64 mCallAverage;
U32 mCountAverage;
U32 mCallAverage;
U64* mCountHistory;
U64* mCallHistory;
U32* mCountHistory;
U32* mCallHistory;
// tree structure
NamedTimer* mParent; // NamedTimer of caller(parent)
@ -147,41 +207,46 @@ public:
bool mCollapsed; // don't show children
bool mNeedsSorting; // sort children whenever child added
static info_list_t* sTimerInfos;
};
// used to statically declare a new named timer
class LL_COMMON_API DeclareTimer
: public LLInstanceTracker<DeclareTimer>
{
public:
DeclareTimer(const std::string& name, bool open);
DeclareTimer(const std::string& name);
static void updateCachedPointers();
// convertable to NamedTimer::FrameState for convenient usage of LLFastTimer(declared_timer)
operator NamedTimer::FrameState&() { return mNamedTimer.getFrameStateFast(); }
operator NamedTimer::FrameState&() { return *mFrameState; }
private:
NamedTimer& mNamedTimer;
NamedTimer& mTimer;
NamedTimer::FrameState* mFrameState;
};
public:
enum RootTimerMarker { ROOT };
static LLMutex* sLogLock;
static std::queue<LLSD> sLogQueue;
static BOOL sLog;
static BOOL sMetricLog;
typedef std::vector<NamedTimer::FrameState> info_list_t;
static info_list_t& getFrameStateList();
enum RootTimerMarker { ROOT };
LLFastTimer(RootTimerMarker);
LLFastTimer(NamedTimer::FrameState& timer)
: mFrameState(&timer)
{
#if FAST_TIMER_ON
NamedTimer::FrameState* frame_state = mFrameState;
U64 cur_time = get_cpu_clock_count();
frame_state->mLastStartTime = cur_time;
NamedTimer::FrameState* frame_state = &timer;
U32 cur_time = get_cpu_clock_count_32();
mStartSelfTime = cur_time;
mStartTotalTime = cur_time;
frame_state->mActiveCount++;
frame_state->mCalls++;
@ -197,7 +262,7 @@ public:
{
#if FAST_TIMER_ON
NamedTimer::FrameState* frame_state = mFrameState;
U64 cur_time = get_cpu_clock_count();
U32 cur_time = get_cpu_clock_count_32();
frame_state->mSelfTimeCounter += cur_time - mStartSelfTime;
frame_state->mActiveCount--;
@ -208,7 +273,7 @@ public:
frame_state->mLastCaller = last_timer->mFrameState;
// we are only tracking self time, so subtract our total time delta from parents
U64 total_time = cur_time - frame_state->mLastStartTime;
U32 total_time = cur_time - mStartTotalTime;
last_timer->mStartSelfTime += total_time;
#endif
}
@ -240,9 +305,11 @@ private:
static LLFastTimer* sCurTimer;
static S32 sCurFrameIndex;
static S32 sLastFrameIndex;
static U64 sLastFrameTime;
static info_list_t* sTimerInfos;
static F64 sCPUClockFrequency;
U64 mStartSelfTime; // start time + time of all child timers
U32 mStartSelfTime; // start time + time of all child timers
U32 mStartTotalTime; // start time + time of all child timers
NamedTimer::FrameState* mFrameState;
LLFastTimer* mLastTimer;
};

View File

@ -71,17 +71,13 @@ private:
static std::map<KEY, T*>& getMap()
{
if (! sInstances)
{
sInstances = new std::map<KEY, T*>;
}
static std::map<KEY, T*>* sInstances = new std::map<KEY, T*>();
return *sInstances;
}
private:
KEY mKey;
static std::map<KEY, T*>* sInstances;
};
// explicit specialization for default case where KEY is T*
@ -105,17 +101,10 @@ protected:
static std::set<T*>& getSet() // called after getReady() but before go()
{
if (! sInstances)
{
sInstances = new std::set<T*>;
}
static std::set<T*>* sInstances = new std::set<T*>();
return *sInstances;
}
static std::set<T*>* sInstances;
};
template <typename T, typename KEY> std::map<KEY, T*>* LLInstanceTracker<T, KEY>::sInstances = NULL;
template <typename T> std::set<T*>* LLInstanceTracker<T, T*>::sInstances = NULL;
#endif

View File

@ -1018,7 +1018,11 @@ S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions)
bool found_replacement = false;
std::string replacement;
if (tokens.size() == 1)
if (tokens.size() == 0)
{
found_replacement = false;
}
else if (tokens.size() == 1)
{
found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
}
@ -1054,9 +1058,9 @@ S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions)
}
else
{
// we had no replacement, so leave the string we searched for so that it gets noticed by QA
// "hello [NAME_NOT_FOUND]" is output
output += std::string("[") + tokens[0] + std::string("]");
// we had no replacement, use the string as is
// e.g. "hello [MISSING_REPLACEMENT]" or "-=[Stylized Name]=-"
output += std::string(s, key_start, start-key_start);
}
tokens.clear();
}
@ -1092,7 +1096,11 @@ S32 LLStringUtil::format(std::string& s, const LLSD& substitutions)
bool found_replacement = false;
std::string replacement;
if (tokens.size() == 1)
if (tokens.size() == 0)
{
found_replacement = false;
}
else if (tokens.size() == 1)
{
found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
}
@ -1120,9 +1128,9 @@ S32 LLStringUtil::format(std::string& s, const LLSD& substitutions)
}
else
{
// we had no replacement, so leave the string we searched for so that it gets noticed by QA
// "hello [NAME_NOT_FOUND]" is output
output += std::string("[") + tokens[0] + std::string("]");
// we had no replacement, use the string as is
// e.g. "hello [MISSING_REPLACEMENT]" or "-=[Stylized Name]=-"
output += std::string(s, key_start, start-key_start);
}
tokens.clear();
}

View File

@ -34,6 +34,7 @@
#define LL_LLSTRING_H
#include <string>
#include <cstdio>
#include <locale>
#include <iomanip>
#include "llsd.h"
@ -998,14 +999,15 @@ void LLStringUtilBase<T>::stripNonprintable(std::basic_string<T>& string)
{
return;
}
char* c_string = new char[string.size() + 1];
size_t src_size = string.size();
char* c_string = new char[src_size + 1];
if(c_string == NULL)
{
return;
}
strcpy(c_string, string.c_str()); /*Flawfinder: ignore*/
copy(c_string, string.c_str(), src_size+1);
char* write_head = &c_string[0];
for (size_type i = 0; i < string.size(); i++)
for (size_type i = 0; i < src_size; i++)
{
char* read_head = &string[i];
write_head = &c_string[j];

View File

@ -124,9 +124,42 @@ LLOSInfo::LLOSInfo() :
}
else if(osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0)
{
if(osvi.wProductType == VER_NT_WORKSTATION)
mOSStringSimple = "Microsoft Windows Vista ";
else mOSStringSimple = "Microsoft Windows Vista Server ";
///get native system info if available..
typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO); ///function pointer for loading GetNativeSystemInfo
SYSTEM_INFO si; //System Info object file contains architecture info
PGNSI pGNSI; //pointer object
ZeroMemory(&si, sizeof(SYSTEM_INFO)); //zero out the memory in information
pGNSI = (PGNSI) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo"); //load kernel32 get function
if(NULL != pGNSI) //check if it has failed
pGNSI(&si); //success
else
GetSystemInfo(&si); //if it fails get regular system info
//(Warning: If GetSystemInfo it may result in incorrect information in a WOW64 machine, if the kernel fails to load)
//msdn microsoft finds 32 bit and 64 bit flavors this way..
//http://msdn.microsoft.com/en-us/library/ms724429(VS.85).aspx (example code that contains quite a few more flavors
//of windows than this code does (in case it is needed for the future)
if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 ) //check for 64 bit
{
if(osvi.wProductType == VER_NT_WORKSTATION)
mOSStringSimple = "Microsoft Windows Vista 64-bit ";
else
mOSStringSimple = "Microsoft Windows Vista Server 64-bit ";
}
else if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL )
{
if(osvi.wProductType == VER_NT_WORKSTATION)
mOSStringSimple = "Microsoft Windows Vista 32-bit ";
else
mOSStringSimple = "Microsoft Windows Vista Server 32-bit ";
}
else // PROCESSOR_ARCHITECTURE_IA64 || PROCESSOR_ARCHITECTURE_UNKNOWN not checked
{
if(osvi.wProductType == VER_NT_WORKSTATION)
mOSStringSimple = "Microsoft Windows Vista ";
else
mOSStringSimple = "Microsoft Windows Vista Server ";
}
}
else if(osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 1)
{

View File

@ -0,0 +1,125 @@
/**
* @file bitpack_test.cpp
* @author Adroit
* @date 2007-02
* @brief llstreamtools test cases.
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "../bitpack.h"
#include "../test/lltut.h"
namespace tut
{
struct bit_pack
{
};
typedef test_group<bit_pack> bit_pack_t;
typedef bit_pack_t::object bit_pack_object_t;
tut::bit_pack_t tut_bit_pack("bitpack");
// pack -> unpack
template<> template<>
void bit_pack_object_t::test<1>()
{
U8 packbuffer[255];
U8 unpackbuffer[255];
int pack_bufsize = 0;
int unpack_bufsize = 0;
LLBitPack bitpack(packbuffer, 255);
char str[] = "SecondLife is a 3D virtual world";
int len = sizeof(str);
pack_bufsize = bitpack.bitPack((U8*) str, len*8);
pack_bufsize = bitpack.flushBitPack();
LLBitPack bitunpack(packbuffer, pack_bufsize*8);
unpack_bufsize = bitunpack.bitUnpack(unpackbuffer, len*8);
ensure("bitPack: unpack size should be same as string size prior to pack", len == unpack_bufsize);
ensure_memory_matches("str->bitPack->bitUnpack should be equal to string", str, len, unpackbuffer, unpack_bufsize);
}
// pack large, unpack in individual bytes
template<> template<>
void bit_pack_object_t::test<2>()
{
U8 packbuffer[255];
U8 unpackbuffer[255];
int pack_bufsize = 0;
int unpack_bufsize = 0;
LLBitPack bitpack(packbuffer, 255);
char str[] = "SecondLife";
int len = sizeof(str);
pack_bufsize = bitpack.bitPack((U8*) str, len*8);
pack_bufsize = bitpack.flushBitPack();
LLBitPack bitunpack(packbuffer, pack_bufsize*8);
unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8);
ensure("bitPack: individual unpack: 0", unpackbuffer[0] == (U8) str[0]);
unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8);
ensure("bitPack: individual unpack: 1", unpackbuffer[0] == (U8) str[1]);
unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8);
ensure("bitPack: individual unpack: 2", unpackbuffer[0] == (U8) str[2]);
unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8);
ensure("bitPack: individual unpack: 3", unpackbuffer[0] == (U8) str[3]);
unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8);
ensure("bitPack: individual unpack: 4", unpackbuffer[0] == (U8) str[4]);
unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8);
ensure("bitPack: individual unpack: 5", unpackbuffer[0] == (U8) str[5]);
unpack_bufsize = bitunpack.bitUnpack(unpackbuffer, 8*4); // Life
ensure_memory_matches("bitPack: 4 bytes unpack:", unpackbuffer, 4, str+6, 4);
}
// U32 packing
template<> template<>
void bit_pack_object_t::test<3>()
{
U8 packbuffer[255];
int pack_bufsize = 0;
LLBitPack bitpack(packbuffer, 255);
U32 num = 0x41fab67a;
pack_bufsize = bitpack.bitPack((U8*)&num, 8*sizeof(U32));
pack_bufsize = bitpack.flushBitPack();
LLBitPack bitunpack(packbuffer, pack_bufsize*8);
U32 res = 0;
// since packing and unpacking is done on same machine in the unit test run,
// endianness should not matter
bitunpack.bitUnpack((U8*) &res, sizeof(res)*8);
ensure("U32->bitPack->bitUnpack->U32 should be equal", num == res);
}
}

View File

@ -0,0 +1,677 @@
/**
* @file common.cpp
* @author Phoenix
* @date 2005-10-12
* @brief Common templates for test framework
*
* $LicenseInfo:firstyear=2005&license=viewergpl$
*
* Copyright (c) 2005-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
/**
*
* THOROUGH_DESCRIPTION of common.cpp
*
*/
#include <algorithm>
#include <iomanip>
#include <iterator>
#include "linden_common.h"
#include "../llmemorystream.h"
#include "../llsd.h"
#include "../llsdserialize.h"
#include "../u64.h"
#include "../llhash.h"
#include "../test/lltut.h"
#if LL_WINDOWS
// disable overflow warnings
#pragma warning(disable: 4307)
#endif
namespace tut
{
struct sd_data
{
};
typedef test_group<sd_data> sd_test;
typedef sd_test::object sd_object;
tut::sd_test sd("llsd");
template<> template<>
void sd_object::test<1>()
{
std::ostringstream resp;
resp << "{'connect':true, 'position':[r128,r128,r128], 'look_at':[r0,r1,r0], 'agent_access':'M', 'region_x':i8192, 'region_y':i8192}";
std::string str = resp.str();
LLMemoryStream mstr((U8*)str.c_str(), str.size());
LLSD response;
S32 count = LLSDSerialize::fromNotation(response, mstr, str.size());
ensure("stream parsed", response.isDefined());
ensure_equals("stream parse count", count, 13);
ensure_equals("sd type", response.type(), LLSD::TypeMap);
ensure_equals("map element count", response.size(), 6);
ensure_equals("value connect", response["connect"].asBoolean(), true);
ensure_equals("value region_x", response["region_x"].asInteger(),8192);
ensure_equals("value region_y", response["region_y"].asInteger(),8192);
}
template<> template<>
void sd_object::test<2>()
{
const std::string decoded("random");
//const std::string encoded("cmFuZG9t\n");
const std::string streamed("b(6)\"random\"");
typedef std::vector<U8> buf_t;
buf_t buf;
std::copy(
decoded.begin(),
decoded.end(),
std::back_insert_iterator<buf_t>(buf));
LLSD sd;
sd = buf;
std::stringstream str;
S32 count = LLSDSerialize::toNotation(sd, str);
ensure_equals("output count", count, 1);
std::string actual(str.str());
ensure_equals("formatted binary encoding", actual, streamed);
sd.clear();
LLSDSerialize::fromNotation(sd, str, str.str().size());
std::vector<U8> after;
after = sd.asBinary();
ensure_equals("binary decoded size", after.size(), decoded.size());
ensure("binary decoding", (0 == memcmp(
&after[0],
decoded.c_str(),
decoded.size())));
}
template<> template<>
void sd_object::test<3>()
{
for(S32 i = 0; i < 100; ++i)
{
// gen up a starting point
typedef std::vector<U8> buf_t;
buf_t source;
srand(i); /* Flawfinder: ignore */
S32 size = rand() % 1000 + 10;
std::generate_n(
std::back_insert_iterator<buf_t>(source),
size,
rand);
LLSD sd(source);
std::stringstream str;
S32 count = LLSDSerialize::toNotation(sd, str);
sd.clear();
ensure_equals("format count", count, 1);
LLSD sd2;
count = LLSDSerialize::fromNotation(sd2, str, str.str().size());
ensure_equals("parse count", count, 1);
buf_t dest = sd2.asBinary();
str.str("");
str << "binary encoding size " << i;
ensure_equals(str.str().c_str(), dest.size(), source.size());
str.str("");
str << "binary encoding " << i;
ensure(str.str().c_str(), (source == dest));
}
}
template<> template<>
void sd_object::test<4>()
{
std::ostringstream ostr;
ostr << "{'task_id':u1fd77b79-a8e7-25a5-9454-02a4d948ba1c}\n"
<< "{\n\tname\tObject|\n}\n";
std::string expected = ostr.str();
std::stringstream serialized;
serialized << "'" << LLSDNotationFormatter::escapeString(expected)
<< "'";
LLSD sd;
S32 count = LLSDSerialize::fromNotation(
sd,
serialized,
serialized.str().size());
ensure_equals("parse count", count, 1);
ensure_equals("String streaming", sd.asString(), expected);
}
template<> template<>
void sd_object::test<5>()
{
for(S32 i = 0; i < 100; ++i)
{
// gen up a starting point
typedef std::vector<U8> buf_t;
buf_t source;
srand(666 + i); /* Flawfinder: ignore */
S32 size = rand() % 1000 + 10;
std::generate_n(
std::back_insert_iterator<buf_t>(source),
size,
rand);
std::stringstream str;
str << "b(" << size << ")\"";
str.write((const char*)&source[0], size);
str << "\"";
LLSD sd;
S32 count = LLSDSerialize::fromNotation(sd, str, str.str().size());
ensure_equals("binary parse", count, 1);
buf_t actual = sd.asBinary();
ensure_equals("binary size", actual.size(), (size_t)size);
ensure("binary data", (0 == memcmp(&source[0], &actual[0], size)));
}
}
template<> template<>
void sd_object::test<6>()
{
std::string expected("'{\"task_id\":u1fd77b79-a8e7-25a5-9454-02a4d948ba1c}'\t\n\t\t");
std::stringstream str;
str << "s(" << expected.size() << ")'";
str.write(expected.c_str(), expected.size());
str << "'";
LLSD sd;
S32 count = LLSDSerialize::fromNotation(sd, str, str.str().size());
ensure_equals("parse count", count, 1);
std::string actual = sd.asString();
ensure_equals("string sizes", actual.size(), expected.size());
ensure_equals("string content", actual, expected);
}
template<> template<>
void sd_object::test<7>()
{
std::string msg("come on in");
std::stringstream stream;
stream << "{'connect':1, 'message':'" << msg << "',"
<< " 'position':[r45.65,r100.1,r25.5],"
<< " 'look_at':[r0,r1,r0],"
<< " 'agent_access':'PG'}";
LLSD sd;
S32 count = LLSDSerialize::fromNotation(
sd,
stream,
stream.str().size());
ensure_equals("parse count", count, 12);
ensure_equals("bool value", sd["connect"].asBoolean(), true);
ensure_equals("message value", sd["message"].asString(), msg);
ensure_equals("pos x", sd["position"][0].asReal(), 45.65);
ensure_equals("pos y", sd["position"][1].asReal(), 100.1);
ensure_equals("pos z", sd["position"][2].asReal(), 25.5);
ensure_equals("look x", sd["look_at"][0].asReal(), 0.0);
ensure_equals("look y", sd["look_at"][1].asReal(), 1.0);
ensure_equals("look z", sd["look_at"][2].asReal(), 0.0);
}
template<> template<>
void sd_object::test<8>()
{
std::stringstream resp;
resp << "{'label':'short string test', 'singlechar':'a', 'empty':'', 'endoftest':'end' }";
LLSD response;
S32 count = LLSDSerialize::fromNotation(
response,
resp,
resp.str().size());
ensure_equals("parse count", count, 5);
ensure_equals("sd type", response.type(), LLSD::TypeMap);
ensure_equals("map element count", response.size(), 4);
ensure_equals("singlechar", response["singlechar"].asString(), "a");
ensure_equals("empty", response["empty"].asString(), "");
}
template<> template<>
void sd_object::test<9>()
{
std::ostringstream resp;
resp << "{'label':'short binary test', 'singlebinary':b(1)\"A\", 'singlerawstring':s(1)\"A\", 'endoftest':'end' }";
std::string str = resp.str();
LLSD sd;
LLMemoryStream mstr((U8*)str.c_str(), str.size());
S32 count = LLSDSerialize::fromNotation(sd, mstr, str.size());
ensure_equals("parse count", count, 5);
ensure("sd created", sd.isDefined());
ensure_equals("sd type", sd.type(), LLSD::TypeMap);
ensure_equals("map element count", sd.size(), 4);
ensure_equals(
"label",
sd["label"].asString(),
"short binary test");
std::vector<U8> bin = sd["singlebinary"].asBinary();
std::vector<U8> expected;
expected.resize(1);
expected[0] = 'A';
ensure("single binary", (0 == memcmp(&bin[0], &expected[0], 1)));
ensure_equals(
"single string",
sd["singlerawstring"].asString(),
std::string("A"));
ensure_equals("end", sd["endoftest"].asString(), "end");
}
template<> template<>
void sd_object::test<10>()
{
std::string message("parcel '' is naughty.");
std::stringstream str;
str << "{'message':'" << LLSDNotationFormatter::escapeString(message)
<< "'}";
std::string expected_str("{'message':'parcel \\'\\' is naughty.'}");
std::string actual_str = str.str();
ensure_equals("stream contents", actual_str, expected_str);
LLSD sd;
S32 count = LLSDSerialize::fromNotation(sd, str, actual_str.size());
ensure_equals("parse count", count, 2);
ensure("valid parse", sd.isDefined());
std::string actual = sd["message"].asString();
ensure_equals("message contents", actual, message);
}
template<> template<>
void sd_object::test<11>()
{
std::string expected("\"\"\"\"''''''\"");
std::stringstream str;
str << "'" << LLSDNotationFormatter::escapeString(expected) << "'";
LLSD sd;
S32 count = LLSDSerialize::fromNotation(sd, str, str.str().size());
ensure_equals("parse count", count, 1);
ensure_equals("string value", sd.asString(), expected);
}
template<> template<>
void sd_object::test<12>()
{
std::string expected("mytest\\");
std::stringstream str;
str << "'" << LLSDNotationFormatter::escapeString(expected) << "'";
LLSD sd;
S32 count = LLSDSerialize::fromNotation(sd, str, str.str().size());
ensure_equals("parse count", count, 1);
ensure_equals("string value", sd.asString(), expected);
}
template<> template<>
void sd_object::test<13>()
{
for(S32 i = 0; i < 1000; ++i)
{
// gen up a starting point
std::string expected;
srand(1337 + i); /* Flawfinder: ignore */
S32 size = rand() % 30 + 5;
std::generate_n(
std::back_insert_iterator<std::string>(expected),
size,
rand);
std::stringstream str;
str << "'" << LLSDNotationFormatter::escapeString(expected) << "'";
LLSD sd;
S32 count = LLSDSerialize::fromNotation(sd, str, expected.size());
ensure_equals("parse count", count, 1);
std::string actual = sd.asString();
/*
if(actual != expected)
{
llwarns << "iteration " << i << llendl;
std::ostringstream e_str;
std::string::iterator iter = expected.begin();
std::string::iterator end = expected.end();
for(; iter != end; ++iter)
{
e_str << (S32)((U8)(*iter)) << " ";
}
e_str << std::endl;
llsd_serialize_string(e_str, expected);
llwarns << "expected size: " << expected.size() << llendl;
llwarns << "expected: " << e_str.str() << llendl;
std::ostringstream a_str;
iter = actual.begin();
end = actual.end();
for(; iter != end; ++iter)
{
a_str << (S32)((U8)(*iter)) << " ";
}
a_str << std::endl;
llsd_serialize_string(a_str, actual);
llwarns << "actual size: " << actual.size() << llendl;
llwarns << "actual: " << a_str.str() << llendl;
}
*/
ensure_equals("string value", actual, expected);
}
}
template<> template<>
void sd_object::test<14>()
{
//#if LL_WINDOWS && _MSC_VER >= 1400
// skip_fail("Fails on VS2005 due to broken LLSDSerialize::fromNotation() parser.");
//#endif
std::string param = "[{'version':i1},{'data':{'binary_bucket':b(0)\"\"},'from_id':u3c115e51-04f4-523c-9fa6-98aff1034730,'from_name':'Phoenix Linden','id':u004e45e5-5576-277a-fba7-859d6a4cb5c8,'message':'hey','offline':i0,'timestamp':i0,'to_id':u3c5f1bb4-5182-7546-6401-1d329b4ff2f8,'type':i0},{'agent_id':u3c115e51-04f4-523c-9fa6-98aff1034730,'god_level':i0,'limited_to_estate':i1}]";
std::istringstream istr;
istr.str(param);
LLSD param_sd;
LLSDSerialize::fromNotation(param_sd, istr, param.size());
ensure_equals("parsed type", param_sd.type(), LLSD::TypeArray);
LLSD version_sd = param_sd[0];
ensure_equals("version type", version_sd.type(), LLSD::TypeMap);
ensure("has version", version_sd.has("version"));
ensure_equals("version number", version_sd["version"].asInteger(), 1);
LLSD src_sd = param_sd[1];
ensure_equals("src type", src_sd.type(), LLSD::TypeMap);
LLSD dst_sd = param_sd[2];
ensure_equals("dst type", dst_sd.type(), LLSD::TypeMap);
}
template<> template<>
void sd_object::test<15>()
{
std::string val = "[{'failures':!,'successfuls':[u3c115e51-04f4-523c-9fa6-98aff1034730]}]";
std::istringstream istr;
istr.str(val);
LLSD sd;
LLSDSerialize::fromNotation(sd, istr, val.size());
ensure_equals("parsed type", sd.type(), LLSD::TypeArray);
ensure_equals("parsed size", sd.size(), 1);
LLSD failures = sd[0]["failures"];
ensure("no failures.", failures.isUndefined());
LLSD success = sd[0]["successfuls"];
ensure_equals("success type", success.type(), LLSD::TypeArray);
ensure_equals("success size", success.size(), 1);
ensure_equals("success instance type", success[0].type(), LLSD::TypeUUID);
}
template<> template<>
void sd_object::test<16>()
{
std::string val = "[f,t,0,1,{'foo':t,'bar':f}]";
std::istringstream istr;
istr.str(val);
LLSD sd;
LLSDSerialize::fromNotation(sd, istr, val.size());
ensure_equals("parsed type", sd.type(), LLSD::TypeArray);
ensure_equals("parsed size", sd.size(), 5);
ensure_equals("element 0 false", sd[0].asBoolean(), false);
ensure_equals("element 1 true", sd[1].asBoolean(), true);
ensure_equals("element 2 false", sd[2].asBoolean(), false);
ensure_equals("element 3 true", sd[3].asBoolean(), true);
LLSD map = sd[4];
ensure_equals("element 4 type", map.type(), LLSD::TypeMap);
ensure_equals("map foo type", map["foo"].type(), LLSD::TypeBoolean);
ensure_equals("map foo value", map["foo"].asBoolean(), true);
ensure_equals("map bar type", map["bar"].type(), LLSD::TypeBoolean);
ensure_equals("map bar value", map["bar"].asBoolean(), false);
}
/*
template<> template<>
void sd_object::test<16>()
{
}
*/
}
#if 0
'{\'task_id\':u1fd77b79-a8e7-25a5-9454-02a4d948ba1c}\n{\n\tname\tObject|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t00082000\n\t\tcreator_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t00000000-0000-0000-0000-000000000000\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t10284\n\ttotal_crc\t35\n\ttype\t1\n\ttask_valid\t2\n\ttravel_access\t21\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t0\t0\t0\n\toldpos\t0\t0\t0\n\trotation\t4.371139183945160766597837e-08\t1\t4.371139183945160766597837e-08\t0\n\tvelocity\t0\t0\t0\n\tangvel\t0\t0\t0\n\tscale\t0.2816932\t0.2816932\t0.2816932\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t80\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t16\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\tscale_x\t1\n\t\t\tscale_y\t1\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t1\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t6\n\t{\n\t\timageid\t89556747-24cb-43ed-920b-47caed15465f\n\t\tcolors\t1 1 1 1\n\t\tscales\t0.56\n\t\tscalet\t0.56\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\t89556747-24cb-43ed-920b-47caed15465f\n\t\tcolors\t1 1 1 1\n\t\tscales\t0.56\n\t\tscalet\t0.56\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\t89556747-24cb-43ed-920b-47caed15465f\n\t\tcolors\t1 1 1 1\n\t\tscales\t0.56\n\t\tscalet\t0.56\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\t89556747-24cb-43ed-920b-47caed15465f\n\t\tcolors\t1 1 1 1\n\t\tscales\t0.56\n\t\tscalet\t0.56\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\t89556747-24cb-43ed-920b-47caed15465f\n\t\tcolors\t1 1 1 1\n\t\tscales\t0.56\n\t\tscalet\t0.56\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\t89556747-24cb-43ed-920b-47caed15465f\n\t\tcolors\t1 1 1 1\n\t\tscales\t0.56\n\t\tscalet\t0.56\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t1132625972249870\n\tbirthtime\t1132625953120694\n\treztime\t1132625953120694\n\tparceltime\t1132625953120694\n\ttax_rate\t1.01615\n\tnamevalue\tAttachmentOrientation VEC3 RW DS -3.141593, 0.000000, -3.141593\n\tnamevalue\tAttachmentOffset VEC3 RW DS 0.000000, 0.000000, 0.000000\n\tnamevalue\tAttachPt U32 RW S 5\n\tnamevalue\tAttachItemID STRING RW SV 1f9975c0-2951-1b93-dd83-46e2b932fcc8\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\torig_asset_id\t52019cdd-b464-ba19-e66d-3da751fef9da\n\torig_item_id\t1f9975c0-2951-1b93-dd83-46e2b932fcc8\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n'
#endif
namespace tut
{
struct mem_data
{
};
typedef test_group<mem_data> mem_test;
typedef mem_test::object mem_object;
tut::mem_test mem_stream("memory_stream");
template<> template<>
void mem_object::test<1>()
{
const char HELLO_WORLD[] = "hello world";
LLMemoryStream mem((U8*)&HELLO_WORLD[0], strlen(HELLO_WORLD)); /* Flawfinder: ignore */
std::string hello;
std::string world;
mem >> hello >> world;
ensure_equals("first word", hello, std::string("hello"));
ensure_equals("second word", world, std::string("world"));
}
}
namespace tut
{
struct U64_data
{
};
typedef test_group<U64_data> U64_test;
typedef U64_test::object U64_object;
tut::U64_test U64_testcase("U64_conversion");
// U64_to_str
template<> template<>
void U64_object::test<1>()
{
U64 val;
std::string val_str;
char result[256];
std::string result_str;
val = U64L(18446744073709551610); // slightly less than MAX_U64
val_str = "18446744073709551610";
U64_to_str(val, result, sizeof(result));
result_str = (const char*) result;
ensure_equals("U64_to_str converted 1.1", val_str, result_str);
val = 0;
val_str = "0";
U64_to_str(val, result, sizeof(result));
result_str = (const char*) result;
ensure_equals("U64_to_str converted 1.2", val_str, result_str);
val = U64L(18446744073709551615); // 0xFFFFFFFFFFFFFFFF
val_str = "18446744073709551615";
U64_to_str(val, result, sizeof(result));
result_str = (const char*) result;
ensure_equals("U64_to_str converted 1.3", val_str, result_str);
// overflow - will result in warning at compile time
val = U64L(18446744073709551615) + 1; // overflow 0xFFFFFFFFFFFFFFFF + 1 == 0
val_str = "0";
U64_to_str(val, result, sizeof(result));
result_str = (const char*) result;
ensure_equals("U64_to_str converted 1.4", val_str, result_str);
val = U64L(-1); // 0xFFFFFFFFFFFFFFFF == 18446744073709551615
val_str = "18446744073709551615";
U64_to_str(val, result, sizeof(result));
result_str = (const char*) result;
ensure_equals("U64_to_str converted 1.5", val_str, result_str);
val = U64L(10000000000000000000); // testing preserving of 0s
val_str = "10000000000000000000";
U64_to_str(val, result, sizeof(result));
result_str = (const char*) result;
ensure_equals("U64_to_str converted 1.6", val_str, result_str);
val = 1; // testing no leading 0s
val_str = "1";
U64_to_str(val, result, sizeof(result));
result_str = (const char*) result;
ensure_equals("U64_to_str converted 1.7", val_str, result_str);
val = U64L(18446744073709551615); // testing exact sized buffer for result
val_str = "18446744073709551615";
memset(result, 'A', sizeof(result)); // initialize buffer with all 'A'
U64_to_str(val, result, sizeof("18446744073709551615")); //pass in the exact size
result_str = (const char*) result;
ensure_equals("U64_to_str converted 1.8", val_str, result_str);
val = U64L(18446744073709551615); // testing smaller sized buffer for result
val_str = "1844";
memset(result, 'A', sizeof(result)); // initialize buffer with all 'A'
U64_to_str(val, result, 5); //pass in a size of 5. should only copy first 4 integers and add a null terminator
result_str = (const char*) result;
ensure_equals("U64_to_str converted 1.9", val_str, result_str);
}
// str_to_U64
template<> template<>
void U64_object::test<2>()
{
U64 val;
U64 result;
val = U64L(18446744073709551610); // slightly less than MAX_U64
result = str_to_U64("18446744073709551610");
ensure_equals("str_to_U64 converted 2.1", val, result);
val = U64L(0); // empty string
result = str_to_U64(LLStringUtil::null);
ensure_equals("str_to_U64 converted 2.2", val, result);
val = U64L(0); // 0
result = str_to_U64("0");
ensure_equals("str_to_U64 converted 2.3", val, result);
val = U64L(18446744073709551615); // 0xFFFFFFFFFFFFFFFF
result = str_to_U64("18446744073709551615");
ensure_equals("str_to_U64 converted 2.4", val, result);
// overflow - will result in warning at compile time
val = U64L(18446744073709551615) + 1; // overflow 0xFFFFFFFFFFFFFFFF + 1 == 0
result = str_to_U64("18446744073709551616");
ensure_equals("str_to_U64 converted 2.5", val, result);
val = U64L(1234); // process till first non-integral character
result = str_to_U64("1234A5678");
ensure_equals("str_to_U64 converted 2.6", val, result);
val = U64L(5678); // skip all non-integral characters
result = str_to_U64("ABCD5678");
ensure_equals("str_to_U64 converted 2.7", val, result);
// should it skip negative sign and process
// rest of string or return 0
val = U64L(1234); // skip initial negative sign
result = str_to_U64("-1234");
ensure_equals("str_to_U64 converted 2.8", val, result);
val = U64L(5678); // stop at negative sign in the middle
result = str_to_U64("5678-1234");
ensure_equals("str_to_U64 converted 2.9", val, result);
val = U64L(0); // no integers
result = str_to_U64("AaCD");
ensure_equals("str_to_U64 converted 2.10", val, result);
}
// U64_to_F64
template<> template<>
void U64_object::test<3>()
{
F64 val;
F64 result;
result = 18446744073709551610.0;
val = U64_to_F64(U64L(18446744073709551610));
ensure_equals("U64_to_F64 converted 3.1", val, result);
result = 18446744073709551615.0; // 0xFFFFFFFFFFFFFFFF
val = U64_to_F64(U64L(18446744073709551615));
ensure_equals("U64_to_F64 converted 3.2", val, result);
result = 0.0; // overflow 0xFFFFFFFFFFFFFFFF + 1 == 0
// overflow - will result in warning at compile time
val = U64_to_F64(U64L(18446744073709551615)+1);
ensure_equals("U64_to_F64 converted 3.3", val, result);
result = 0.0; // 0
val = U64_to_F64(U64L(0));
ensure_equals("U64_to_F64 converted 3.4", val, result);
result = 1.0; // odd
val = U64_to_F64(U64L(1));
ensure_equals("U64_to_F64 converted 3.5", val, result);
result = 2.0; // even
val = U64_to_F64(U64L(2));
ensure_equals("U64_to_F64 converted 3.6", val, result);
result = U64L(0x7FFFFFFFFFFFFFFF) * 1.0L; // 0x7FFFFFFFFFFFFFFF
val = U64_to_F64(U64L(0x7FFFFFFFFFFFFFFF));
ensure_equals("U64_to_F64 converted 3.7", val, result);
}
// llstrtou64
// seems to be deprecated - could not find it being used
// anywhere in the tarball - skipping unit tests for now
}
namespace tut
{
struct hash_data
{
};
typedef test_group<hash_data> hash_test;
typedef hash_test::object hash_object;
tut::hash_test hash_tester("hash_test");
template<> template<>
void hash_object::test<1>()
{
const char * str1 = "test string one";
const char * same_as_str1 = "test string one";
size_t hash1 = llhash(str1);
size_t same_as_hash1 = llhash(same_as_str1);
ensure("Hashes from identical strings should be equal", hash1 == same_as_hash1);
char str[100];
strcpy( str, "Another test" );
size_t hash2 = llhash(str);
strcpy( str, "Different string, same pointer" );
size_t hash3 = llhash(str);
ensure("Hashes from same pointer but different string should not be equal", hash2 != hash3);
}
}

View File

@ -0,0 +1,83 @@
/**
* @file llbase64_tut.cpp
* @author James Cook
* @date 2007-02-04
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include <string>
#include "linden_common.h"
#include "../llbase64.h"
#include "../lluuid.h"
#include "../test/lltut.h"
namespace tut
{
struct base64_data
{
};
typedef test_group<base64_data> base64_test;
typedef base64_test::object base64_object;
tut::base64_test base64("base64");
template<> template<>
void base64_object::test<1>()
{
std::string result;
result = LLBase64::encode(NULL, 0);
ensure("encode nothing", (result == "") );
LLUUID nothing;
result = LLBase64::encode(&nothing.mData[0], UUID_BYTES);
ensure("encode blank uuid",
(result == "AAAAAAAAAAAAAAAAAAAAAA==") );
LLUUID id("526a1e07-a19d-baed-84c4-ff08a488d15e");
result = LLBase64::encode(&id.mData[0], UUID_BYTES);
ensure("encode random uuid",
(result == "UmoeB6Gduu2ExP8IpIjRXg==") );
}
template<> template<>
void base64_object::test<2>()
{
std::string result;
U8 blob[40] = { 115, 223, 172, 255, 140, 70, 49, 125, 236, 155, 45, 199, 101, 17, 164, 131, 230, 19, 80, 64, 112, 53, 135, 98, 237, 12, 26, 72, 126, 14, 145, 143, 118, 196, 11, 177, 132, 169, 195, 134 };
result = LLBase64::encode(&blob[0], 40);
ensure("encode 40 bytes",
(result == "c9+s/4xGMX3smy3HZRGkg+YTUEBwNYdi7QwaSH4OkY92xAuxhKnDhg==") );
}
}

View File

@ -0,0 +1,219 @@
/**
* @file lldate_tut.cpp
* @author Adroit
* @date 2007-02
* @brief LLDate test cases.
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "../llstring.h"
#include "../lldate.h"
#include "../test/lltut.h"
#define VALID_DATE "2003-04-30T04:00:00Z"
#define VALID_DATE_LEAP "2004-02-29T04:00:00Z"
#define VALID_DATE_HOUR_BOUNDARY "2003-04-30T23:59:59Z"
#define VALID_DATE_FRACTIONAL_SECS "2007-09-26T20:31:33.70Z"
// invalid format
#define INVALID_DATE_MISSING_YEAR "-04-30T22:59:59Z"
#define INVALID_DATE_MISSING_MONTH "1900-0430T22:59:59Z"
#define INVALID_DATE_MISSING_DATE "1900-0430-T22:59:59Z"
#define INVALID_DATE_MISSING_T "1900-04-30-22:59:59Z"
#define INVALID_DATE_MISSING_HOUR "1900-04-30T:59:59Z"
#define INVALID_DATE_MISSING_MIN "1900-04-30T01::59Z"
#define INVALID_DATE_MISSING_SEC "1900-04-30T01:59Z"
#define INVALID_DATE_MISSING_Z "1900-04-30T01:59:23"
#define INVALID_DATE_EMPTY ""
// invalid values
// apr 1.1.1 seems to not care about constraining the date to valid
// dates. Put these back when the parser checks.
#define LL_DATE_PARSER_CHECKS_BOUNDARY 0
//#define INVALID_DATE_24HOUR_BOUNDARY "2003-04-30T24:00:00Z"
//#define INVALID_DATE_LEAP "2003-04-29T04:00:00Z"
//#define INVALID_DATE_HOUR "2003-04-30T24:59:59Z"
//#define INVALID_DATE_MIN "2003-04-30T22:69:59Z"
//#define INVALID_DATE_SEC "2003-04-30T22:59:69Z"
//#define INVALID_DATE_YEAR "0-04-30T22:59:59Z"
//#define INVALID_DATE_MONTH "2003-13-30T22:59:59Z"
//#define INVALID_DATE_DAY "2003-04-35T22:59:59Z"
namespace tut
{
struct date_test
{
};
typedef test_group<date_test> date_test_t;
typedef date_test_t::object date_test_object_t;
tut::date_test_t tut_date_test("date_test");
/* format validation */
template<> template<>
void date_test_object_t::test<1>()
{
LLDate date(VALID_DATE);
std::string expected_string;
bool result;
expected_string = VALID_DATE;
ensure_equals("Valid Date failed" , expected_string, date.asString());
result = date.fromString(VALID_DATE_LEAP);
expected_string = VALID_DATE_LEAP;
ensure_equals("VALID_DATE_LEAP failed" , expected_string, date.asString());
result = date.fromString(VALID_DATE_HOUR_BOUNDARY);
expected_string = VALID_DATE_HOUR_BOUNDARY;
ensure_equals("VALID_DATE_HOUR_BOUNDARY failed" , expected_string, date.asString());
result = date.fromString(VALID_DATE_FRACTIONAL_SECS);
expected_string = VALID_DATE_FRACTIONAL_SECS;
ensure_equals("VALID_DATE_FRACTIONAL_SECS failed" , expected_string, date.asString());
result = date.fromString(INVALID_DATE_MISSING_YEAR);
ensure_equals("INVALID_DATE_MISSING_YEAR should have failed" , result, false);
result = date.fromString(INVALID_DATE_MISSING_MONTH);
ensure_equals("INVALID_DATE_MISSING_MONTH should have failed" , result, false);
result = date.fromString(INVALID_DATE_MISSING_DATE);
ensure_equals("INVALID_DATE_MISSING_DATE should have failed" , result, false);
result = date.fromString(INVALID_DATE_MISSING_T);
ensure_equals("INVALID_DATE_MISSING_T should have failed" , result, false);
result = date.fromString(INVALID_DATE_MISSING_HOUR);
ensure_equals("INVALID_DATE_MISSING_HOUR should have failed" , result, false);
result = date.fromString(INVALID_DATE_MISSING_MIN);
ensure_equals("INVALID_DATE_MISSING_MIN should have failed" , result, false);
result = date.fromString(INVALID_DATE_MISSING_SEC);
ensure_equals("INVALID_DATE_MISSING_SEC should have failed" , result, false);
result = date.fromString(INVALID_DATE_MISSING_Z);
ensure_equals("INVALID_DATE_MISSING_Z should have failed" , result, false);
result = date.fromString(INVALID_DATE_EMPTY);
ensure_equals("INVALID_DATE_EMPTY should have failed" , result, false);
}
/* Invalid Value Handling */
template<> template<>
void date_test_object_t::test<2>()
{
#if LL_DATE_PARSER_CHECKS_BOUNDARY
LLDate date;
std::string expected_string;
bool result;
result = date.fromString(INVALID_DATE_24HOUR_BOUNDARY);
ensure_equals("INVALID_DATE_24HOUR_BOUNDARY should have failed" , result, false);
ensure_equals("INVALID_DATE_24HOUR_BOUNDARY date still set to old value on failure!" , date.secondsSinceEpoch(), 0);
result = date.fromString(INVALID_DATE_LEAP);
ensure_equals("INVALID_DATE_LEAP should have failed" , result, false);
result = date.fromString(INVALID_DATE_HOUR);
ensure_equals("INVALID_DATE_HOUR should have failed" , result, false);
result = date.fromString(INVALID_DATE_MIN);
ensure_equals("INVALID_DATE_MIN should have failed" , result, false);
result = date.fromString(INVALID_DATE_SEC);
ensure_equals("INVALID_DATE_SEC should have failed" , result, false);
result = date.fromString(INVALID_DATE_YEAR);
ensure_equals("INVALID_DATE_YEAR should have failed" , result, false);
result = date.fromString(INVALID_DATE_MONTH);
ensure_equals("INVALID_DATE_MONTH should have failed" , result, false);
result = date.fromString(INVALID_DATE_DAY);
ensure_equals("INVALID_DATE_DAY should have failed" , result, false);
#endif
}
/* API checks */
template<> template<>
void date_test_object_t::test<3>()
{
LLDate date;
std::istringstream stream(VALID_DATE);
std::string expected_string = VALID_DATE;
date.fromStream(stream);
ensure_equals("fromStream failed", date.asString(), expected_string);
}
template<> template<>
void date_test_object_t::test<4>()
{
LLDate date1(VALID_DATE);
LLDate date2(date1);
ensure_equals("LLDate(const LLDate& date) constructor failed", date1.asString(), date2.asString());
}
template<> template<>
void date_test_object_t::test<5>()
{
LLDate date1(VALID_DATE);
LLDate date2(date1.secondsSinceEpoch());
ensure_equals("secondsSinceEpoch not equal",date1.secondsSinceEpoch(), date2.secondsSinceEpoch());
ensure_equals("LLDate created using secondsSinceEpoch not equal", date1.asString(), date2.asString());
}
template<> template<>
void date_test_object_t::test<6>()
{
LLDate date(VALID_DATE);
std::ostringstream stream;
stream << date;
std::string expected_str = VALID_DATE;
ensure_equals("ostringstream failed", expected_str, stream.str());
}
template<> template<>
void date_test_object_t::test<7>()
{
LLDate date;
std::istringstream stream(VALID_DATE);
stream >> date;
std::string expected_str = VALID_DATE;
std::ostringstream out_stream;
out_stream << date;
ensure_equals("<< failed", date.asString(),expected_str);
ensure_equals("<< to >> failed", stream.str(),out_stream.str());
}
}

View File

@ -0,0 +1,768 @@
/**
* @file llerror_tut.cpp
* @date December 2006
* @brief error unit tests
*
* $LicenseInfo:firstyear=2006&license=viewergpl$
*
* Copyright (c) 2006-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include <vector>
#include "linden_common.h"
#include "../llerror.h"
#include "../llerrorcontrol.h"
#include "../llsd.h"
#include "../test/lltut.h"
namespace
{
void test_that_error_h_includes_enough_things_to_compile_a_message()
{
llinfos << "!" << llendl;
}
}
namespace
{
static bool fatalWasCalled;
void fatalCall(const std::string&) { fatalWasCalled = true; }
class TestRecorder : public LLError::Recorder
{
public:
TestRecorder() : mWantsTime(false) { }
~TestRecorder() { LLError::removeRecorder(this); }
void recordMessage(LLError::ELevel level,
const std::string& message)
{
mMessages.push_back(message);
}
int countMessages() { return (int) mMessages.size(); }
void clearMessages() { mMessages.clear(); }
void setWantsTime(bool t) { mWantsTime = t; }
bool wantsTime() { return mWantsTime; }
std::string message(int n)
{
std::ostringstream test_name;
test_name << "testing message " << n << ", not enough messages";
tut::ensure(test_name.str(), n < countMessages());
return mMessages[n];
}
private:
typedef std::vector<std::string> MessageVector;
MessageVector mMessages;
bool mWantsTime;
};
}
namespace tut
{
struct ErrorTestData
{
TestRecorder mRecorder;
LLError::Settings* mPriorErrorSettings;
ErrorTestData()
{
fatalWasCalled = false;
mPriorErrorSettings = LLError::saveAndResetSettings();
LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
LLError::setFatalFunction(fatalCall);
LLError::addRecorder(&mRecorder);
}
~ErrorTestData()
{
LLError::removeRecorder(&mRecorder);
LLError::restoreSettings(mPriorErrorSettings);
}
void ensure_message_count(int expectedCount)
{
ensure_equals("message count", mRecorder.countMessages(), expectedCount);
}
void ensure_message_contains(int n, const std::string& expectedText)
{
std::ostringstream test_name;
test_name << "testing message " << n;
ensure_contains(test_name.str(), mRecorder.message(n), expectedText);
}
void ensure_message_does_not_contain(int n, const std::string& expectedText)
{
std::ostringstream test_name;
test_name << "testing message " << n;
ensure_does_not_contain(test_name.str(), mRecorder.message(n), expectedText);
}
};
typedef test_group<ErrorTestData> ErrorTestGroup;
typedef ErrorTestGroup::object ErrorTestObject;
ErrorTestGroup errorTestGroup("error");
template<> template<>
void ErrorTestObject::test<1>()
// basic test of output
{
llinfos << "test" << llendl;
llinfos << "bob" << llendl;
ensure_message_contains(0, "test");
ensure_message_contains(1, "bob");
}
}
namespace
{
void writeSome()
{
lldebugs << "one" << llendl;
llinfos << "two" << llendl;
llwarns << "three" << llendl;
llerrs << "four" << llendl;
// fatal messages write out and addtional "error" message
}
};
namespace tut
{
template<> template<>
void ErrorTestObject::test<2>()
// messages are filtered based on default level
{
LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
writeSome();
ensure_message_contains(0, "one");
ensure_message_contains(1, "two");
ensure_message_contains(2, "three");
ensure_message_contains(3, "error");
ensure_message_contains(4, "four");
ensure_message_count(5);
LLError::setDefaultLevel(LLError::LEVEL_INFO);
writeSome();
ensure_message_contains(5, "two");
ensure_message_contains(6, "three");
ensure_message_contains(7, "error");
ensure_message_contains(8, "four");
ensure_message_count(9);
LLError::setDefaultLevel(LLError::LEVEL_WARN);
writeSome();
ensure_message_contains(9, "three");
ensure_message_contains(10, "error");
ensure_message_contains(11, "four");
ensure_message_count(12);
LLError::setDefaultLevel(LLError::LEVEL_ERROR);
writeSome();
ensure_message_contains(12, "error");
ensure_message_contains(13, "four");
ensure_message_count(14);
LLError::setDefaultLevel(LLError::LEVEL_NONE);
writeSome();
ensure_message_count(14);
}
template<> template<>
void ErrorTestObject::test<3>()
// error type string in output
{
writeSome();
ensure_message_contains(0, "DEBUG: ");
ensure_message_contains(1, "INFO: ");
ensure_message_contains(2, "WARNING: ");
ensure_message_does_not_contain(3, "ERROR");
ensure_message_contains(4, "ERROR: ");
ensure_message_count(5);
}
template<> template<>
void ErrorTestObject::test<4>()
// file abbreviation
{
std::string thisFile = __FILE__;
std::string abbreviateFile = LLError::abbreviateFile(thisFile);
ensure_ends_with("file name abbreviation",
abbreviateFile,
"llcommon/tests/llerror_test.cpp"
);
ensure_does_not_contain("file name abbreviation",
abbreviateFile, "indra");
std::string someFile =
#if LL_WINDOWS
"C:/amy/bob/cam.cpp"
#else
"/amy/bob/cam.cpp"
#endif
;
std::string someAbbreviation = LLError::abbreviateFile(someFile);
ensure_equals("non-indra file abbreviation",
someAbbreviation, someFile);
}
}
namespace
{
std::string locationString(int line)
{
std::ostringstream location;
location << LLError::abbreviateFile(__FILE__)
<< "(" << line << ") : ";
return location.str();
}
std::string writeReturningLocation()
{
llinfos << "apple" << llendl; int this_line = __LINE__;
return locationString(this_line);
}
std::string writeReturningLocationAndFunction()
{
llinfos << "apple" << llendl; int this_line = __LINE__;
return locationString(this_line) + __FUNCTION__;
}
std::string errorReturningLocation()
{
llerrs << "die" << llendl; int this_line = __LINE__;
return locationString(this_line);
}
}
namespace tut
{
template<> template<>
void ErrorTestObject::test<5>()
// file and line information in log messages
{
std::string location = writeReturningLocation();
// expecting default to not print location information
LLError::setPrintLocation(true);
writeReturningLocation();
LLError::setPrintLocation(false);
writeReturningLocation();
ensure_message_does_not_contain(0, location);
ensure_message_contains(1, location);
ensure_message_does_not_contain(2, location);
}
}
/* The following helper functions and class members all log a simple message
from some particular function scope. Each function takes a bool argument
that indicates if it should log its own name or not (in the manner that
existing log messages often do.) The functions all return their C++
name so that test can be substantial mechanized.
*/
std::string logFromGlobal(bool id)
{
llinfos << (id ? "logFromGlobal: " : "") << "hi" << llendl;
return "logFromGlobal";
}
static std::string logFromStatic(bool id)
{
llinfos << (id ? "logFromStatic: " : "") << "hi" << llendl;
return "logFromStatic";
}
namespace
{
std::string logFromAnon(bool id)
{
llinfos << (id ? "logFromAnon: " : "") << "hi" << llendl;
return "logFromAnon";
}
}
namespace Foo {
std::string logFromNamespace(bool id)
{
llinfos << (id ? "Foo::logFromNamespace: " : "") << "hi" << llendl;
//return "Foo::logFromNamespace";
// there is no standard way to get the namespace name, hence
// we won't be testing for it
return "logFromNamespace";
}
}
namespace
{
class ClassWithNoLogType {
public:
std::string logFromMember(bool id)
{
llinfos << (id ? "ClassWithNoLogType::logFromMember: " : "") << "hi" << llendl;
return "ClassWithNoLogType::logFromMember";
}
static std::string logFromStatic(bool id)
{
llinfos << (id ? "ClassWithNoLogType::logFromStatic: " : "") << "hi" << llendl;
return "ClassWithNoLogType::logFromStatic";
}
};
class ClassWithLogType {
LOG_CLASS(ClassWithLogType);
public:
std::string logFromMember(bool id)
{
llinfos << (id ? "ClassWithLogType::logFromMember: " : "") << "hi" << llendl;
return "ClassWithLogType::logFromMember";
}
static std::string logFromStatic(bool id)
{
llinfos << (id ? "ClassWithLogType::logFromStatic: " : "") << "hi" << llendl;
return "ClassWithLogType::logFromStatic";
}
};
std::string logFromNamespace(bool id) { return Foo::logFromNamespace(id); }
std::string logFromClassWithNoLogTypeMember(bool id) { ClassWithNoLogType c; return c.logFromMember(id); }
std::string logFromClassWithNoLogTypeStatic(bool id) { return ClassWithNoLogType::logFromStatic(id); }
std::string logFromClassWithLogTypeMember(bool id) { ClassWithLogType c; return c.logFromMember(id); }
std::string logFromClassWithLogTypeStatic(bool id) { return ClassWithLogType::logFromStatic(id); }
void ensure_has(const std::string& message,
const std::string& actual, const std::string& expected)
{
std::string::size_type n1 = actual.find(expected);
if (n1 == std::string::npos)
{
std::stringstream ss;
ss << message << ": " << "expected to find a copy of " << expected
<< " in actual " << actual;
throw tut::failure(ss.str().c_str());
}
}
typedef std::string (*LogFromFunction)(bool);
void testLogName(TestRecorder& recorder, LogFromFunction f,
const std::string& class_name = "")
{
recorder.clearMessages();
std::string name = f(false);
f(true);
std::string messageWithoutName = recorder.message(0);
std::string messageWithName = recorder.message(1);
ensure_has(name + " logged without name",
messageWithoutName, name);
ensure_has(name + " logged with name",
messageWithName, name);
if (!class_name.empty())
{
ensure_has(name + "logged without name",
messageWithoutName, class_name);
ensure_has(name + "logged with name",
messageWithName, class_name);
}
}
}
namespace tut
{
template<> template<>
// class/function information in output
void ErrorTestObject::test<6>()
{
testLogName(mRecorder, logFromGlobal);
testLogName(mRecorder, logFromStatic);
testLogName(mRecorder, logFromAnon);
testLogName(mRecorder, logFromNamespace);
//testLogName(mRecorder, logFromClassWithNoLogTypeMember, "ClassWithNoLogType");
//testLogName(mRecorder, logFromClassWithNoLogTypeStatic, "ClassWithNoLogType");
// XXX: figure out what the exepcted response is for these
testLogName(mRecorder, logFromClassWithLogTypeMember, "ClassWithLogType");
testLogName(mRecorder, logFromClassWithLogTypeStatic, "ClassWithLogType");
}
}
namespace
{
std::string innerLogger()
{
llinfos << "inside" << llendl;
return "moo";
}
std::string outerLogger()
{
llinfos << "outside(" << innerLogger() << ")" << llendl;
return "bar";
}
void uberLogger()
{
llinfos << "uber(" << outerLogger() << "," << innerLogger() << ")" << llendl;
}
class LogWhileLogging
{
public:
void print(std::ostream& out) const
{
llinfos << "logging" << llendl;
out << "baz";
}
};
std::ostream& operator<<(std::ostream& out, const LogWhileLogging& l)
{ l.print(out); return out; }
void metaLogger()
{
LogWhileLogging l;
llinfos << "meta(" << l << ")" << llendl;
}
}
namespace tut
{
template<> template<>
// handle nested logging
void ErrorTestObject::test<7>()
{
outerLogger();
ensure_message_contains(0, "inside");
ensure_message_contains(1, "outside(moo)");
ensure_message_count(2);
uberLogger();
ensure_message_contains(2, "inside");
ensure_message_contains(3, "inside");
ensure_message_contains(4, "outside(moo)");
ensure_message_contains(5, "uber(bar,moo)");
ensure_message_count(6);
metaLogger();
ensure_message_contains(6, "logging");
ensure_message_contains(7, "meta(baz)");
ensure_message_count(8);
}
template<> template<>
// special handling of llerrs calls
void ErrorTestObject::test<8>()
{
LLError::setPrintLocation(false);
std::string location = errorReturningLocation();
ensure_message_contains(0, location + "error");
ensure_message_contains(1, "die");
ensure_message_count(2);
ensure("fatal callback called", fatalWasCalled);
}
}
namespace
{
std::string roswell()
{
return "1947-07-08T03:04:05Z";
}
void ufoSighting()
{
llinfos << "ufo" << llendl;
}
}
namespace tut
{
template<> template<>
// time in output (for recorders that need it)
void ErrorTestObject::test<9>()
{
LLError::setTimeFunction(roswell);
mRecorder.setWantsTime(false);
ufoSighting();
ensure_message_contains(0, "ufo");
ensure_message_does_not_contain(0, roswell());
mRecorder.setWantsTime(true);
ufoSighting();
ensure_message_contains(1, "ufo");
ensure_message_contains(1, roswell());
}
template<> template<>
// output order
void ErrorTestObject::test<10>()
{
LLError::setPrintLocation(true);
LLError::setTimeFunction(roswell);
mRecorder.setWantsTime(true);
std::string locationAndFunction = writeReturningLocationAndFunction();
ensure_equals("order is time type location function message",
mRecorder.message(0),
roswell() + " INFO: " + locationAndFunction + ": apple");
}
template<> template<>
// multiple recorders
void ErrorTestObject::test<11>()
{
TestRecorder altRecorder;
LLError::addRecorder(&altRecorder);
llinfos << "boo" << llendl;
ensure_message_contains(0, "boo");
ensure_equals("alt recorder count", altRecorder.countMessages(), 1);
ensure_contains("alt recorder message 0", altRecorder.message(0), "boo");
LLError::setTimeFunction(roswell);
TestRecorder anotherRecorder;
anotherRecorder.setWantsTime(true);
LLError::addRecorder(&anotherRecorder);
llinfos << "baz" << llendl;
std::string when = roswell();
ensure_message_does_not_contain(1, when);
ensure_equals("alt recorder count", altRecorder.countMessages(), 2);
ensure_does_not_contain("alt recorder message 1", altRecorder.message(1), when);
ensure_equals("another recorder count", anotherRecorder.countMessages(), 1);
ensure_contains("another recorder message 0", anotherRecorder.message(0), when);
}
}
class TestAlpha
{
LOG_CLASS(TestAlpha);
public:
static void doDebug() { lldebugs << "add dice" << llendl; }
static void doInfo() { llinfos << "any idea" << llendl; }
static void doWarn() { llwarns << "aim west" << llendl; }
static void doError() { llerrs << "ate eels" << llendl; }
static void doAll() { doDebug(); doInfo(); doWarn(); doError(); }
};
class TestBeta
{
LOG_CLASS(TestBeta);
public:
static void doDebug() { lldebugs << "bed down" << llendl; }
static void doInfo() { llinfos << "buy iron" << llendl; }
static void doWarn() { llwarns << "bad word" << llendl; }
static void doError() { llerrs << "big easy" << llendl; }
static void doAll() { doDebug(); doInfo(); doWarn(); doError(); }
};
namespace tut
{
template<> template<>
// filtering by class
void ErrorTestObject::test<12>()
{
LLError::setDefaultLevel(LLError::LEVEL_WARN);
LLError::setClassLevel("TestBeta", LLError::LEVEL_INFO);
TestAlpha::doAll();
TestBeta::doAll();
ensure_message_contains(0, "aim west");
ensure_message_contains(1, "error");
ensure_message_contains(2, "ate eels");
ensure_message_contains(3, "buy iron");
ensure_message_contains(4, "bad word");
ensure_message_contains(5, "error");
ensure_message_contains(6, "big easy");
ensure_message_count(7);
}
template<> template<>
// filtering by function, and that it will override class filtering
void ErrorTestObject::test<13>()
{
LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
LLError::setClassLevel("TestBeta", LLError::LEVEL_WARN);
LLError::setFunctionLevel("TestBeta::doInfo", LLError::LEVEL_DEBUG);
LLError::setFunctionLevel("TestBeta::doError", LLError::LEVEL_NONE);
TestBeta::doAll();
ensure_message_contains(0, "buy iron");
ensure_message_contains(1, "bad word");
ensure_message_count(2);
}
template<> template<>
// filtering by file
// and that it is overridden by both class and function filtering
void ErrorTestObject::test<14>()
{
LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
LLError::setFileLevel(LLError::abbreviateFile(__FILE__),
LLError::LEVEL_WARN);
LLError::setClassLevel("TestAlpha", LLError::LEVEL_INFO);
LLError::setFunctionLevel("TestAlpha::doError",
LLError::LEVEL_NONE);
LLError::setFunctionLevel("TestBeta::doError",
LLError::LEVEL_NONE);
TestAlpha::doAll();
TestBeta::doAll();
ensure_message_contains(0, "any idea");
ensure_message_contains(1, "aim west");
ensure_message_contains(2, "bad word");
ensure_message_count(3);
}
template<> template<>
// proper cached, efficient lookup of filtering
void ErrorTestObject::test<15>()
{
LLError::setDefaultLevel(LLError::LEVEL_NONE);
TestAlpha::doInfo();
ensure_message_count(0);
ensure_equals("first check", LLError::shouldLogCallCount(), 1);
TestAlpha::doInfo();
ensure_message_count(0);
ensure_equals("second check", LLError::shouldLogCallCount(), 1);
LLError::setClassLevel("TestAlpha", LLError::LEVEL_DEBUG);
TestAlpha::doInfo();
ensure_message_count(1);
ensure_equals("third check", LLError::shouldLogCallCount(), 2);
TestAlpha::doInfo();
ensure_message_count(2);
ensure_equals("fourth check", LLError::shouldLogCallCount(), 2);
LLError::setClassLevel("TestAlpha", LLError::LEVEL_WARN);
TestAlpha::doInfo();
ensure_message_count(2);
ensure_equals("fifth check", LLError::shouldLogCallCount(), 3);
TestAlpha::doInfo();
ensure_message_count(2);
ensure_equals("sixth check", LLError::shouldLogCallCount(), 3);
}
template<> template<>
// configuration from LLSD
void ErrorTestObject::test<16>()
{
std::string this_file = LLError::abbreviateFile(__FILE__);
LLSD config;
config["print-location"] = true;
config["default-level"] = "DEBUG";
LLSD set1;
set1["level"] = "WARN";
set1["files"][0] = this_file;
LLSD set2;
set2["level"] = "INFO";
set2["classes"][0] = "TestAlpha";
LLSD set3;
set3["level"] = "NONE";
set3["functions"][0] = "TestAlpha::doError";
set3["functions"][1] = "TestBeta::doError";
config["settings"][0] = set1;
config["settings"][1] = set2;
config["settings"][2] = set3;
LLError::configure(config);
TestAlpha::doAll();
TestBeta::doAll();
ensure_message_contains(0, "any idea");
ensure_message_contains(0, this_file);
ensure_message_contains(1, "aim west");
ensure_message_contains(2, "bad word");
ensure_message_count(3);
// make sure reconfiguring works
LLSD config2;
config2["default-level"] = "WARN";
LLError::configure(config2);
TestAlpha::doAll();
TestBeta::doAll();
ensure_message_contains(3, "aim west");
ensure_message_does_not_contain(3, this_file);
ensure_message_contains(4, "error");
ensure_message_contains(5, "ate eels");
ensure_message_contains(6, "bad word");
ensure_message_contains(7, "error");
ensure_message_contains(8, "big easy");
ensure_message_count(9);
}
}
/* Tests left:
handling of classes without LOG_CLASS
live update of filtering from file
syslog recorder
file recorder
cerr/stderr recorder
fixed buffer recorder
windows recorder
mutex use when logging (?)
strange careful about to crash handling (?)
*/

View File

@ -0,0 +1,118 @@
/**
* @file lltiming_tut.cpp
* @date 2006-07-23
* @brief Tests the timers.
*
* $LicenseInfo:firstyear=2006&license=viewergpl$
*
* Copyright (c) 2006-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "../llframetimer.h"
#include "../llsd.h"
#include "../test/lltut.h"
namespace tut
{
struct frametimer_test
{
frametimer_test()
{
LLFrameTimer::updateFrameTime();
}
};
typedef test_group<frametimer_test> frametimer_group_t;
typedef frametimer_group_t::object frametimer_object_t;
tut::frametimer_group_t frametimer_instance("frametimer");
template<> template<>
void frametimer_object_t::test<1>()
{
F64 seconds_since_epoch = LLFrameTimer::getTotalSeconds();
LLFrameTimer timer;
timer.setExpiryAt(seconds_since_epoch);
F64 expires_at = timer.expiresAt();
ensure_distance(
"set expiry matches get expiry",
expires_at,
seconds_since_epoch,
0.001);
}
template<> template<>
void frametimer_object_t::test<2>()
{
F64 seconds_since_epoch = LLFrameTimer::getTotalSeconds();
seconds_since_epoch += 10.0;
LLFrameTimer timer;
timer.setExpiryAt(seconds_since_epoch);
F64 expires_at = timer.expiresAt();
ensure_distance(
"set expiry matches get expiry 1",
expires_at,
seconds_since_epoch,
0.001);
seconds_since_epoch += 10.0;
timer.setExpiryAt(seconds_since_epoch);
expires_at = timer.expiresAt();
ensure_distance(
"set expiry matches get expiry 2",
expires_at,
seconds_since_epoch,
0.001);
}
template<> template<>
void frametimer_object_t::test<3>()
{
F64 seconds_since_epoch = LLFrameTimer::getTotalSeconds();
seconds_since_epoch += 2.0;
LLFrameTimer timer;
timer.setExpiryAt(seconds_since_epoch);
ensure("timer not expired on create", !timer.hasExpired());
int ii;
for(ii = 0; ii < 10; ++ii)
{
ms_sleep(150);
LLFrameTimer::updateFrameTime();
}
ensure("timer not expired after a bit", !timer.hasExpired());
for(ii = 0; ii < 10; ++ii)
{
ms_sleep(100);
LLFrameTimer::updateFrameTime();
}
ensure("timer expired", timer.hasExpired());
}
/*
template<> template<>
void frametimer_object_t::test<4>()
{
}
*/
}

View File

@ -0,0 +1,133 @@
/**
* @file llrandom_tut.cpp
* @author Phoenix
* @date 2007-01-25
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "../test/lltut.h"
#include "../llrand.h"
namespace tut
{
struct random
{
};
typedef test_group<random> random_t;
typedef random_t::object random_object_t;
tut::random_t tut_random("random");
template<> template<>
void random_object_t::test<1>()
{
F32 number = 0.0f;
for(S32 ii = 0; ii < 100000; ++ii)
{
number = ll_frand();
ensure("frand >= 0", (number >= 0.0f));
ensure("frand < 1", (number < 1.0f));
}
}
template<> template<>
void random_object_t::test<2>()
{
F64 number = 0.0f;
for(S32 ii = 0; ii < 100000; ++ii)
{
number = ll_drand();
ensure("drand >= 0", (number >= 0.0));
ensure("drand < 1", (number < 1.0));
}
}
template<> template<>
void random_object_t::test<3>()
{
F32 number = 0.0f;
for(S32 ii = 0; ii < 100000; ++ii)
{
number = ll_frand(2.0f) - 1.0f;
ensure("frand >= 0", (number >= -1.0f));
ensure("frand < 1", (number <= 1.0f));
}
}
template<> template<>
void random_object_t::test<4>()
{
F32 number = 0.0f;
for(S32 ii = 0; ii < 100000; ++ii)
{
number = ll_frand(-7.0);
ensure("drand <= 0", (number <= 0.0));
ensure("drand > -7", (number > -7.0));
}
}
template<> template<>
void random_object_t::test<5>()
{
F64 number = 0.0f;
for(S32 ii = 0; ii < 100000; ++ii)
{
number = ll_drand(-2.0);
ensure("drand <= 0", (number <= 0.0));
ensure("drand > -2", (number > -2.0));
}
}
template<> template<>
void random_object_t::test<6>()
{
S32 number = 0;
for(S32 ii = 0; ii < 100000; ++ii)
{
number = ll_rand(100);
ensure("rand >= 0", (number >= 0));
ensure("rand < 100", (number < 100));
}
}
template<> template<>
void random_object_t::test<7>()
{
S32 number = 0;
for(S32 ii = 0; ii < 100000; ++ii)
{
number = ll_rand(-127);
ensure("rand <= 0", (number <= 0));
ensure("rand > -127", (number > -127));
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,750 @@
/**
* @file llstring_test.cpp
* @author Adroit, Steve Linden, Tofu Linden
* @date 2006-12-24
* @brief Test cases of llstring.cpp
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "../test/lltut.h"
#include "../llstring.h"
namespace tut
{
struct string_index
{
};
typedef test_group<string_index> string_index_t;
typedef string_index_t::object string_index_object_t;
tut::string_index_t tut_string_index("string_test");
template<> template<>
void string_index_object_t::test<1>()
{
std::string llstr1;
ensure("Empty std::string", (llstr1.size() == 0) && llstr1.empty());
std::string llstr2("Hello");
ensure("std::string = Hello", (!strcmp(llstr2.c_str(), "Hello")) && (llstr2.size() == 5) && !llstr2.empty());
std::string llstr3(llstr2);
ensure("std::string = std::string(std::string)", (!strcmp(llstr3.c_str(), "Hello")) && (llstr3.size() == 5) && !llstr3.empty());
std::string str("Hello World");
std::string llstr4(str, 6);
ensure("std::string = std::string(s, size_type pos, size_type n = npos)", (!strcmp(llstr4.c_str(), "World")) && (llstr4.size() == 5) && !llstr4.empty());
std::string llstr5(str, str.size());
ensure("std::string = std::string(s, size_type pos, size_type n = npos)", (llstr5.size() == 0) && llstr5.empty());
std::string llstr6(5, 'A');
ensure("std::string = std::string(count, c)", (!strcmp(llstr6.c_str(), "AAAAA")) && (llstr6.size() == 5) && !llstr6.empty());
std::string llstr7("Hello World", 5);
ensure("std::string(s, n)", (!strcmp(llstr7.c_str(), "Hello")) && (llstr7.size() == 5) && !llstr7.empty());
std::string llstr8("Hello World", 6, 5);
ensure("std::string(s, n, count)", (!strcmp(llstr8.c_str(), "World")) && (llstr8.size() == 5) && !llstr8.empty());
std::string llstr9("Hello World", sizeof("Hello World")-1, 5); // go past end
ensure("std::string(s, n, count) goes past end", (llstr9.size() == 0) && llstr9.empty());
}
template<> template<>
void string_index_object_t::test<3>()
{
std::string str("Len=5");
ensure("isValidIndex failed", LLStringUtil::isValidIndex(str, 0) == TRUE &&
LLStringUtil::isValidIndex(str, 5) == TRUE &&
LLStringUtil::isValidIndex(str, 6) == FALSE);
std::string str1;
ensure("isValidIndex failed fo rempty string", LLStringUtil::isValidIndex(str1, 0) == FALSE);
}
template<> template<>
void string_index_object_t::test<4>()
{
std::string str_val(" Testing the extra whitespaces ");
LLStringUtil::trimHead(str_val);
ensure_equals("1: trimHead failed", str_val, "Testing the extra whitespaces ");
std::string str_val1("\n\t\r\n Testing the extra whitespaces ");
LLStringUtil::trimHead(str_val1);
ensure_equals("2: trimHead failed", str_val1, "Testing the extra whitespaces ");
}
template<> template<>
void string_index_object_t::test<5>()
{
std::string str_val(" Testing the extra whitespaces ");
LLStringUtil::trimTail(str_val);
ensure_equals("1: trimTail failed", str_val, " Testing the extra whitespaces");
std::string str_val1("\n Testing the extra whitespaces \n\t\r\n ");
LLStringUtil::trimTail(str_val1);
ensure_equals("2: trimTail failed", str_val1, "\n Testing the extra whitespaces");
}
template<> template<>
void string_index_object_t::test<6>()
{
std::string str_val(" \t \r Testing the extra \r\n whitespaces \n \t ");
LLStringUtil::trim(str_val);
ensure_equals("1: trim failed", str_val, "Testing the extra \r\n whitespaces");
}
template<> template<>
void string_index_object_t::test<7>()
{
std::string str("Second LindenLabs");
LLStringUtil::truncate(str, 6);
ensure_equals("1: truncate", str, "Second");
// further truncate more than the length
LLStringUtil::truncate(str, 0);
ensure_equals("2: truncate", str, "");
}
template<> template<>
void string_index_object_t::test<8>()
{
std::string str_val("SecondLife Source");
LLStringUtil::toUpper(str_val);
ensure_equals("toUpper failed", str_val, "SECONDLIFE SOURCE");
}
template<> template<>
void string_index_object_t::test<9>()
{
std::string str_val("SecondLife Source");
LLStringUtil::toLower(str_val);
ensure_equals("toLower failed", str_val, "secondlife source");
}
template<> template<>
void string_index_object_t::test<10>()
{
std::string str_val("Second");
ensure("1. isHead failed", LLStringUtil::isHead(str_val, "SecondLife Source") == TRUE);
ensure("2. isHead failed", LLStringUtil::isHead(str_val, " SecondLife Source") == FALSE);
std::string str_val2("");
ensure("3. isHead failed", LLStringUtil::isHead(str_val2, "") == FALSE);
}
template<> template<>
void string_index_object_t::test<11>()
{
std::string str_val("Hello.\n\n Lindenlabs. \n This is \na simple test.\n");
std::string orig_str_val(str_val);
LLStringUtil::addCRLF(str_val);
ensure_equals("addCRLF failed", str_val, "Hello.\r\n\r\n Lindenlabs. \r\n This is \r\na simple test.\r\n");
LLStringUtil::removeCRLF(str_val);
ensure_equals("removeCRLF failed", str_val, orig_str_val);
}
template<> template<>
void string_index_object_t::test<12>()
{
std::string str_val("Hello.\n\n\t \t Lindenlabs. \t\t");
std::string orig_str_val(str_val);
LLStringUtil::replaceTabsWithSpaces(str_val, 1);
ensure_equals("replaceTabsWithSpaces failed", str_val, "Hello.\n\n Lindenlabs. ");
LLStringUtil::replaceTabsWithSpaces(orig_str_val, 0);
ensure_equals("replaceTabsWithSpaces failed for 0", orig_str_val, "Hello.\n\n Lindenlabs. ");
str_val = "\t\t\t\t";
LLStringUtil::replaceTabsWithSpaces(str_val, 0);
ensure_equals("replaceTabsWithSpaces failed for all tabs", str_val, "");
}
template<> template<>
void string_index_object_t::test<13>()
{
std::string str_val("Hello.\n\n\t\t\r\nLindenlabsX.");
LLStringUtil::replaceNonstandardASCII(str_val, 'X');
ensure_equals("replaceNonstandardASCII failed", str_val, "Hello.\n\nXXX\nLindenlabsX.");
}
template<> template<>
void string_index_object_t::test<14>()
{
std::string str_val("Hello.\n\t\r\nABCDEFGHIABABAB");
LLStringUtil::replaceChar(str_val, 'A', 'X');
ensure_equals("1: replaceChar failed", str_val, "Hello.\n\t\r\nXBCDEFGHIXBXBXB");
std::string str_val1("Hello.\n\t\r\nABCDEFGHIABABAB");
}
template<> template<>
void string_index_object_t::test<15>()
{
std::string str_val("Hello.\n\r\t");
ensure("containsNonprintable failed", LLStringUtil::containsNonprintable(str_val) == TRUE);
str_val = "ABC ";
ensure("containsNonprintable failed", LLStringUtil::containsNonprintable(str_val) == FALSE);
}
template<> template<>
void string_index_object_t::test<16>()
{
std::string str_val("Hello.\n\r\t Again!");
LLStringUtil::stripNonprintable(str_val);
ensure_equals("stripNonprintable failed", str_val, "Hello. Again!");
str_val = "\r\n\t\t";
LLStringUtil::stripNonprintable(str_val);
ensure_equals("stripNonprintable resulting in empty string failed", str_val, "");
str_val = "";
LLStringUtil::stripNonprintable(str_val);
ensure_equals("stripNonprintable of empty string resulting in empty string failed", str_val, "");
}
template<> template<>
void string_index_object_t::test<17>()
{
BOOL value;
std::string str_val("1");
ensure("convertToBOOL 1 failed", LLStringUtil::convertToBOOL(str_val, value) && value);
str_val = "T";
ensure("convertToBOOL T failed", LLStringUtil::convertToBOOL(str_val, value) && value);
str_val = "t";
ensure("convertToBOOL t failed", LLStringUtil::convertToBOOL(str_val, value) && value);
str_val = "TRUE";
ensure("convertToBOOL TRUE failed", LLStringUtil::convertToBOOL(str_val, value) && value);
str_val = "True";
ensure("convertToBOOL True failed", LLStringUtil::convertToBOOL(str_val, value) && value);
str_val = "true";
ensure("convertToBOOL true failed", LLStringUtil::convertToBOOL(str_val, value) && value);
str_val = "0";
ensure("convertToBOOL 0 failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
str_val = "F";
ensure("convertToBOOL F failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
str_val = "f";
ensure("convertToBOOL f failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
str_val = "FALSE";
ensure("convertToBOOL FASLE failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
str_val = "False";
ensure("convertToBOOL False failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
str_val = "false";
ensure("convertToBOOL false failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
str_val = "Tblah";
ensure("convertToBOOL false failed", !LLStringUtil::convertToBOOL(str_val, value));
}
template<> template<>
void string_index_object_t::test<18>()
{
U8 value;
std::string str_val("255");
ensure("1: convertToU8 failed", LLStringUtil::convertToU8(str_val, value) && value == 255);
str_val = "0";
ensure("2: convertToU8 failed", LLStringUtil::convertToU8(str_val, value) && value == 0);
str_val = "-1";
ensure("3: convertToU8 failed", !LLStringUtil::convertToU8(str_val, value));
str_val = "256"; // bigger than MAX_U8
ensure("4: convertToU8 failed", !LLStringUtil::convertToU8(str_val, value));
}
template<> template<>
void string_index_object_t::test<19>()
{
S8 value;
std::string str_val("127");
ensure("1: convertToS8 failed", LLStringUtil::convertToS8(str_val, value) && value == 127);
str_val = "0";
ensure("2: convertToS8 failed", LLStringUtil::convertToS8(str_val, value) && value == 0);
str_val = "-128";
ensure("3: convertToS8 failed", LLStringUtil::convertToS8(str_val, value) && value == -128);
str_val = "128"; // bigger than MAX_S8
ensure("4: convertToS8 failed", !LLStringUtil::convertToS8(str_val, value));
str_val = "-129";
ensure("5: convertToS8 failed", !LLStringUtil::convertToS8(str_val, value));
}
template<> template<>
void string_index_object_t::test<20>()
{
S16 value;
std::string str_val("32767");
ensure("1: convertToS16 failed", LLStringUtil::convertToS16(str_val, value) && value == 32767);
str_val = "0";
ensure("2: convertToS16 failed", LLStringUtil::convertToS16(str_val, value) && value == 0);
str_val = "-32768";
ensure("3: convertToS16 failed", LLStringUtil::convertToS16(str_val, value) && value == -32768);
str_val = "32768";
ensure("4: convertToS16 failed", !LLStringUtil::convertToS16(str_val, value));
str_val = "-32769";
ensure("5: convertToS16 failed", !LLStringUtil::convertToS16(str_val, value));
}
template<> template<>
void string_index_object_t::test<21>()
{
U16 value;
std::string str_val("65535"); //0xFFFF
ensure("1: convertToU16 failed", LLStringUtil::convertToU16(str_val, value) && value == 65535);
str_val = "0";
ensure("2: convertToU16 failed", LLStringUtil::convertToU16(str_val, value) && value == 0);
str_val = "-1";
ensure("3: convertToU16 failed", !LLStringUtil::convertToU16(str_val, value));
str_val = "65536";
ensure("4: convertToU16 failed", !LLStringUtil::convertToU16(str_val, value));
}
template<> template<>
void string_index_object_t::test<22>()
{
U32 value;
std::string str_val("4294967295"); //0xFFFFFFFF
ensure("1: convertToU32 failed", LLStringUtil::convertToU32(str_val, value) && value == 4294967295UL);
str_val = "0";
ensure("2: convertToU32 failed", LLStringUtil::convertToU32(str_val, value) && value == 0);
str_val = "4294967296";
ensure("3: convertToU32 failed", !LLStringUtil::convertToU32(str_val, value));
}
template<> template<>
void string_index_object_t::test<23>()
{
S32 value;
std::string str_val("2147483647"); //0x7FFFFFFF
ensure("1: convertToS32 failed", LLStringUtil::convertToS32(str_val, value) && value == 2147483647);
str_val = "0";
ensure("2: convertToS32 failed", LLStringUtil::convertToS32(str_val, value) && value == 0);
// Avoid "unary minus operator applied to unsigned type" warning on VC++. JC
S32 min_val = -2147483647 - 1;
str_val = "-2147483648";
ensure("3: convertToS32 failed", LLStringUtil::convertToS32(str_val, value) && value == min_val);
str_val = "2147483648";
ensure("4: convertToS32 failed", !LLStringUtil::convertToS32(str_val, value));
str_val = "-2147483649";
ensure("5: convertToS32 failed", !LLStringUtil::convertToS32(str_val, value));
}
template<> template<>
void string_index_object_t::test<24>()
{
F32 value;
std::string str_val("2147483647"); //0x7FFFFFFF
ensure("1: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == 2147483647);
str_val = "0";
ensure("2: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == 0);
/* Need to find max/min F32 values
str_val = "-2147483648";
ensure("3: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == -2147483648);
str_val = "2147483648";
ensure("4: convertToF32 failed", !LLStringUtil::convertToF32(str_val, value));
str_val = "-2147483649";
ensure("5: convertToF32 failed", !LLStringUtil::convertToF32(str_val, value));
*/
}
template<> template<>
void string_index_object_t::test<25>()
{
F64 value;
std::string str_val("9223372036854775807"); //0x7FFFFFFFFFFFFFFF
ensure("1: convertToF64 failed", LLStringUtil::convertToF64(str_val, value) && value == 9223372036854775807LL);
str_val = "0";
ensure("2: convertToF64 failed", LLStringUtil::convertToF64(str_val, value) && value == 0.0F);
/* Need to find max/min F64 values
str_val = "-2147483648";
ensure("3: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == -2147483648);
str_val = "2147483648";
ensure("4: convertToF32 failed", !LLStringUtil::convertToF32(str_val, value));
str_val = "-2147483649";
ensure("5: convertToF32 failed", !LLStringUtil::convertToF32(str_val, value));
*/
}
template<> template<>
void string_index_object_t::test<26>()
{
const char* str1 = NULL;
const char* str2 = NULL;
ensure("1: compareStrings failed", LLStringUtil::compareStrings(str1, str2) == 0);
str2 = "A";
ensure("2: compareStrings failed", LLStringUtil::compareStrings(str1, str2) > 0);
ensure("3: compareStrings failed", LLStringUtil::compareStrings(str2, str1) < 0);
str1 = "A is smaller than B";
str2 = "B is greater than A";
ensure("4: compareStrings failed", LLStringUtil::compareStrings(str1, str2) < 0);
str2 = "A is smaller than B";
ensure("5: compareStrings failed", LLStringUtil::compareStrings(str1, str2) == 0);
}
template<> template<>
void string_index_object_t::test<27>()
{
const char* str1 = NULL;
const char* str2 = NULL;
ensure("1: compareInsensitive failed", LLStringUtil::compareInsensitive(str1, str2) == 0);
str2 = "A";
ensure("2: compareInsensitive failed", LLStringUtil::compareInsensitive(str1, str2) > 0);
ensure("3: compareInsensitive failed", LLStringUtil::compareInsensitive(str2, str1) < 0);
str1 = "A is equal to a";
str2 = "a is EQUAL to A";
ensure("4: compareInsensitive failed", LLStringUtil::compareInsensitive(str1, str2) == 0);
}
template<> template<>
void string_index_object_t::test<28>()
{
std::string lhs_str("PROgraM12files");
std::string rhs_str("PROgram12Files");
ensure("compareDict 1 failed", LLStringUtil::compareDict(lhs_str, rhs_str) < 0);
ensure("precedesDict 1 failed", LLStringUtil::precedesDict(lhs_str, rhs_str) == TRUE);
lhs_str = "PROgram12Files";
rhs_str = "PROgram12Files";
ensure("compareDict 2 failed", LLStringUtil::compareDict(lhs_str, rhs_str) == 0);
ensure("precedesDict 2 failed", LLStringUtil::precedesDict(lhs_str, rhs_str) == FALSE);
lhs_str = "PROgram12Files";
rhs_str = "PROgRAM12FILES";
ensure("compareDict 3 failed", LLStringUtil::compareDict(lhs_str, rhs_str) > 0);
ensure("precedesDict 3 failed", LLStringUtil::precedesDict(lhs_str, rhs_str) == FALSE);
}
template<> template<>
void string_index_object_t::test<29>()
{
char str1[] = "First String...";
char str2[100];
LLStringUtil::copy(str2, str1, 100);
ensure("LLStringUtil::copy with enough dest length failed", strcmp(str2, str1) == 0);
LLStringUtil::copy(str2, str1, sizeof("First"));
ensure("LLStringUtil::copy with less dest length failed", strcmp(str2, "First") == 0);
}
template<> template<>
void string_index_object_t::test<30>()
{
std::string str1 = "This is the sentence...";
std::string str2 = "This is the ";
std::string str3 = "first ";
std::string str4 = "This is the first sentence...";
std::string str5 = "This is the sentence...first ";
std::string dest;
dest = str1;
LLStringUtil::copyInto(dest, str3, str2.length());
ensure("LLStringUtil::copyInto insert failed", dest == str4);
dest = str1;
LLStringUtil::copyInto(dest, str3, dest.length());
ensure("LLStringUtil::copyInto append failed", dest == str5);
}
template<> template<>
void string_index_object_t::test<31>()
{
std::string stripped;
// Plain US ASCII text, including spaces and punctuation,
// should not be altered.
std::string simple_text = "Hello, world!";
stripped = LLStringFn::strip_invalid_xml(simple_text);
ensure("Simple text passed unchanged", stripped == simple_text);
// Control characters should be removed
// except for 0x09, 0x0a, 0x0d
std::string control_chars;
for (char c = 0x01; c < 0x20; c++)
{
control_chars.push_back(c);
}
std::string allowed_control_chars;
allowed_control_chars.push_back( (char)0x09 );
allowed_control_chars.push_back( (char)0x0a );
allowed_control_chars.push_back( (char)0x0d );
stripped = LLStringFn::strip_invalid_xml(control_chars);
ensure("Only tab, LF, CR control characters allowed",
stripped == allowed_control_chars);
// UTF-8 should be passed intact, including high byte
// characters. Try Francais (with C squiggle cedilla)
std::string french = "Fran";
french.push_back( (char)0xC3 );
french.push_back( (char)0xA7 );
french += "ais";
stripped = LLStringFn::strip_invalid_xml( french );
ensure("UTF-8 high byte text is allowed", french == stripped );
}
template<> template<>
void string_index_object_t::test<32>()
{
// Test LLStringUtil::format() string interpolation
LLStringUtil::format_map_t fmt_map;
std::string s;
int subcount;
fmt_map["[TRICK1]"] = "[A]";
fmt_map["[A]"] = "a";
fmt_map["[B]"] = "b";
fmt_map["[AAA]"] = "aaa";
fmt_map["[BBB]"] = "bbb";
fmt_map["[TRICK2]"] = "[A]";
fmt_map["[EXPLOIT]"] = "!!!!!!!!!!!![EXPLOIT]!!!!!!!!!!!!";
fmt_map["[KEYLONGER]"] = "short";
fmt_map["[KEYSHORTER]"] = "Am I not a long string?";
fmt_map["?"] = "?";
fmt_map["[DELETE]"] = "";
fmt_map["[]"] = "[]"; // doesn't do a substitution, but shouldn't crash either
for (LLStringUtil::format_map_t::const_iterator iter = fmt_map.begin(); iter != fmt_map.end(); ++iter)
{
// Test when source string is entirely one key
std::string s1 = (std::string)iter->first;
std::string s2 = (std::string)iter->second;
subcount = LLStringUtil::format(s1, fmt_map);
ensure_equals("LLStringUtil::format: Raw interpolation result", s1, s2);
if (s1 == "?" || s1 == "[]") // no interp expected
{
ensure_equals("LLStringUtil::format: Raw interpolation result count", 0, subcount);
}
else
{
ensure_equals("LLStringUtil::format: Raw interpolation result count", 1, subcount);
}
}
for (LLStringUtil::format_map_t::const_iterator iter = fmt_map.begin(); iter != fmt_map.end(); ++iter)
{
// Test when source string is one key, duplicated
std::string s1 = (std::string)iter->first;
std::string s2 = (std::string)iter->second;
s = s1 + s1 + s1 + s1;
subcount = LLStringUtil::format(s, fmt_map);
ensure_equals("LLStringUtil::format: Rawx4 interpolation result", s, s2 + s2 + s2 + s2);
if (s1 == "?" || s1 == "[]") // no interp expected
{
ensure_equals("LLStringUtil::format: Rawx4 interpolation result count", 0, subcount);
}
else
{
ensure_equals("LLStringUtil::format: Rawx4 interpolation result count", 4, subcount);
}
}
// Test when source string has no keys
std::string srcs = "!!!!!!!!!!!!!!!!";
s = srcs;
subcount = LLStringUtil::format(s, fmt_map);
ensure_equals("LLStringUtil::format: No key test result", s, srcs);
ensure_equals("LLStringUtil::format: No key test result count", 0, subcount);
// Test when source string has no keys and is empty
std::string srcs3;
s = srcs3;
subcount = LLStringUtil::format(s, fmt_map);
ensure("LLStringUtil::format: No key test3 result", s.empty());
ensure_equals("LLStringUtil::format: No key test3 result count", 0, subcount);
// Test a substitution where a key is substituted with blankness
std::string srcs2 = "[DELETE]";
s = srcs2;
subcount = LLStringUtil::format(s, fmt_map);
ensure("LLStringUtil::format: Delete key test2 result", s.empty());
ensure_equals("LLStringUtil::format: Delete key test2 result count", 1, subcount);
// Test an assorted substitution
std::string srcs4 = "[TRICK1][A][B][AAA][BBB][TRICK2][KEYLONGER][KEYSHORTER]?[DELETE]";
s = srcs4;
subcount = LLStringUtil::format(s, fmt_map);
ensure_equals("LLStringUtil::format: Assorted Test1 result", s, "[A]abaaabbb[A]shortAm I not a long string??");
ensure_equals("LLStringUtil::format: Assorted Test1 result count", 9, subcount);
// Test an assorted substitution
std::string srcs5 = "[DELETE]?[KEYSHORTER][KEYLONGER][TRICK2][BBB][AAA][B][A][TRICK1]";
s = srcs5;
subcount = LLStringUtil::format(s, fmt_map);
ensure_equals("LLStringUtil::format: Assorted Test2 result", s, "?Am I not a long string?short[A]bbbaaaba[A]");
ensure_equals("LLStringUtil::format: Assorted Test2 result count", 9, subcount);
// Test an assorted substitution
std::string srcs8 = "foo[DELETE]bar?";
s = srcs8;
subcount = LLStringUtil::format(s, fmt_map);
ensure_equals("LLStringUtil::format: Assorted Test3 result", s, "foobar?");
ensure_equals("LLStringUtil::format: Assorted Test3 result count", 1, subcount);
}
template<> template<>
void string_index_object_t::test<33>()
{
// Test LLStringUtil::format() string interpolation
LLStringUtil::format_map_t blank_fmt_map;
std::string s;
int subcount;
// Test substituting out of a blank format_map
std::string srcs6 = "12345";
s = srcs6;
subcount = LLStringUtil::format(s, blank_fmt_map);
ensure_equals("LLStringUtil::format: Blankfmt Test1 result", s, "12345");
ensure_equals("LLStringUtil::format: Blankfmt Test1 result count", 0, subcount);
// Test substituting a blank string out of a blank format_map
std::string srcs7;
s = srcs7;
subcount = LLStringUtil::format(s, blank_fmt_map);
ensure("LLStringUtil::format: Blankfmt Test2 result", s.empty());
ensure_equals("LLStringUtil::format: Blankfmt Test2 result count", 0, subcount);
}
template<> template<>
void string_index_object_t::test<34>()
{
// Test that incorrect LLStringUtil::format() use does not explode.
LLStringUtil::format_map_t nasty_fmt_map;
std::string s;
int subcount;
nasty_fmt_map[""] = "never used"; // see, this is nasty.
// Test substituting out of a nasty format_map
std::string srcs6 = "12345";
s = srcs6;
subcount = LLStringUtil::format(s, nasty_fmt_map);
ensure_equals("LLStringUtil::format: Nastyfmt Test1 result", s, "12345");
ensure_equals("LLStringUtil::format: Nastyfmt Test1 result count", 0, subcount);
// Test substituting a blank string out of a nasty format_map
std::string srcs7;
s = srcs7;
subcount = LLStringUtil::format(s, nasty_fmt_map);
ensure("LLStringUtil::format: Nastyfmt Test2 result", s.empty());
ensure_equals("LLStringUtil::format: Nastyfmt Test2 result count", 0, subcount);
}
template<> template<>
void string_index_object_t::test<35>()
{
// Make sure startsWith works
std::string string("anybody in there?");
std::string substr("anybody");
ensure("startsWith works.", LLStringUtil::startsWith(string, substr));
}
template<> template<>
void string_index_object_t::test<36>()
{
// Make sure startsWith correctly fails
std::string string("anybody in there?");
std::string substr("there");
ensure("startsWith fails.", !LLStringUtil::startsWith(string, substr));
}
template<> template<>
void string_index_object_t::test<37>()
{
// startsWith fails on empty strings
std::string value("anybody in there?");
std::string empty;
ensure("empty string.", !LLStringUtil::startsWith(value, empty));
ensure("empty substr.", !LLStringUtil::startsWith(empty, value));
ensure("empty everything.", !LLStringUtil::startsWith(empty, empty));
}
template<> template<>
void string_index_object_t::test<38>()
{
// Make sure endsWith works correctly
std::string string("anybody in there?");
std::string substr("there?");
ensure("endsWith works.", LLStringUtil::endsWith(string, substr));
}
template<> template<>
void string_index_object_t::test<39>()
{
// Make sure endsWith correctly fails
std::string string("anybody in there?");
std::string substr("anybody");
ensure("endsWith fails.", !LLStringUtil::endsWith(string, substr));
substr = "there";
ensure("endsWith fails.", !LLStringUtil::endsWith(string, substr));
substr = "ther?";
ensure("endsWith fails.", !LLStringUtil::endsWith(string, substr));
}
template<> template<>
void string_index_object_t::test<40>()
{
// endsWith fails on empty strings
std::string value("anybody in there?");
std::string empty;
ensure("empty string.", !LLStringUtil::endsWith(value, empty));
ensure("empty substr.", !LLStringUtil::endsWith(empty, value));
ensure("empty everything.", !LLStringUtil::endsWith(empty, empty));
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,370 @@
/**
* @file lluri_tut.cpp
* @brief LLURI unit tests
* @date September 2006
*
* $LicenseInfo:firstyear=2006&license=viewergpl$
*
* Copyright (c) 2006-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "../llsd.h"
#include "../lluri.h"
#include "../test/lltut.h"
namespace tut
{
struct URITestData {
void checkParts(const LLURI& u,
const char* expectedScheme,
const char* expectedOpaque,
const char* expectedAuthority,
const char* expectedPath,
const char* expectedQuery = "")
{
ensure_equals("scheme", u.scheme(), expectedScheme);
ensure_equals("opaque", u.opaque(), expectedOpaque);
ensure_equals("authority", u.authority(), expectedAuthority);
ensure_equals("path", u.path(), expectedPath);
ensure_equals("query", u.query(), expectedQuery);
}
void escapeRoundTrip(const std::string& uri_raw_1)
{
std::string uri_esc_1(LLURI::escape(uri_raw_1));
std::string uri_raw_2(LLURI::unescape(uri_esc_1));
ensure_equals("escape/unescape raw", uri_raw_2, uri_raw_1);
std::string uri_esc_2(LLURI::escape(uri_raw_2));
ensure_equals("escape/unescape escaped", uri_esc_2, uri_esc_1);
}
};
typedef test_group<URITestData> URITestGroup;
typedef URITestGroup::object URITestObject;
URITestGroup uriTestGroup("LLURI");
template<> template<>
void URITestObject::test<1>()
{
LLURI u("http://abc.com/def/ghi?x=37&y=hello");
ensure_equals("scheme", u.scheme(), "http");
ensure_equals("authority", u.authority(), "abc.com");
ensure_equals("path", u.path(), "/def/ghi");
ensure_equals("query", u.query(), "x=37&y=hello");
ensure_equals("host name", u.hostName(), "abc.com");
ensure_equals("host port", u.hostPort(), 80);
LLSD query = u.queryMap();
ensure_equals("query x", query["x"].asInteger(), 37);
ensure_equals("query y", query["y"].asString(), "hello");
query = LLURI::queryMap("x=22.23&y=https://lindenlab.com/");
ensure_equals("query x", query["x"].asReal(), 22.23);
ensure_equals("query y", query["y"].asURI().asString(), "https://lindenlab.com/");
}
template<> template<>
void URITestObject::test<2>()
{
// empty string
checkParts(LLURI(""), "", "", "", "");
}
template<> template<>
void URITestObject::test<3>()
{
// no scheme
checkParts(LLURI("foo"), "", "foo", "", "");
checkParts(LLURI("foo%3A"), "", "foo:", "", "");
}
template<> template<>
void URITestObject::test<4>()
{
// scheme w/o paths
checkParts(LLURI("mailto:zero@ll.com"),
"mailto", "zero@ll.com", "", "");
checkParts(LLURI("silly://abc/def?foo"),
"silly", "//abc/def?foo", "", "");
}
template<> template<>
void URITestObject::test<5>()
{
// authority section
checkParts(LLURI("http:///"),
"http", "///", "", "/");
checkParts(LLURI("http://abc"),
"http", "//abc", "abc", "");
checkParts(LLURI("http://a%2Fb/cd"),
"http", "//a/b/cd", "a/b", "/cd");
checkParts(LLURI("http://host?"),
"http", "//host?", "host", "");
}
template<> template<>
void URITestObject::test<6>()
{
// path section
checkParts(LLURI("http://host/a/b/"),
"http", "//host/a/b/", "host", "/a/b/");
checkParts(LLURI("http://host/a%3Fb/"),
"http", "//host/a?b/", "host", "/a?b/");
checkParts(LLURI("http://host/a:b/"),
"http", "//host/a:b/", "host", "/a:b/");
}
template<> template<>
void URITestObject::test<7>()
{
// query string
checkParts(LLURI("http://host/?"),
"http", "//host/?", "host", "/", "");
checkParts(LLURI("http://host/?x"),
"http", "//host/?x", "host", "/", "x");
checkParts(LLURI("http://host/??"),
"http", "//host/??", "host", "/", "?");
checkParts(LLURI("http://host/?%3F"),
"http", "//host/??", "host", "/", "?");
}
template<> template<>
void URITestObject::test<8>()
{
LLSD path;
path.append("x");
path.append("123");
checkParts(LLURI::buildHTTP("host", path),
"http", "//host/x/123", "host", "/x/123");
LLSD query;
query["123"] = "12";
query["abcd"] = "abc";
checkParts(LLURI::buildHTTP("host", path, query),
"http", "//host/x/123?123=12&abcd=abc",
"host", "/x/123", "123=12&abcd=abc");
}
template<> template<>
void URITestObject::test<9>()
{
// test unescaped path components
LLSD path;
path.append("x@*//*$&^");
path.append("123");
checkParts(LLURI::buildHTTP("host", path),
"http", "//host/x@*//*$&^/123", "host", "/x@*//*$&^/123");
}
template<> template<>
void URITestObject::test<10>()
{
// test unescaped query components
LLSD path;
path.append("x");
path.append("123");
LLSD query;
query["123"] = "?&*#//";
query["**@&?//"] = "abc";
checkParts(LLURI::buildHTTP("host", path, query),
"http", "//host/x/123?**@&?//=abc&123=?&*#//",
"host", "/x/123", "**@&?//=abc&123=?&*#//");
}
template<> template<>
void URITestObject::test<11>()
{
// test unescaped host components
LLSD path;
path.append("x");
path.append("123");
LLSD query;
query["123"] = "12";
query["abcd"] = "abc";
checkParts(LLURI::buildHTTP("hi123*33--}{:portstuffs", path, query),
"http", "//hi123*33--}{:portstuffs/x/123?123=12&abcd=abc",
"hi123*33--}{:portstuffs", "/x/123", "123=12&abcd=abc");
}
template<> template<>
void URITestObject::test<12>()
{
// test funky host_port values that are actually prefixes
checkParts(LLURI::buildHTTP("http://example.com:8080", LLSD()),
"http", "//example.com:8080",
"example.com:8080", "");
checkParts(LLURI::buildHTTP("http://example.com:8080/", LLSD()),
"http", "//example.com:8080/",
"example.com:8080", "/");
checkParts(LLURI::buildHTTP("http://example.com:8080/a/b", LLSD()),
"http", "//example.com:8080/a/b",
"example.com:8080", "/a/b");
}
template<> template<>
void URITestObject::test<13>()
{
const std::string unreserved =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
"0123456789"
"-._~";
// test escape
ensure_equals("escaping", LLURI::escape("abcdefg", "abcdef"), "abcdef%67");
ensure_equals("escaping", LLURI::escape("|/&\\+-_!@", ""), "%7C%2F%26%5C%2B%2D%5F%21%40");
ensure_equals("escaping as query variable",
LLURI::escape("http://10.0.1.4:12032/agent/god/agent-id/map/layer/?resume=http://station3.ll.com:12032/agent/203ad6df-b522-491d-ba48-4e24eb57aeff/send-postcard", unreserved + ":@!$'()*+,="),
"http:%2F%2F10.0.1.4:12032%2Fagent%2Fgod%2Fagent-id%2Fmap%2Flayer%2F%3Fresume=http:%2F%2Fstation3.ll.com:12032%2Fagent%2F203ad6df-b522-491d-ba48-4e24eb57aeff%2Fsend-postcard");
// French cedilla (C with squiggle, like in the word Francais) is UTF-8 C3 A7
#if LL_WINDOWS
#pragma warning(disable: 4309)
#endif
std::string cedilla;
cedilla.push_back( (char)0xC3 );
cedilla.push_back( (char)0xA7 );
ensure_equals("escape UTF8", LLURI::escape( cedilla, unreserved), "%C3%A7");
}
template<> template<>
void URITestObject::test<14>()
{
// make sure escape and unescape of empty strings return empty
// strings.
std::string uri_esc(LLURI::escape(""));
ensure("escape string empty", uri_esc.empty());
std::string uri_raw(LLURI::unescape(""));
ensure("unescape string empty", uri_raw.empty());
}
template<> template<>
void URITestObject::test<15>()
{
// do some round-trip tests
escapeRoundTrip("http://secondlife.com");
escapeRoundTrip("http://secondlife.com/url with spaces");
escapeRoundTrip("http://bad[domain]name.com/");
escapeRoundTrip("ftp://bill.gates@ms/micro$oft.com/c:\\autoexec.bat");
escapeRoundTrip("");
}
template<> template<>
void URITestObject::test<16>()
{
// Test the default escaping
// yes -- this mangles the url. This is expected behavior
std::string simple("http://secondlife.com");
ensure_equals(
"simple http",
LLURI::escape(simple),
"http%3A%2F%2Fsecondlife.com");
ensure_equals(
"needs escape",
LLURI::escape("http://get.secondlife.com/windows viewer"),
"http%3A%2F%2Fget.secondlife.com%2Fwindows%20viewer");
}
template<> template<>
void URITestObject::test<17>()
{
// do some round-trip tests with very long strings.
escapeRoundTrip("Welcome to Second Life.We hope you'll have a richly rewarding experience, filled with creativity, self expression and fun.The goals of the Community Standards are simple: treat each other with respect and without harassment, adhere to local standards as indicated by simulator ratings, and refrain from any hate activity which slurs a real-world individual or real-world community. Behavioral Guidelines - The Big Six");
escapeRoundTrip(
"'asset_data':b(12100){'task_id':ucc706f2d-0b68-68f8-11a4-f1043ff35ca0}\n{\n\tname\tObject|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreator_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444921\n\ttotal_crc\t323\n\ttype\t2\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.368634403\t0.00781063363\t-0.569040775\n\toldpos\t150.117996\t25.8658009\t8.19664001\n\trotation\t-0.06293071806430816650390625\t-0.6995697021484375\t-0.7002241611480712890625\t0.1277817934751510620117188\n\tchildpos\t-0.00499999989\t-0.0359999985\t0.307999998\n\tchildrot\t-0.515492737293243408203125\t-0.46601200103759765625\t0.529055416584014892578125\t0.4870323240756988525390625\n\tscale"
"\t0.074629\t0.289956\t0.01\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t16\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\tscale_x\t1\n\t\t\tscale_y\t1\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t1\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tf"
"aces\t6\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204"
"\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t-1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061088050622956\n\treztime\t1094866329019785\n\tparceltime\t1133568981980596\n\ttax_rate\t1.00084\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tchild\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n{'task_id':u61fa7364-e151-0597-774c-523312dae31b}\n{\n\tname\tObject|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffff"
"ff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreator_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444922\n\ttotal_crc\t324\n\ttype\t2\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.367110789\t0.00780026987\t-0.566269755\n\toldpos\t150.115005\t25.8479004\t8.18669987\n\trotation\t0.47332942485809326171875\t-0.380102097988128662109375\t-0.5734078884124755859375\t0.550168216228485107421875\n\tchildpos\t-0.00499999989\t-0.0370000005\t0.305000007\n\tchildrot\t-0.736649334430694580078125\t-0.03042060509324073791503906\t-0.02784589119255542755126953\t0.67501628398895263671875\n\tscale\t0.074629\t0.289956\t0.01\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t"
"0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t16\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\tscale_x\t1\n\t\t\tscale_y\t1\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t1\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t6\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t"
"\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t"
"\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t-1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061087839248891\n\treztime\t1094866329020800\n\tparceltime\t1133568981981983\n\ttax_rate\t1.00084\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tchild\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n{'task_id':ub8d68643-7dd8-57af-0d24-8790032aed0c}\n{\n\tname\tObject|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreat"
"or_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444923\n\ttotal_crc\t235\n\ttype\t2\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.120029509\t-0.00284469454\t-0.0302077383\n\toldpos\t150.710999\t25.8584995\t8.19172001\n\trotation\t0.145459949970245361328125\t-0.1646589934825897216796875\t0.659558117389678955078125\t-0.718826770782470703125\n\tchildpos\t0\t-0.182999998\t-0.26699999\n\tchildrot\t0.991444766521453857421875\t3.271923924330621957778931e-05\t-0.0002416197530692443251609802\t0.1305266767740249633789062\n\tscale\t0.0382982\t0.205957\t0.368276\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundra"
"dius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t32\n\t\t\tbegin\t0.3\n\t\t\tend\t0.65\n\t\t\tscale_x\t1\n\t\t\tscale_y\t0.05\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t0\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t3\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0"
"\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061087534454174\n\treztime\t1094866329021741\n\tparceltime\t1133568981982889\n\ttax_rate\t1.00326\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tchild\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n{'task_id':ue4b19200-9d33-962f-c8c5-6f"
"25be3a3fd0}\n{\n\tname\tApotheosis_Immolaine_tail|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreator_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444924\n\ttotal_crc\t675\n\ttype\t1\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.34780401\t-0.00968400016\t-0.260098994\n\toldpos\t0\t0\t0\n\trotation\t0.73164522647857666015625\t-0.67541944980621337890625\t-0.07733880728483200073242188\t0.05022468417882919311523438\n\tvelocity\t0\t0\t0\n\tangvel\t0\t0\t0\n\tscale\t0.0382982\t0.32228\t0.383834\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000"
"000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t32\n\t\t\tbegin\t0.3\n\t\t\tend\t0.65\n\t\t\tscale_x\t1\n\t\t\tscale_y\t0.05\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t0\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t3\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1"
".57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061087463950186\n\treztime\t1094866329022555\n\tparceltime\t1133568981984359\n\tdescription\t(No Description)|\n\ttax_rate\t1.01736\n\tnamevalue\tAttachPt U32 RW S 10\n\tnamevalue\tAttachmentOrientation VEC3 RW DS -3.110088, -0.182018, 1.493795\n\tnamevalue\tAttachmentOffset VEC3 RW DS -0.347804, -0.009684, -0.260099\n\tnamevalue\tAttachItemI"
"D STRING RW SV 20f36c3a-b44b-9bc7-87f3-018bfdfc8cda\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\torig_asset_id\t8747acbc-d391-1e59-69f1-41d06830e6c0\n\torig_item_id\t20f36c3a-b44b-9bc7-87f3-018bfdfc8cda\n\tfrom_task_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tlinked\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n");
}
template<> template<>
void URITestObject::test<18>()
{
LLURI u("secondlife:///app/login?first_name=Testert4&last_name=Tester&web_login_key=test");
// if secondlife is the scheme, LLURI should parse /app/login as path, with no authority
ensure_equals("scheme", u.scheme(), "secondlife");
ensure_equals("authority", u.authority(), "");
ensure_equals("path", u.path(), "/app/login");
ensure_equals("pathmap", u.pathArray()[0].asString(), "app");
ensure_equals("pathmap", u.pathArray()[1].asString(), "login");
ensure_equals("query", u.query(), "first_name=Testert4&last_name=Tester&web_login_key=test");
ensure_equals("query map element", u.queryMap()["last_name"].asString(), "Tester");
u = LLURI("secondlife://Da Boom/128/128/128");
// if secondlife is the scheme, LLURI should parse /128/128/128 as path, with Da Boom as authority
ensure_equals("scheme", u.scheme(), "secondlife");
ensure_equals("authority", u.authority(), "Da Boom");
ensure_equals("path", u.path(), "/128/128/128");
ensure_equals("pathmap", u.pathArray()[0].asString(), "128");
ensure_equals("pathmap", u.pathArray()[1].asString(), "128");
ensure_equals("pathmap", u.pathArray()[2].asString(), "128");
ensure_equals("query", u.query(), "");
}
template<> template<>
void URITestObject::test<19>()
{
// Parse about: schemes
LLURI u("about:blank?redirect-http-hack=secondlife%3A%2F%2F%2Fapp%2Flogin%3Ffirst_name%3DCallum%26last_name%3DLinden%26location%3Dspecify%26grid%3Dvaak%26region%3D%2FMorris%2F128%2F128%26web_login_key%3Defaa4795-c2aa-4c58-8966-763c27931e78");
ensure_equals("scheme", u.scheme(), "about");
ensure_equals("authority", u.authority(), "");
ensure_equals("path", u.path(), "blank");
ensure_equals("pathmap", u.pathArray()[0].asString(), "blank");
ensure_equals("query", u.query(), "redirect-http-hack=secondlife:///app/login?first_name=Callum&last_name=Linden&location=specify&grid=vaak&region=/Morris/128/128&web_login_key=efaa4795-c2aa-4c58-8966-763c27931e78");
ensure_equals("query map element", u.queryMap()["redirect-http-hack"].asString(), "secondlife:///app/login?first_name=Callum&last_name=Linden&location=specify&grid=vaak&region=/Morris/128/128&web_login_key=efaa4795-c2aa-4c58-8966-763c27931e78");
}
}

View File

@ -159,7 +159,7 @@ U8* LLImageBase::allocateData(S32 size)
size = mWidth * mHeight * mComponents;
if (size <= 0)
{
llerrs << llformat("LLImageBase::allocateData called with bad dimentions: %dx%dx%d",mWidth,mHeight,mComponents) << llendl;
llerrs << llformat("LLImageBase::allocateData called with bad dimensions: %dx%dx%d",mWidth,mHeight,mComponents) << llendl;
}
}
else if (size <= 0 || (size > 4096*4096*16 && sSizeOverride == FALSE))

View File

@ -6,6 +6,7 @@ include(00-Common)
include(LLCommon)
include(LLMath)
include(LLMessage)
include(LLVFS)
include(LLXML)
include_directories(
@ -54,3 +55,16 @@ set_source_files_properties(${llinventory_HEADER_FILES}
list(APPEND llinventory_SOURCE_FILES ${llinventory_HEADER_FILES})
add_library (llinventory ${llinventory_SOURCE_FILES})
#add unit tests
INCLUDE(LLAddBuildTest)
SET(llinventory_TEST_SOURCE_FILES
# no real unit tests yet!
)
LL_ADD_PROJECT_UNIT_TESTS(llinventory "${llinventory_TEST_SOURCE_FILES}")
#set(TEST_DEBUG on)
set(test_libs llinventory ${LLMESSAGE_LIBRARIES} ${LLVFS_LIBRARIES} ${LLMATH_LIBRARIES} ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
LL_ADD_INTEGRATION_TEST(inventorymisc "" "${test_libs}")

View File

@ -706,7 +706,6 @@ void LLParcel::packMessage(LLSD& msg)
msg["category"] = (U8)mCategory;
msg["auth_buyer_id"] = mAuthBuyerID;
msg["snapshot_id"] = mSnapshotID;
msg["snapshot_id"] = mSnapshotID;
msg["user_location"] = ll_sd_from_vector3(mUserLocation);
msg["user_look_at"] = ll_sd_from_vector3(mUserLookAt);
msg["landing_type"] = (U8)mLandingType;

View File

@ -0,0 +1,514 @@
/**
* @file inventory.cpp
* @author Phoenix
* @date 2005-11-15
* @brief Functions for inventory test framework
*
* $LicenseInfo:firstyear=2005&license=viewergpl$
*
* Copyright (c) 2005-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llsd.h"
#include "../llinventory.h"
#include "../test/lltut.h"
#if LL_WINDOWS
// disable unreachable code warnings
#pragma warning(disable: 4702)
#endif
LLPointer<LLInventoryItem> create_random_inventory_item()
{
LLUUID item_id;
item_id.generate();
LLUUID parent_id;
parent_id.generate();
LLPermissions perm;
LLUUID creator_id;
creator_id.generate();
LLUUID owner_id;
owner_id.generate();
LLUUID last_owner_id;
last_owner_id.generate();
LLUUID group_id;
group_id.generate();
perm.init(creator_id, owner_id, last_owner_id, group_id);
perm.initMasks(PERM_ALL, PERM_ALL, PERM_COPY, PERM_COPY, PERM_MODIFY | PERM_COPY);
LLUUID asset_id;
asset_id.generate();
S32 price = rand();
LLSaleInfo sale_info(LLSaleInfo::FS_COPY, price);
U32 flags = rand();
S32 creation = time(NULL);
LLPointer<LLInventoryItem> item = new LLInventoryItem(
item_id,
parent_id,
perm,
asset_id,
LLAssetType::AT_OBJECT,
LLInventoryType::IT_ATTACHMENT,
std::string("Sample Object"),
std::string("Used for Testing"),
sale_info,
flags,
creation);
return item;
}
LLPointer<LLInventoryCategory> create_random_inventory_cat()
{
LLUUID item_id;
item_id.generate();
LLUUID parent_id;
parent_id.generate();
LLPointer<LLInventoryCategory> cat = new LLInventoryCategory(
item_id,
parent_id,
LLAssetType::AT_NONE,
std::string("Sample category"));
return cat;
}
namespace tut
{
struct inventory_data
{
};
typedef test_group<inventory_data> inventory_test;
typedef inventory_test::object inventory_object;
tut::inventory_test inv("llinventory");
//***class LLInventoryType***//
template<> template<>
void inventory_object::test<1>()
{
LLInventoryType::EType retType = LLInventoryType::lookup(std::string("sound"));
ensure("1.LLInventoryType::lookup(char*) failed", retType == LLInventoryType::IT_SOUND);
retType = LLInventoryType::lookup(std::string("snapshot"));
ensure("2.LLInventoryType::lookup(char*) failed", retType == LLInventoryType::IT_SNAPSHOT);
}
template<> template<>
void inventory_object::test<2>()
{
static std::string retType = LLInventoryType::lookup(LLInventoryType::IT_CALLINGCARD);
ensure("1.LLInventoryType::lookup(EType) failed", (retType == "callcard"));
retType = LLInventoryType::lookup(LLInventoryType::IT_LANDMARK);
ensure("2.LLInventoryType::lookup(EType) failed", (retType == "landmark"));
}
template<> template<>
void inventory_object::test<3>()
{
static std::string retType = LLInventoryType::lookupHumanReadable(LLInventoryType::IT_CALLINGCARD);
ensure("1.LLInventoryType::lookupHumanReadable(EType) failed", (retType == "calling card"));
retType = LLInventoryType::lookupHumanReadable(LLInventoryType::IT_LANDMARK);
ensure("2.LLInventoryType::lookupHumanReadable(EType) failed", (retType == "landmark"));
}
template<> template<>
void inventory_object::test<4>()
{
static LLInventoryType::EType retType = LLInventoryType::defaultForAssetType(LLAssetType::AT_TEXTURE);
ensure("1.LLInventoryType::defaultForAssetType(LLAssetType EType) failed", retType == LLInventoryType::IT_TEXTURE);
retType = LLInventoryType::defaultForAssetType(LLAssetType::AT_LANDMARK);
ensure("2.LLInventoryType::defaultForAssetType(LLAssetType EType) failed", retType == LLInventoryType::IT_LANDMARK);
}
//*****class LLInventoryItem*****//
template<> template<>
void inventory_object::test<5>()
{
LLPointer<LLInventoryItem> src = create_random_inventory_item();
LLSD sd = ll_create_sd_from_inventory_item(src);
//llinfos << "sd: " << *sd << llendl;
LLPointer<LLInventoryItem> dst = new LLInventoryItem;
bool successful_parse = dst->fromLLSD(sd);
ensure_equals("0.LLInventoryItem::fromLLSD()", successful_parse, true);
ensure_equals("1.item id::getUUID() failed", dst->getUUID(), src->getUUID());
ensure_equals("2.parent::getParentUUID() failed", dst->getParentUUID(), src->getParentUUID());
ensure_equals("3.name::getName() failed", dst->getName(), src->getName());
ensure_equals("4.type::getType() failed", dst->getType(), src->getType());
ensure_equals("5.permissions::getPermissions() failed", dst->getPermissions(), src->getPermissions());
ensure_equals("6.description::getDescription() failed", dst->getDescription(), src->getDescription());
ensure_equals("7.sale type::getSaleType() failed", dst->getSaleInfo().getSaleType(), src->getSaleInfo().getSaleType());
ensure_equals("8.sale price::getSalePrice() failed", dst->getSaleInfo().getSalePrice(), src->getSaleInfo().getSalePrice());
ensure_equals("9.asset id::getAssetUUID() failed", dst->getAssetUUID(), src->getAssetUUID());
ensure_equals("10.inventory type::getInventoryType() failed", dst->getInventoryType(), src->getInventoryType());
ensure_equals("11.flags::getFlags() failed", dst->getFlags(), src->getFlags());
ensure_equals("12.creation::getCreationDate() failed", dst->getCreationDate(), src->getCreationDate());
LLUUID new_item_id, new_parent_id;
new_item_id.generate();
src->setUUID(new_item_id);
new_parent_id.generate();
src->setParent(new_parent_id);
std::string new_name = "LindenLab";
src->rename(new_name);
src->setType(LLAssetType::AT_SOUND);
LLUUID new_asset_id;
new_asset_id.generate();
src->setAssetUUID(new_asset_id);
std::string new_desc = "SecondLife Testing";
src->setDescription(new_desc);
S32 new_price = rand();
LLSaleInfo new_sale_info(LLSaleInfo::FS_COPY, new_price);
src->setSaleInfo(new_sale_info);
U32 new_flags = rand();
S32 new_creation = time(NULL);
LLPermissions new_perm;
LLUUID new_creator_id;
new_creator_id.generate();
LLUUID new_owner_id;
new_owner_id.generate();
LLUUID last_owner_id;
last_owner_id.generate();
LLUUID new_group_id;
new_group_id.generate();
new_perm.init(new_creator_id, new_owner_id, last_owner_id, new_group_id);
new_perm.initMasks(PERM_ALL, PERM_ALL, PERM_COPY, PERM_COPY, PERM_MODIFY | PERM_COPY);
src->setPermissions(new_perm);
src->setInventoryType(LLInventoryType::IT_SOUND);
src->setFlags(new_flags);
src->setCreationDate(new_creation);
sd = ll_create_sd_from_inventory_item(src);
//llinfos << "sd: " << *sd << llendl;
successful_parse = dst->fromLLSD(sd);
ensure_equals("13.item id::getUUID() failed", dst->getUUID(), src->getUUID());
ensure_equals("14.parent::getParentUUID() failed", dst->getParentUUID(), src->getParentUUID());
ensure_equals("15.name::getName() failed", dst->getName(), src->getName());
ensure_equals("16.type::getType() failed", dst->getType(), src->getType());
ensure_equals("17.permissions::getPermissions() failed", dst->getPermissions(), src->getPermissions());
ensure_equals("18.description::getDescription() failed", dst->getDescription(), src->getDescription());
ensure_equals("19.sale type::getSaleType() failed type", dst->getSaleInfo().getSaleType(), src->getSaleInfo().getSaleType());
ensure_equals("20.sale price::getSalePrice() failed price", dst->getSaleInfo().getSalePrice(), src->getSaleInfo().getSalePrice());
ensure_equals("21.asset id::getAssetUUID() failed id", dst->getAssetUUID(), src->getAssetUUID());
ensure_equals("22.inventory type::getInventoryType() failed type", dst->getInventoryType(), src->getInventoryType());
ensure_equals("23.flags::getFlags() failed", dst->getFlags(), src->getFlags());
ensure_equals("24.creation::getCreationDate() failed", dst->getCreationDate(), src->getCreationDate());
}
template<> template<>
void inventory_object::test<6>()
{
LLPointer<LLInventoryItem> src = create_random_inventory_item();
LLUUID new_item_id, new_parent_id;
new_item_id.generate();
src->setUUID(new_item_id);
new_parent_id.generate();
src->setParent(new_parent_id);
std::string new_name = "LindenLab";
src->rename(new_name);
src->setType(LLAssetType::AT_SOUND);
LLUUID new_asset_id;
new_asset_id.generate();
src->setAssetUUID(new_asset_id);
std::string new_desc = "SecondLife Testing";
src->setDescription(new_desc);
S32 new_price = rand();
LLSaleInfo new_sale_info(LLSaleInfo::FS_COPY, new_price);
src->setSaleInfo(new_sale_info);
U32 new_flags = rand();
S32 new_creation = time(NULL);
LLPermissions new_perm;
LLUUID new_creator_id;
new_creator_id.generate();
LLUUID new_owner_id;
new_owner_id.generate();
LLUUID last_owner_id;
last_owner_id.generate();
LLUUID new_group_id;
new_group_id.generate();
new_perm.init(new_creator_id, new_owner_id, last_owner_id, new_group_id);
new_perm.initMasks(PERM_ALL, PERM_ALL, PERM_COPY, PERM_COPY, PERM_MODIFY | PERM_COPY);
src->setPermissions(new_perm);
src->setInventoryType(LLInventoryType::IT_SOUND);
src->setFlags(new_flags);
src->setCreationDate(new_creation);
// test a save/load cycle to LLSD and back again
LLSD sd = ll_create_sd_from_inventory_item(src);
LLPointer<LLInventoryItem> dst = new LLInventoryItem;
bool successful_parse = dst->fromLLSD(sd);
ensure_equals("0.LLInventoryItem::fromLLSD()", successful_parse, true);
LLPointer<LLInventoryItem> src1 = create_random_inventory_item();
src1->copyItem(src);
ensure_equals("1.item id::getUUID() failed", dst->getUUID(), src1->getUUID());
ensure_equals("2.parent::getParentUUID() failed", dst->getParentUUID(), src1->getParentUUID());
ensure_equals("3.name::getName() failed", dst->getName(), src1->getName());
ensure_equals("4.type::getType() failed", dst->getType(), src1->getType());
ensure_equals("5.permissions::getPermissions() failed", dst->getPermissions(), src1->getPermissions());
ensure_equals("6.description::getDescription() failed", dst->getDescription(), src1->getDescription());
ensure_equals("7.sale type::getSaleType() failed type", dst->getSaleInfo().getSaleType(), src1->getSaleInfo().getSaleType());
ensure_equals("8.sale price::getSalePrice() failed price", dst->getSaleInfo().getSalePrice(), src1->getSaleInfo().getSalePrice());
ensure_equals("9.asset id::getAssetUUID() failed id", dst->getAssetUUID(), src1->getAssetUUID());
ensure_equals("10.inventory type::getInventoryType() failed type", dst->getInventoryType(), src1->getInventoryType());
ensure_equals("11.flags::getFlags() failed", dst->getFlags(), src1->getFlags());
ensure_equals("12.creation::getCreationDate() failed", dst->getCreationDate(), src1->getCreationDate());
// quick test to make sure generateUUID() really works
src1->generateUUID();
ensure_not_equals("13.item id::generateUUID() failed", src->getUUID(), src1->getUUID());
}
template<> template<>
void inventory_object::test<7>()
{
LLFILE* fp = LLFile::fopen("linden_file.dat","w+");
if(!fp)
{
llerrs << "file could not be opened\n" << llendl;
return;
}
LLPointer<LLInventoryItem> src1 = create_random_inventory_item();
src1->exportFile(fp, TRUE);
fclose(fp);
LLPointer<LLInventoryItem> src2 = new LLInventoryItem();
fp = LLFile::fopen("linden_file.dat","r+");
if(!fp)
{
llerrs << "file could not be opened\n" << llendl;
return;
}
src2->importFile(fp);
fclose(fp);
ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID());
ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID());
ensure_equals("3.permissions::getPermissions() failed", src1->getPermissions(), src2->getPermissions());
ensure_equals("4.sale price::getSalePrice() failed price", src1->getSaleInfo().getSalePrice(), src2->getSaleInfo().getSalePrice());
ensure_equals("5.asset id::getAssetUUID() failed id", src1->getAssetUUID(), src2->getAssetUUID());
ensure_equals("6.type::getType() failed", src1->getType(), src2->getType());
ensure_equals("7.inventory type::getInventoryType() failed type", src1->getInventoryType(), src2->getInventoryType());
ensure_equals("8.name::getName() failed", src1->getName(), src2->getName());
ensure_equals("9.description::getDescription() failed", src1->getDescription(), src2->getDescription());
ensure_equals("10.creation::getCreationDate() failed", src1->getCreationDate(), src2->getCreationDate());
}
template<> template<>
void inventory_object::test<8>()
{
LLPointer<LLInventoryItem> src1 = create_random_inventory_item();
std::ostringstream ostream;
src1->exportLegacyStream(ostream, TRUE);
std::istringstream istream(ostream.str());
LLPointer<LLInventoryItem> src2 = new LLInventoryItem();
src2->importLegacyStream(istream);
ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID());
ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID());
ensure_equals("3.permissions::getPermissions() failed", src1->getPermissions(), src2->getPermissions());
ensure_equals("4.sale price::getSalePrice() failed price", src1->getSaleInfo().getSalePrice(), src2->getSaleInfo().getSalePrice());
ensure_equals("5.asset id::getAssetUUID() failed id", src1->getAssetUUID(), src2->getAssetUUID());
ensure_equals("6.type::getType() failed", src1->getType(), src2->getType());
ensure_equals("7.inventory type::getInventoryType() failed type", src1->getInventoryType(), src2->getInventoryType());
ensure_equals("8.name::getName() failed", src1->getName(), src2->getName());
ensure_equals("9.description::getDescription() failed", src1->getDescription(), src2->getDescription());
ensure_equals("10.creation::getCreationDate() failed", src1->getCreationDate(), src2->getCreationDate());
}
template<> template<>
void inventory_object::test<9>()
{
// Deleted LLInventoryItem::exportFileXML() and LLInventoryItem::importXML()
// because I can't find any non-test code references to it. 2009-05-04 JC
}
template<> template<>
void inventory_object::test<10>()
{
LLPointer<LLInventoryItem> src1 = create_random_inventory_item();
U8* bin_bucket = new U8[300];
S32 bin_bucket_size = src1->packBinaryBucket(bin_bucket, NULL);
LLPointer<LLInventoryItem> src2 = new LLInventoryItem();
src2->unpackBinaryBucket(bin_bucket, bin_bucket_size);
ensure_equals("1.sale price::getSalePrice() failed price", src1->getSaleInfo().getSalePrice(), src2->getSaleInfo().getSalePrice());
ensure_equals("2.sale type::getSaleType() failed type", src1->getSaleInfo().getSaleType(), src2->getSaleInfo().getSaleType());
ensure_equals("3.type::getType() failed", src1->getType(), src2->getType());
ensure_equals("4.inventory type::getInventoryType() failed type", src1->getInventoryType(), src2->getInventoryType());
ensure_equals("5.name::getName() failed", src1->getName(), src2->getName());
ensure_equals("6.description::getDescription() failed", src1->getDescription(), src2->getDescription());
ensure_equals("7.flags::getFlags() failed", src1->getFlags(), src2->getFlags());
}
template<> template<>
void inventory_object::test<11>()
{
LLPointer<LLInventoryItem> src1 = create_random_inventory_item();
LLSD retSd = src1->asLLSD();
LLPointer<LLInventoryItem> src2 = new LLInventoryItem();
src2->fromLLSD(retSd);
ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID());
ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID());
ensure_equals("3.permissions::getPermissions() failed", src1->getPermissions(), src2->getPermissions());
ensure_equals("4.asset id::getAssetUUID() failed id", src1->getAssetUUID(), src2->getAssetUUID());
ensure_equals("5.type::getType() failed", src1->getType(), src2->getType());
ensure_equals("6.inventory type::getInventoryType() failed type", src1->getInventoryType(), src2->getInventoryType());
ensure_equals("7.flags::getFlags() failed", src1->getFlags(), src2->getFlags());
ensure_equals("8.sale type::getSaleType() failed type", src1->getSaleInfo().getSaleType(), src2->getSaleInfo().getSaleType());
ensure_equals("9.sale price::getSalePrice() failed price", src1->getSaleInfo().getSalePrice(), src2->getSaleInfo().getSalePrice());
ensure_equals("10.name::getName() failed", src1->getName(), src2->getName());
ensure_equals("11.description::getDescription() failed", src1->getDescription(), src2->getDescription());
ensure_equals("12.creation::getCreationDate() failed", src1->getCreationDate(), src2->getCreationDate());
}
//******class LLInventoryCategory*******//
template<> template<>
void inventory_object::test<12>()
{
LLPointer<LLInventoryCategory> src = create_random_inventory_cat();
LLSD sd = ll_create_sd_from_inventory_category(src);
LLPointer<LLInventoryCategory> dst = ll_create_category_from_sd(sd);
ensure_equals("1.item id::getUUID() failed", dst->getUUID(), src->getUUID());
ensure_equals("2.parent::getParentUUID() failed", dst->getParentUUID(), src->getParentUUID());
ensure_equals("3.name::getName() failed", dst->getName(), src->getName());
ensure_equals("4.type::getType() failed", dst->getType(), src->getType());
ensure_equals("5.preferred type::getPreferredType() failed", dst->getPreferredType(), src->getPreferredType());
src->setPreferredType( LLAssetType::AT_TEXTURE);
sd = ll_create_sd_from_inventory_category(src);
dst = ll_create_category_from_sd(sd);
ensure_equals("6.preferred type::getPreferredType() failed", dst->getPreferredType(), src->getPreferredType());
}
template<> template<>
void inventory_object::test<13>()
{
LLFILE* fp = LLFile::fopen("linden_file.dat","w");
if(!fp)
{
llerrs << "file coudnt be opened\n" << llendl;
return;
}
LLPointer<LLInventoryCategory> src1 = create_random_inventory_cat();
src1->exportFile(fp, TRUE);
fclose(fp);
LLPointer<LLInventoryCategory> src2 = new LLInventoryCategory();
fp = LLFile::fopen("linden_file.dat","r");
if(!fp)
{
llerrs << "file coudnt be opened\n" << llendl;
return;
}
src2->importFile(fp);
fclose(fp);
ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID());
ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID());
ensure_equals("3.type::getType() failed", src1->getType(), src2->getType());
ensure_equals("4.preferred type::getPreferredType() failed", src1->getPreferredType(), src2->getPreferredType());
ensure_equals("5.name::getName() failed", src1->getName(), src2->getName());
}
template<> template<>
void inventory_object::test<14>()
{
LLPointer<LLInventoryCategory> src1 = create_random_inventory_cat();
std::ostringstream ostream;
src1->exportLegacyStream(ostream, TRUE);
std::istringstream istream(ostream.str());
LLPointer<LLInventoryCategory> src2 = new LLInventoryCategory();
src2->importLegacyStream(istream);
ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID());
ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID());
ensure_equals("3.type::getType() failed", src1->getType(), src2->getType());
ensure_equals("4.preferred type::getPreferredType() failed", src1->getPreferredType(), src2->getPreferredType());
ensure_equals("5.name::getName() failed", src1->getName(), src2->getName());
}
}

View File

@ -15,6 +15,7 @@ set(llmath_SOURCE_FILES
llcamera.cpp
llcoordframe.cpp
llline.cpp
llmodularmath.cpp
llperlin.cpp
llquaternion.cpp
llrect.cpp
@ -48,6 +49,7 @@ set(llmath_HEADER_FILES
llinterp.h
llline.h
llmath.h
llmodularmath.h
lloctree.h
llperlin.h
llplane.h
@ -83,12 +85,28 @@ list(APPEND llmath_SOURCE_FILES ${llmath_HEADER_FILES})
add_library (llmath ${llmath_SOURCE_FILES})
# Add tests
include(LLAddBuildTest)
# UNIT TESTS
SET(llmath_TEST_SOURCE_FILES
# nat 2009-08-28: found this commented out and considered implementing it
# using LL_ADD_INTEGRATION_TEST, but there's no llvolume_test.cpp source?
# llvolume.cpp
llbboxlocal.cpp
llmodularmath.cpp
llrect.cpp
v2math.cpp
v3color.cpp
v4color.cpp
v4coloru.cpp
)
LL_ADD_PROJECT_UNIT_TESTS(llmath "${llmath_TEST_SOURCE_FILES}")
# INTEGRATION TESTS
set(test_libs llmath llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
# TODO: Some of these need refactoring to be proper Unit tests rather than Integration tests.
LL_ADD_INTEGRATION_TEST(llbbox llbbox.cpp "${test_libs}")
LL_ADD_INTEGRATION_TEST(llquaternion llquaternion.cpp "${test_libs}")
LL_ADD_INTEGRATION_TEST(mathmisc "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(m3math "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(v3dmath v3dmath.cpp "${test_libs}")
LL_ADD_INTEGRATION_TEST(v3math v3math.cpp "${test_libs}")
LL_ADD_INTEGRATION_TEST(v4math v4math.cpp "${test_libs}")
LL_ADD_INTEGRATION_TEST(xform xform.cpp "${test_libs}")

View File

@ -0,0 +1,36 @@
/**
* @file llmodularmath.cpp
* @brief LLModularMath class implementation
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
// implementation is all in the header, this include dep ensures the unit test is rerun if the implementation changes.
#include "llmodularmath.h"

View File

@ -1,5 +1,6 @@
/**
* @file llrect.cpp
* @brief LLRect class implementation
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
@ -31,4 +32,5 @@
#include "linden_common.h"
// implementation is all in the header, this include dep ensures the unit test is rerun if the implementation changes.
#include "llrect.h"

View File

@ -4273,7 +4273,7 @@ LLFaceID LLVolume::generateFaceMask()
}
break;
default:
llerrs << "Unknown profile!" << llendl
llerrs << "Unknown profile!" << llendl;
break;
}

View File

@ -678,32 +678,6 @@ LLVector4 operator*(const LLMatrix4 &a, const LLVector4 &b)
}
*/
// Operates "to the left" on row-vector a
//
// This used to be in the header file but was not actually inlined in practice.
// When avatar vertex programs are off, this function is a hot spot in profiles
// due to software skinning in LLViewerJointMesh::updateGeometry(). JC
LLVector3 operator*(const LLVector3 &a, const LLMatrix4 &b)
{
// This is better than making a temporary LLVector3. This eliminates an
// unnecessary LLVector3() constructor and also helps the compiler to
// realize that the output floats do not alias the input floats, hence
// eliminating redundant loads of a.mV[0], etc. JC
return LLVector3(a.mV[VX] * b.mMatrix[VX][VX] +
a.mV[VY] * b.mMatrix[VY][VX] +
a.mV[VZ] * b.mMatrix[VZ][VX] +
b.mMatrix[VW][VX],
a.mV[VX] * b.mMatrix[VX][VY] +
a.mV[VY] * b.mMatrix[VY][VY] +
a.mV[VZ] * b.mMatrix[VZ][VY] +
b.mMatrix[VW][VY],
a.mV[VX] * b.mMatrix[VX][VZ] +
a.mV[VY] * b.mMatrix[VY][VZ] +
a.mV[VZ] * b.mMatrix[VZ][VZ] +
b.mMatrix[VW][VZ]);
}
LLVector4 operator*(const LLVector4 &a, const LLMatrix4 &b)
{

View File

@ -230,7 +230,7 @@ public:
// friend inline LLMatrix4 operator*(const LLMatrix4 &a, const LLMatrix4 &b); // Return a * b
friend LLVector4 operator*(const LLVector4 &a, const LLMatrix4 &b); // Return transform of vector a by matrix b
friend LLVector3 operator*(const LLVector3 &a, const LLMatrix4 &b); // Return full transform of a by matrix b
friend const LLVector3 operator*(const LLVector3 &a, const LLMatrix4 &b); // Return full transform of a by matrix b
friend LLVector4 rotate_vector(const LLVector4 &a, const LLMatrix4 &b); // Rotates a but does not translate
friend LLVector3 rotate_vector(const LLVector3 &a, const LLMatrix4 &b); // Rotates a but does not translate
@ -353,7 +353,31 @@ inline const LLMatrix4& operator-=(LLMatrix4 &a, const LLMatrix4 &b)
return a;
}
// Operates "to the left" on row-vector a
//
// When avatar vertex programs are off, this function is a hot spot in profiles
// due to software skinning in LLViewerJointMesh::updateGeometry(). JC
inline const LLVector3 operator*(const LLVector3 &a, const LLMatrix4 &b)
{
// This is better than making a temporary LLVector3. This eliminates an
// unnecessary LLVector3() constructor and also helps the compiler to
// realize that the output floats do not alias the input floats, hence
// eliminating redundant loads of a.mV[0], etc. JC
return LLVector3(a.mV[VX] * b.mMatrix[VX][VX] +
a.mV[VY] * b.mMatrix[VY][VX] +
a.mV[VZ] * b.mMatrix[VZ][VX] +
b.mMatrix[VW][VX],
a.mV[VX] * b.mMatrix[VX][VY] +
a.mV[VY] * b.mMatrix[VY][VY] +
a.mV[VZ] * b.mMatrix[VZ][VY] +
b.mMatrix[VW][VY],
a.mV[VX] * b.mMatrix[VX][VZ] +
a.mV[VY] * b.mMatrix[VY][VZ] +
a.mV[VZ] * b.mMatrix[VZ][VZ] +
b.mMatrix[VW][VZ]);
}
#endif

View File

@ -0,0 +1,373 @@
/**
* @file llbbox_tut.cpp
* @author Martin Reddy
* @date 2009-06-25
* @brief Test for llbbox.cpp.
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
* Copyright (c) 2009-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "../test/lltut.h"
#include "../llbbox.h"
#define ANGLE (3.14159265f / 2.0f)
#define APPROX_EQUAL(a, b) dist_vec((a),(b)) < 1e-5
namespace tut
{
struct LLBBoxData
{
};
typedef test_group<LLBBoxData> factory;
typedef factory::object object;
}
namespace
{
tut::factory llbbox_test_factory("LLBBox");
}
namespace tut
{
template<> template<>
void object::test<1>()
{
//
// test the default constructor
//
LLBBox bbox1;
ensure_equals("Default bbox min", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, 0.0f));
ensure_equals("Default bbox max", bbox1.getMaxLocal(), LLVector3(0.0f, 0.0f, 0.0f));
ensure_equals("Default bbox pos agent", bbox1.getPositionAgent(), LLVector3(0.0f, 0.0f, 0.0f));
ensure_equals("Default bbox rotation", bbox1.getRotation(), LLQuaternion(0.0f, 0.0f, 0.0f, 1.0f));
}
template<> template<>
void object::test<2>()
{
//
// test the non-default constructor
//
LLBBox bbox2(LLVector3(1.0f, 2.0f, 3.0f), LLQuaternion(),
LLVector3(2.0f, 3.0f, 4.0f), LLVector3(4.0f, 5.0f, 6.0f));
ensure_equals("Custom bbox min", bbox2.getMinLocal(), LLVector3(2.0f, 3.0f, 4.0f));
ensure_equals("Custom bbox max", bbox2.getMaxLocal(), LLVector3(4.0f, 5.0f, 6.0f));
ensure_equals("Custom bbox pos agent", bbox2.getPositionAgent(), LLVector3(1.0f, 2.0f, 3.0f));
ensure_equals("Custom bbox rotation", bbox2.getRotation(), LLQuaternion(0.0f, 0.0f, 0.0f, 1.0f));
}
template<> template<>
void object::test<3>()
{
//
// test the setMinLocal() method
//
LLBBox bbox2;
bbox2.setMinLocal(LLVector3(3.0f, 3.0f, 3.0f));
ensure_equals("Custom bbox min (2)", bbox2.getMinLocal(), LLVector3(3.0f, 3.0f, 3.0f));
}
template<> template<>
void object::test<4>()
{
//
// test the setMaxLocal() method
//
LLBBox bbox2;
bbox2.setMaxLocal(LLVector3(5.0f, 5.0f, 5.0f));
ensure_equals("Custom bbox max (2)", bbox2.getMaxLocal(), LLVector3(5.0f, 5.0f, 5.0f));
}
template<> template<>
void object::test<5>()
{
//
// test the getCenterLocal() method
//
ensure_equals("Default bbox local center", LLBBox().getCenterLocal(), LLVector3(0.0f, 0.0f, 0.0f));
LLBBox bbox1(LLVector3(1.0f, 2.0f, 3.0f), LLQuaternion(),
LLVector3(2.0f, 4.0f, 6.0f), LLVector3(4.0f, 6.0f, 8.0f));
ensure_equals("Custom bbox center local", bbox1.getCenterLocal(), LLVector3(3.0f, 5.0f, 7.0f));
LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(0.0f, 0.0f, 1.0f)),
LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f));
ensure_equals("Custom bbox center local with rot", bbox2.getCenterLocal(), LLVector3(3.0f, 3.0f, 3.0f));
}
template<> template<>
void object::test<6>()
{
//
// test the getCenterAgent()
//
ensure_equals("Default bbox agent center", LLBBox().getCenterAgent(), LLVector3(0.0f, 0.0f, 0.0f));
LLBBox bbox1(LLVector3(1.0f, 2.0f, 3.0f), LLQuaternion(),
LLVector3(2.0f, 4.0f, 6.0f), LLVector3(4.0f, 6.0f, 8.0f));
ensure_equals("Custom bbox center agent", bbox1.getCenterAgent(), LLVector3(4.0f, 7.0f, 10.0f));
LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(0.0f, 0.0f, 1.0f)),
LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f));
ensure("Custom bbox center agent with rot", APPROX_EQUAL(bbox2.getCenterAgent(), LLVector3(-2.0f, 4.0f, 4.0f)));
}
template<> template<>
void object::test<7>()
{
//
// test the getExtentLocal() method
//
ensure_equals("Default bbox local extent", LLBBox().getExtentLocal(), LLVector3(0.0f, 0.0f, 0.0f));
LLBBox bbox1(LLVector3(1.0f, 2.0f, 3.0f), LLQuaternion(),
LLVector3(2.0f, 4.0f, 6.0f), LLVector3(4.0f, 6.0f, 8.0f));
ensure_equals("Custom bbox extent local", bbox1.getExtentLocal(), LLVector3(2.0f, 2.0f, 2.0f));
LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(0.0f, 0.0f, 1.0f)),
LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f));
ensure_equals("Custom bbox extent local with rot", bbox1.getExtentLocal(), LLVector3(2.0f, 2.0f, 2.0f));
}
template<> template<>
void object::test<8>()
{
//
// test the addPointLocal() method
//
LLBBox bbox1;
bbox1.addPointLocal(LLVector3(1.0f, 1.0f, 1.0f));
bbox1.addPointLocal(LLVector3(3.0f, 3.0f, 3.0f));
ensure_equals("addPointLocal center local (1)", bbox1.getCenterLocal(), LLVector3(2.0f, 2.0f, 2.0f));
ensure_equals("addPointLocal center agent (1)", bbox1.getCenterAgent(), LLVector3(2.0f, 2.0f, 2.0f));
ensure_equals("addPointLocal min (1)", bbox1.getMinLocal(), LLVector3(1.0f, 1.0f, 1.0f));
ensure_equals("addPointLocal max (1)", bbox1.getMaxLocal(), LLVector3(3.0f, 3.0f, 3.0f));
bbox1.addPointLocal(LLVector3(0.0f, 0.0f, 0.0f));
bbox1.addPointLocal(LLVector3(1.0f, 1.0f, 1.0f));
bbox1.addPointLocal(LLVector3(2.0f, 2.0f, 2.0f));
ensure_equals("addPointLocal center local (2)", bbox1.getCenterLocal(), LLVector3(1.5f, 1.5f, 1.5f));
ensure_equals("addPointLocal min (2)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, 0.0f));
ensure_equals("addPointLocal max (2)", bbox1.getMaxLocal(), LLVector3(3.0f, 3.0f, 3.0f));
}
template<> template<>
void object::test<9>()
{
//
// test the addBBoxLocal() method
//
LLBBox bbox1;
bbox1.addBBoxLocal(LLBBox(LLVector3(), LLQuaternion(),
LLVector3(0.0f, 0.0f, 0.0f), LLVector3(3.0f, 3.0f, 3.0f)));
ensure_equals("addPointLocal center local (3)", bbox1.getCenterLocal(), LLVector3(1.5f, 1.5f, 1.5f));
ensure_equals("addPointLocal min (3)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, 0.0f));
ensure_equals("addPointLocal max (3)", bbox1.getMaxLocal(), LLVector3(3.0f, 3.0f, 3.0f));
bbox1.addBBoxLocal(LLBBox(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(),
LLVector3(5.0f, 5.0f, 5.0f), LLVector3(10.0f, 10.0f, 10.0f)));
ensure_equals("addPointLocal center local (4)", bbox1.getCenterLocal(), LLVector3(5.0f, 5.0f, 5.0f));
ensure_equals("addPointLocal center agent (4)", bbox1.getCenterAgent(), LLVector3(5.0f, 5.0f, 5.0f));
ensure_equals("addPointLocal min (4)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, 0.0f));
ensure_equals("addPointLocal max (4)", bbox1.getMaxLocal(), LLVector3(10.0f, 10.0f, 10.0f));
}
template<> template<>
void object::test<10>()
{
//
// test the addPointAgent() method
//
LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(1.0, 0.0, 0.0, 1.0),
LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f));
bbox1.addPointAgent(LLVector3(1.0f, 1.0f, 1.0f));
bbox1.addPointAgent(LLVector3(3.0f, 3.0f, 3.0f));
ensure_equals("addPointAgent center local (1)", bbox1.getCenterLocal(), LLVector3(2.0f, 2.0f, -2.0f));
ensure_equals("addPointAgent center agent (1)", bbox1.getCenterAgent(), LLVector3(3.0f, 3.0f, 7.0f));
ensure_equals("addPointAgent min (1)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, -4.0f));
ensure_equals("addPointAgent max (1)", bbox1.getMaxLocal(), LLVector3(4.0f, 4.0f, 0.0f));
}
template<> template<>
void object::test<11>()
{
//
// test the addBBoxAgent() method
//
LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(1.0, 0.0, 0.0, 1.0),
LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f));
bbox1.addPointAgent(LLVector3(1.0f, 1.0f, 1.0f));
bbox1.addPointAgent(LLVector3(3.0f, 3.0f, 3.0f));
bbox1.addBBoxLocal(LLBBox(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(),
LLVector3(5.0f, 5.0f, 5.0f), LLVector3(10.0f, 10.0f, 10.0f)));
ensure_equals("addPointAgent center local (2)", bbox1.getCenterLocal(), LLVector3(5.0f, 5.0f, 3.0f));
ensure_equals("addPointAgent center agent (2)", bbox1.getCenterAgent(), LLVector3(6.0f, -10.0f, 8.0f));
ensure_equals("addPointAgent min (2)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, -4.0f));
ensure_equals("addPointAgent max (2)", bbox1.getMaxLocal(), LLVector3(10.0f, 10.0f, 10.0f));
}
template<> template<>
void object::test<12>()
{
//
// test the expand() method
//
LLBBox bbox1;
bbox1.expand(0.0);
ensure_equals("Zero-expanded Default BBox center", bbox1.getCenterLocal(), LLVector3(0.0f, 0.0f, 0.0f));
LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(),
LLVector3(1.0f, 1.0f, 1.0f), LLVector3(3.0f, 3.0f, 3.0f));
bbox2.expand(0.0);
ensure_equals("Zero-expanded center local", bbox2.getCenterLocal(), LLVector3(2.0f, 2.0f, 2.0f));
ensure_equals("Zero-expanded center agent", bbox2.getCenterAgent(), LLVector3(3.0f, 3.0f, 3.0f));
ensure_equals("Zero-expanded min", bbox2.getMinLocal(), LLVector3(1.0f, 1.0f, 1.0f));
ensure_equals("Zero-expanded max", bbox2.getMaxLocal(), LLVector3(3.0f, 3.0f, 3.0f));
bbox2.expand(0.5);
ensure_equals("Positive-expanded center", bbox2.getCenterLocal(), LLVector3(2.0f, 2.0f, 2.0f));
ensure_equals("Positive-expanded min", bbox2.getMinLocal(), LLVector3(0.5f, 0.5f, 0.5f));
ensure_equals("Positive-expanded max", bbox2.getMaxLocal(), LLVector3(3.5f, 3.5f, 3.5f));
bbox2.expand(-1.0);
ensure_equals("Negative-expanded center", bbox2.getCenterLocal(), LLVector3(2.0f, 2.0f, 2.0f));
ensure_equals("Negative-expanded min", bbox2.getMinLocal(), LLVector3(1.5f, 1.5f, 1.5f));
ensure_equals("Negative-expanded max", bbox2.getMaxLocal(), LLVector3(2.5f, 2.5f, 2.5f));
}
template<> template<>
void object::test<13>()
{
//
// test the localToAgent() method
//
LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(),
LLVector3(1.0f, 1.0f, 1.0f), LLVector3(3.0f, 3.0f, 3.0f));
ensure_equals("localToAgent(1,2,3)", bbox1.localToAgent(LLVector3(1.0f, 2.0f, 3.0f)), LLVector3(2.0f, 3.0f, 4.0f));
LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(1.0f, 0.0f, 0.0f)),
LLVector3(1.0f, 1.0f, 1.0f), LLVector3(3.0f, 3.0f, 3.0f));
ensure("localToAgent(1,2,3) rot", APPROX_EQUAL(bbox2.localToAgent(LLVector3(1.0f, 2.0f, 3.0f)), LLVector3(2.0f, -2.0f, 3.0f)));
}
template<> template<>
void object::test<14>()
{
//
// test the agentToLocal() method
//
LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(),
LLVector3(1.0f, 1.0f, 1.0f), LLVector3(3.0f, 3.0f, 3.0f));
ensure_equals("agentToLocal(1,2,3)", bbox1.agentToLocal(LLVector3(1.0f, 2.0f, 3.0f)), LLVector3(0.0f, 1.0f, 2.0f));
ensure_equals("agentToLocal(localToAgent)", bbox1.agentToLocal(bbox1.localToAgent(LLVector3(1.0f, 2.0f, 3.0f))),
LLVector3(1.0f, 2.0f, 3.0f));
LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(1.0f, 0.0f, 0.0f)),
LLVector3(1.0f, 1.0f, 1.0f), LLVector3(3.0f, 3.0f, 3.0f));
ensure("agentToLocal(1,2,3) rot", APPROX_EQUAL(bbox2.agentToLocal(LLVector3(1.0f, 2.0f, 3.0f)), LLVector3(0.0f, 2.0f, -1.0f)));
ensure("agentToLocal(localToAgent) rot", APPROX_EQUAL(bbox2.agentToLocal(bbox2.localToAgent(LLVector3(1.0f, 2.0f, 3.0f))),
LLVector3(1.0f, 2.0f, 3.0f)));
}
template<> template<>
void object::test<15>()
{
//
// test the containsPointLocal() method
//
LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(),
LLVector3(1.0f, 2.0f, 3.0f), LLVector3(3.0f, 4.0f, 5.0f));
ensure("containsPointLocal(0,0,0)", bbox1.containsPointLocal(LLVector3(0.0f, 0.0f, 0.0f)) == FALSE);
ensure("containsPointLocal(1,2,3)", bbox1.containsPointLocal(LLVector3(1.0f, 2.0f, 3.0f)) == TRUE);
ensure("containsPointLocal(0.999,2,3)", bbox1.containsPointLocal(LLVector3(0.999f, 2.0f, 3.0f)) == FALSE);
ensure("containsPointLocal(3,4,5)", bbox1.containsPointLocal(LLVector3(3.0f, 4.0f, 5.0f)) == TRUE);
ensure("containsPointLocal(3,4,5.001)", bbox1.containsPointLocal(LLVector3(3.0f, 4.0f, 5.001f)) == FALSE);
}
template<> template<>
void object::test<16>()
{
//
// test the containsPointAgent() method
//
LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(),
LLVector3(1.0f, 2.0f, 3.0f), LLVector3(3.0f, 4.0f, 5.0f));
ensure("containsPointAgent(0,0,0)", bbox1.containsPointAgent(LLVector3(0.0f, 0.0f, 0.0f)) == FALSE);
ensure("containsPointAgent(2,3,4)", bbox1.containsPointAgent(LLVector3(2.0f, 3.0f, 4.0f)) == TRUE);
ensure("containsPointAgent(2,2.999,4)", bbox1.containsPointAgent(LLVector3(2.0f, 2.999f, 4.0f)) == FALSE);
ensure("containsPointAgent(4,5,6)", bbox1.containsPointAgent(LLVector3(4.0f, 5.0f, 6.0f)) == TRUE);
ensure("containsPointAgent(4,5.001,6)", bbox1.containsPointAgent(LLVector3(4.0f, 5.001f, 6.0f)) == FALSE);
}
}

View File

@ -0,0 +1,238 @@
/**
* @file llbboxlocal_tut.cpp
* @author Martin Reddy
* @date 2009-06-25
* @brief Test for llbboxlocal.cpp.
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
* Copyright (c) 2009-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "../test/lltut.h"
#include "../llbboxlocal.h"
namespace tut
{
struct LLBBoxLocalData
{
};
typedef test_group<LLBBoxLocalData> factory;
typedef factory::object object;
}
namespace
{
tut::factory llbboxlocal_test_factory("LLBBoxLocal");
}
namespace tut
{
template<> template<>
void object::test<1>()
{
//
// test the default constructor
//
LLBBoxLocal bbox1;
ensure_equals("Default bbox min", bbox1.getMin(), LLVector3(0.0f, 0.0f, 0.0f));
ensure_equals("Default bbox max", bbox1.getMax(), LLVector3(0.0f, 0.0f, 0.0f));
}
template<> template<>
void object::test<2>()
{
//
// test the non-default constructor
//
LLBBoxLocal bbox2(LLVector3(-1.0f, -2.0f, 0.0f), LLVector3(1.0f, 2.0f, 3.0f));
ensure_equals("Custom bbox min", bbox2.getMin(), LLVector3(-1.0f, -2.0f, 0.0f));
ensure_equals("Custom bbox max", bbox2.getMax(), LLVector3(1.0f, 2.0f, 3.0f));
}
template<> template<>
void object::test<3>()
{
//
// test the setMin()
//
// N.B. no validation is currently performed to ensure that the min
// and max vectors are actually the min/max values.
//
LLBBoxLocal bbox2;
bbox2.setMin(LLVector3(1.0f, 2.0f, 3.0f));
ensure_equals("Custom bbox min (2)", bbox2.getMin(), LLVector3(1.0f, 2.0f, 3.0f));
}
template<> template<>
void object::test<4>()
{
//
// test the setMax()
//
// N.B. no validation is currently performed to ensure that the min
// and max vectors are actually the min/max values.
//
LLBBoxLocal bbox2;
bbox2.setMax(LLVector3(10.0f, 20.0f, 30.0f));
ensure_equals("Custom bbox max (2)", bbox2.getMax(), LLVector3(10.0f, 20.0f, 30.0f));
}
template<> template<>
void object::test<5>()
{
//
// test the getCenter() method
//
ensure_equals("Default bbox center", LLBBoxLocal().getCenter(), LLVector3(0.0f, 0.0f, 0.0f));
LLBBoxLocal bbox1(LLVector3(-1.0f, -1.0f, -1.0f), LLVector3(0.0f, 0.0f, 0.0f));
ensure_equals("Custom bbox center", bbox1.getCenter(), LLVector3(-0.5f, -0.5f, -0.5f));
LLBBoxLocal bbox2(LLVector3(0.0f, 0.0f, 0.0f), LLVector3(-1.0f, -1.0f, -1.0f));
ensure_equals("Invalid bbox center", bbox2.getCenter(), LLVector3(-0.5f, -0.5f, -0.5f));
}
template<> template<>
void object::test<6>()
{
//
// test the getExtent() method
//
LLBBoxLocal bbox2(LLVector3(0.0f, 0.0f, 0.0f), LLVector3(-1.0f, -1.0f, -1.0f));
ensure_equals("Default bbox extent", LLBBoxLocal().getExtent(), LLVector3(0.0f, 0.0f, 0.0f));
LLBBoxLocal bbox3(LLVector3(-1.0f, -1.0f, -1.0f), LLVector3(1.0f, 2.0f, 0.0f));
ensure_equals("Custom bbox extent", bbox3.getExtent(), LLVector3(2.0f, 3.0f, 1.0f));
}
template<> template<>
void object::test<7>()
{
//
// test the addPoint() method
//
// N.B. if you create an empty bbox and then add points,
// the vector (0, 0, 0) will always be part of the bbox.
// (Fixing this would require adding a bool to the class size).
//
LLBBoxLocal bbox1;
bbox1.addPoint(LLVector3(-1.0f, -2.0f, -3.0f));
bbox1.addPoint(LLVector3(3.0f, 4.0f, 5.0f));
ensure_equals("Custom BBox center (1)", bbox1.getCenter(), LLVector3(1.0f, 1.0f, 1.0f));
ensure_equals("Custom BBox min (1)", bbox1.getMin(), LLVector3(-1.0f, -2.0f, -3.0f));
ensure_equals("Custom BBox max (1)", bbox1.getMax(), LLVector3(3.0f, 4.0f, 5.0f));
bbox1.addPoint(LLVector3(0.0f, 0.0f, 0.0f));
bbox1.addPoint(LLVector3(1.0f, 2.0f, 3.0f));
bbox1.addPoint(LLVector3(2.0f, 2.0f, 2.0f));
ensure_equals("Custom BBox center (2)", bbox1.getCenter(), LLVector3(1.0f, 1.0f, 1.0f));
ensure_equals("Custom BBox min (2)", bbox1.getMin(), LLVector3(-1.0f, -2.0f, -3.0f));
ensure_equals("Custom BBox max (2)", bbox1.getMax(), LLVector3(3.0f, 4.0f, 5.0f));
bbox1.addPoint(LLVector3(5.0f, 5.0f, 5.0f));
ensure_equals("Custom BBox center (3)", bbox1.getCenter(), LLVector3(2.0f, 1.5f, 1.0f));
ensure_equals("Custom BBox min (3)", bbox1.getMin(), LLVector3(-1.0f, -2.0f, -3.0f));
ensure_equals("Custom BBox max (3)", bbox1.getMax(), LLVector3(5.0f, 5.0f, 5.0f));
}
template<> template<>
void object::test<8>()
{
//
// test the addBBox() methods
//
// N.B. if you create an empty bbox and then add points,
// the vector (0, 0, 0) will always be part of the bbox.
// (Fixing this would require adding a bool to the class size).
//
LLBBoxLocal bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLVector3(2.0f, 2.0f, 2.0f));
bbox2.addBBox(LLBBoxLocal(LLVector3(1.5f, 1.5f, 1.5f), LLVector3(3.0f, 3.0f, 3.0f)));
ensure_equals("Custom BBox center (4)", bbox2.getCenter(), LLVector3(2.0f, 2.0f, 2.0f));
ensure_equals("Custom BBox min (4)", bbox2.getMin(), LLVector3(1.0f, 1.0f, 1.0f));
ensure_equals("Custom BBox max (4)", bbox2.getMax(), LLVector3(3.0f, 3.0f, 3.0f));
bbox2.addBBox(LLBBoxLocal(LLVector3(-1.0f, -1.0f, -1.0f), LLVector3(0.0f, 0.0f, 0.0f)));
ensure_equals("Custom BBox center (5)", bbox2.getCenter(), LLVector3(1.0f, 1.0f, 1.0f));
ensure_equals("Custom BBox min (5)", bbox2.getMin(), LLVector3(-1.0f, -1.0f, -1.0f));
ensure_equals("Custom BBox max (5)", bbox2.getMax(), LLVector3(3.0f, 3.0f, 3.0f));
}
template<> template<>
void object::test<9>()
{
//
// test the expand() method
//
LLBBoxLocal bbox1;
bbox1.expand(0.0f);
ensure_equals("Zero-expanded Default BBox center", bbox1.getCenter(), LLVector3(0.0f, 0.0f, 0.0f));
LLBBoxLocal bbox2(LLVector3(1.0f, 2.0f, 3.0f), LLVector3(3.0f, 4.0f, 5.0f));
bbox2.expand(0.0f);
ensure_equals("Zero-expanded BBox center", bbox2.getCenter(), LLVector3(2.0f, 3.0f, 4.0f));
ensure_equals("Zero-expanded BBox min", bbox2.getMin(), LLVector3(1.0f, 2.0f, 3.0f));
ensure_equals("Zero-expanded BBox max", bbox2.getMax(), LLVector3(3.0f, 4.0f, 5.0f));
bbox2.expand(0.5f);
ensure_equals("Positive-expanded BBox center", bbox2.getCenter(), LLVector3(2.0f, 3.0f, 4.0f));
ensure_equals("Positive-expanded BBox min", bbox2.getMin(), LLVector3(0.5f, 1.5f, 2.5f));
ensure_equals("Positive-expanded BBox max", bbox2.getMax(), LLVector3(3.5f, 4.5f, 5.5f));
bbox2.expand(-1.0f);
ensure_equals("Negative-expanded BBox center", bbox2.getCenter(), LLVector3(2.0f, 3.0f, 4.0f));
ensure_equals("Negative-expanded BBox min", bbox2.getMin(), LLVector3(1.5f, 2.5f, 3.5f));
ensure_equals("Negative-expanded BBox max", bbox2.getMax(), LLVector3(2.5f, 3.5f, 4.5f));
}
}

View File

@ -0,0 +1,82 @@
/**
* @file modularmath_tut.cpp
* @author babbage
* @date 2008-09
* @brief llmodularmath tests
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "../llmodularmath.h"
#include "../test/lltut.h"
namespace tut
{
struct modularmath_data
{
};
typedef test_group<modularmath_data> modularmath_test;
typedef modularmath_test::object modularmath_object;
tut::modularmath_test modularmath_testcase("modularmath");
template<> template<>
void modularmath_object::test<1>()
{
// lhs < rhs
const U32 lhs = 0x000001;
const U32 rhs = 0xFFFFFF;
const U32 width = 24;
U32 result = LLModularMath::subtract<width>(lhs, rhs);
ensure_equals("diff(0x000001, 0xFFFFFF, 24)", result, 2);
}
template<> template<>
void modularmath_object::test<2>()
{
// lhs > rhs
const U32 lhs = 0x000002;
const U32 rhs = 0x000001;
const U32 width = 24;
U32 result = LLModularMath::subtract<width>(lhs, rhs);
ensure_equals("diff(0x000002, 0x000001, 24)", result, 1);
}
template<> template<>
void modularmath_object::test<3>()
{
// lhs == rhs
const U32 lhs = 0xABCDEF;
const U32 rhs = 0xABCDEF;
const U32 width = 24;
U32 result = LLModularMath::subtract<width>(lhs, rhs);
ensure_equals("diff(0xABCDEF, 0xABCDEF, 24)", result, 0);
}
}

View File

@ -0,0 +1,666 @@
/**
* @file llquaternion_tut.cpp
* @author Adroit
* @date 2007-03
* @brief Test cases of llquaternion.h
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "../test/lltut.h"
#include "../llquaternion.h"
#include "../v4math.h"
#include "../v3math.h"
#include "../v3dmath.h"
#include "../m4math.h"
#include "../m3math.h"
namespace tut
{
struct llquat_test
{
};
typedef test_group<llquat_test> llquat_test_t;
typedef llquat_test_t::object llquat_test_object_t;
tut::llquat_test_t tut_llquat_test("llquat");
//test case for LLQuaternion::LLQuaternion(void) fn.
template<> template<>
void llquat_test_object_t::test<1>()
{
LLQuaternion llquat;
ensure("LLQuaternion::LLQuaternion() failed", 0.f == llquat.mQ[0] &&
0.f == llquat.mQ[1] &&
0.f == llquat.mQ[2] &&
1.f == llquat.mQ[3]);
}
//test case for explicit LLQuaternion(const LLMatrix4 &mat) fn.
template<> template<>
void llquat_test_object_t::test<2>()
{
LLMatrix4 llmat;
LLVector4 vector1(2.0f, 1.0f, 3.0f, 6.0f);
LLVector4 vector2(5.0f, 6.0f, 0.0f, 1.0f);
LLVector4 vector3(2.0f, 1.0f, 2.0f, 9.0f);
LLVector4 vector4(3.0f, 8.0f, 1.0f, 5.0f);
llmat.initRows(vector1, vector2, vector3, vector4);
ensure("explicit LLQuaternion(const LLMatrix4 &mat) failed", 2.0f == llmat.mMatrix[0][0] &&
1.0f == llmat.mMatrix[0][1] &&
3.0f == llmat.mMatrix[0][2] &&
6.0f == llmat.mMatrix[0][3] &&
5.0f == llmat.mMatrix[1][0] &&
6.0f == llmat.mMatrix[1][1] &&
0.0f == llmat.mMatrix[1][2] &&
1.0f == llmat.mMatrix[1][3] &&
2.0f == llmat.mMatrix[2][0] &&
1.0f == llmat.mMatrix[2][1] &&
2.0f == llmat.mMatrix[2][2] &&
9.0f == llmat.mMatrix[2][3] &&
3.0f == llmat.mMatrix[3][0] &&
8.0f == llmat.mMatrix[3][1] &&
1.0f == llmat.mMatrix[3][2] &&
5.0f == llmat.mMatrix[3][3]);
}
template<> template<>
void llquat_test_object_t::test<3>()
{
LLMatrix3 llmat;
LLVector3 vect1(3.4028234660000000f , 234.56f, 4234.442234f);
LLVector3 vect2(741.434f, 23.00034f, 6567.223423f);
LLVector3 vect3(566.003034f, 12.98705f, 234.764423f);
llmat.setRows(vect1, vect2, vect3);
ensure("LLMatrix3::setRows fn failed.", 3.4028234660000000f == llmat.mMatrix[0][0] &&
234.56f == llmat.mMatrix[0][1] &&
4234.442234f == llmat.mMatrix[0][2] &&
741.434f == llmat.mMatrix[1][0] &&
23.00034f == llmat.mMatrix[1][1] &&
6567.223423f == llmat.mMatrix[1][2] &&
566.003034f == llmat.mMatrix[2][0] &&
12.98705f == llmat.mMatrix[2][1] &&
234.764423f == llmat.mMatrix[2][2]);
}
//test case for LLQuaternion(F32 x, F32 y, F32 z, F32 w), setQuatInit() and normQuat() fns.
template<> template<>
void llquat_test_object_t::test<4>()
{
F32 x_val = 3.0f;
F32 y_val = 2.0f;
F32 z_val = 6.0f;
F32 w_val = 1.0f;
LLQuaternion res_quat;
res_quat.setQuatInit(x_val, y_val, z_val, w_val);
res_quat.normQuat();
ensure("LLQuaternion::normQuat() fn failed",
is_approx_equal(0.42426407f, res_quat.mQ[0]) &&
is_approx_equal(0.28284273f, res_quat.mQ[1]) &&
is_approx_equal(0.84852815f, res_quat.mQ[2]) &&
is_approx_equal(0.14142136f, res_quat.mQ[3]));
x_val = 0.0f;
y_val = 0.0f;
z_val = 0.0f;
w_val = 0.0f;
res_quat.setQuatInit(x_val, y_val, z_val, w_val);
res_quat.normQuat();
ensure("LLQuaternion::normQuat() fn. failed.",
is_approx_equal(0.0f, res_quat.mQ[0]) &&
is_approx_equal(0.0f, res_quat.mQ[1]) &&
is_approx_equal(0.0f, res_quat.mQ[2]) &&
is_approx_equal(1.0f, res_quat.mQ[3]));
ensure("LLQuaternion::normQuat() fn. failed.",
is_approx_equal(0.0f, res_quat.mQ[0]) &&
is_approx_equal(0.0f, res_quat.mQ[1]) &&
is_approx_equal(0.0f, res_quat.mQ[2]) &&
is_approx_equal(1.0f, res_quat.mQ[3]));
}
//test case for conjQuat() and transQuat() fns.
template<> template<>
void llquat_test_object_t::test<5>()
{
F32 x_val = 3.0f;
F32 y_val = 2.0f;
F32 z_val = 6.0f;
F32 w_val = 1.0f;
LLQuaternion res_quat;
LLQuaternion result, result1;
result1 = result = res_quat.setQuatInit(x_val, y_val, z_val, w_val);
result.conjQuat();
result1.transQuat();
ensure("LLQuaternion::conjQuat and LLQuaternion::transQuat failed ",
is_approx_equal(result1.mQ[0], result.mQ[0]) &&
is_approx_equal(result1.mQ[1], result.mQ[1]) &&
is_approx_equal(result1.mQ[2], result.mQ[2]));
}
//test case for dot(const LLQuaternion &a, const LLQuaternion &b) fn.
template<> template<>
void llquat_test_object_t::test<6>()
{
LLQuaternion quat1(3.0f, 2.0f, 6.0f, 0.0f), quat2(1.0f, 1.0f, 1.0f, 1.0f);
ensure("1. The two values are different", llround(12.000000f, 2) == llround(dot(quat1, quat2), 2));
LLQuaternion quat0(3.0f, 9.334f, 34.5f, 23.0f), quat(34.5f, 23.23f, 2.0f, 45.5f);
ensure("2. The two values are different", llround(1435.828807f, 2) == llround(dot(quat0, quat), 2));
}
//test case for LLQuaternion &LLQuaternion::constrain(F32 radians) fn.
template<> template<>
void llquat_test_object_t::test<7>()
{
F32 radian = 60.0f;
LLQuaternion quat(3.0f, 2.0f, 6.0f, 0.0f);
LLQuaternion quat1;
quat1 = quat.constrain(radian);
ensure("1. LLQuaternion::constrain(F32 radians) failed",
is_approx_equal_fraction(-0.423442f, quat1.mQ[0], 8) &&
is_approx_equal_fraction(-0.282295f, quat1.mQ[1], 8) &&
is_approx_equal_fraction(-0.846884f, quat1.mQ[2], 8) &&
is_approx_equal_fraction(0.154251f, quat1.mQ[3], 8));
radian = 30.0f;
LLQuaternion quat0(37.50f, 12.0f, 86.023f, 40.32f);
quat1 = quat0.constrain(radian);
ensure("2. LLQuaternion::constrain(F32 radians) failed",
is_approx_equal_fraction(37.500000f, quat1.mQ[0], 8) &&
is_approx_equal_fraction(12.0000f, quat1.mQ[1], 8) &&
is_approx_equal_fraction(86.0230f, quat1.mQ[2], 8) &&
is_approx_equal_fraction(40.320000f, quat1.mQ[3], 8));
}
template<> template<>
void llquat_test_object_t::test<8>()
{
F32 value1 = 15.0f;
LLQuaternion quat1(1.0f, 2.0f, 4.0f, 1.0f);
LLQuaternion quat2(4.0f, 3.0f, 6.5f, 9.7f);
LLQuaternion res_lerp, res_slerp, res_nlerp;
//test case for lerp(F32 t, const LLQuaternion &q) fn.
res_lerp = lerp(value1, quat1);
ensure("1. LLQuaternion lerp(F32 t, const LLQuaternion &q) failed",
is_approx_equal_fraction(0.181355f, res_lerp.mQ[0], 16) &&
is_approx_equal_fraction(0.362711f, res_lerp.mQ[1], 16) &&
is_approx_equal_fraction(0.725423f, res_lerp.mQ[2], 16) &&
is_approx_equal_fraction(0.556158f, res_lerp.mQ[3], 16));
//test case for lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q) fn.
res_lerp = lerp(value1, quat1, quat2);
ensure("2. LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q) failed",
is_approx_equal_fraction(0.314306f, res_lerp.mQ[0], 16) &&
is_approx_equal_fraction(0.116156f, res_lerp.mQ[1], 16) &&
is_approx_equal_fraction(0.283559f, res_lerp.mQ[2], 16) &&
is_approx_equal_fraction(0.898506f, res_lerp.mQ[3], 16));
//test case for slerp( F32 u, const LLQuaternion &a, const LLQuaternion &b ) fn.
res_slerp = slerp(value1, quat1, quat2);
ensure("3. LLQuaternion slerp( F32 u, const LLQuaternion &a, const LLQuaternion &b) failed",
is_approx_equal_fraction(46.000f, res_slerp.mQ[0], 16) &&
is_approx_equal_fraction(17.00f, res_slerp.mQ[1], 16) &&
is_approx_equal_fraction(41.5f, res_slerp.mQ[2], 16) &&
is_approx_equal_fraction(131.5f, res_slerp.mQ[3], 16));
//test case for nlerp(F32 t, const LLQuaternion &a, const LLQuaternion &b) fn.
res_nlerp = nlerp(value1, quat1, quat2);
ensure("4. LLQuaternion nlerp(F32 t, const LLQuaternion &a, const LLQuaternion &b) failed",
is_approx_equal_fraction(0.314306f, res_nlerp.mQ[0], 16) &&
is_approx_equal_fraction(0.116157f, res_nlerp.mQ[1], 16) &&
is_approx_equal_fraction(0.283559f, res_nlerp.mQ[2], 16) &&
is_approx_equal_fraction(0.898506f, res_nlerp.mQ[3], 16));
//test case for nlerp(F32 t, const LLQuaternion &q) fn.
res_slerp = slerp(value1, quat1);
ensure("5. LLQuaternion slerp(F32 t, const LLQuaternion &q) failed",
is_approx_equal_fraction(1.0f, res_slerp.mQ[0], 16) &&
is_approx_equal_fraction(2.0f, res_slerp.mQ[1], 16) &&
is_approx_equal_fraction(4.0000f, res_slerp.mQ[2], 16) &&
is_approx_equal_fraction(1.000f, res_slerp.mQ[3], 16));
LLQuaternion quat3(2.0f, 1.0f, 5.5f, 10.5f);
LLQuaternion res_nlerp1;
value1 = 100.0f;
res_nlerp1 = nlerp(value1, quat3);
ensure("6. LLQuaternion nlerp(F32 t, const LLQuaternion &q) failed",
is_approx_equal_fraction(0.268245f, res_nlerp1.mQ[0], 16) && is_approx_equal_fraction(0.134122f, res_nlerp1.mQ[1], 2) &&
is_approx_equal_fraction(0.737673f, res_nlerp1.mQ[2], 16) &&
is_approx_equal_fraction(0.604892f, res_nlerp1.mQ[3], 16));
//test case for lerp(F32 t, const LLQuaternion &q) fn.
res_lerp = lerp(value1, quat2);
ensure("7. LLQuaternion lerp(F32 t, const LLQuaternion &q) failed",
is_approx_equal_fraction(0.404867f, res_lerp.mQ[0], 16) &&
is_approx_equal_fraction(0.303650f, res_lerp.mQ[1], 16) &&
is_approx_equal_fraction(0.657909f, res_lerp.mQ[2], 16) &&
is_approx_equal_fraction(0.557704f, res_lerp.mQ[3], 16));
}
template<> template<>
void llquat_test_object_t::test<9>()
{
//test case for LLQuaternion operator*(const LLQuaternion &a, const LLQuaternion &b) fn
LLQuaternion quat1(1.0f, 2.5f, 3.5f, 5.5f);
LLQuaternion quat2(4.0f, 3.0f, 5.0f, 1.0f);
LLQuaternion result = quat1 * quat2;
ensure("1. LLQuaternion Operator* failed", (21.0f == result.mQ[0]) &&
(10.0f == result.mQ[1]) &&
(38.0f == result.mQ[2]) &&
(-23.5f == result.mQ[3]));
LLQuaternion quat3(2341.340f, 2352.345f, 233.25f, 7645.5f);
LLQuaternion quat4(674.067f, 893.0897f, 578.0f, 231.0f);
result = quat3 * quat4;
ensure("2. LLQuaternion Operator* failed", (4543086.5f == result.mQ[0]) &&
(8567578.0f == result.mQ[1]) &&
(3967591.25f == result.mQ[2]) &&
is_approx_equal(-2047783.25f, result.mQ[3]));
//inline LLQuaternion operator+(const LLQuaternion &a, const LLQuaternion &b)fn.
result = quat1 + quat2;
ensure("3. LLQuaternion operator+ failed", (5.0f == result.mQ[0]) &&
(5.5f == result.mQ[1]) &&
(8.5f == result.mQ[2]) &&
(6.5f == result.mQ[3]));
result = quat3 + quat4;
ensure(
"4. LLQuaternion operator+ failed",
is_approx_equal(3015.407227f, result.mQ[0]) &&
is_approx_equal(3245.434570f, result.mQ[1]) &&
(811.25f == result.mQ[2]) &&
(7876.5f == result.mQ[3]));
//inline LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b) fn
result = quat1 - quat2;
ensure(
"5. LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b) failed",
(-3.0f == result.mQ[0]) &&
(-0.5f == result.mQ[1]) &&
(-1.5f == result.mQ[2]) &&
(4.5f == result.mQ[3]));
result = quat3 - quat4;
ensure(
"6. LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b) failed",
is_approx_equal(1667.273071f, result.mQ[0]) &&
is_approx_equal(1459.255249f, result.mQ[1]) &&
(-344.75f == result.mQ[2]) &&
(7414.50f == result.mQ[3]));
}
//test case for LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot) fn.
template<> template<>
void llquat_test_object_t::test<10>()
{
LLVector4 vect(12.0f, 5.0f, 60.0f, 75.1f);
LLQuaternion quat(2323.034f, 23.5f, 673.23f, 57667.5f);
LLVector4 result = vect * quat;
ensure(
"1. LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot) failed",
is_approx_equal(39928406016.0f, result.mV[0]) &&
// gcc on x86 actually gives us more precision than we were expecting, verified with -ffloat-store - we forgive this
(1457802240.0f >= result.mV[1]) && // gcc+x86+linux
(1457800960.0f <= result.mV[1]) && // elsewhere
is_approx_equal(200580612096.0f, result.mV[2]) &&
(75.099998f == result.mV[3]));
LLVector4 vect1(22.0f, 45.0f, 40.0f, 78.1f);
LLQuaternion quat1(2.034f, 45.5f, 37.23f, 7.5f);
result = vect1 * quat1;
ensure(
"2. LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot) failed",
is_approx_equal(-58153.5390f, result.mV[0]) &&
(183787.8125f == result.mV[1]) &&
(116864.164063f == result.mV[2]) &&
(78.099998f == result.mV[3]));
}
//test case for LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot) fn.
template<> template<>
void llquat_test_object_t::test<11>()
{
LLVector3 vect(12.0f, 5.0f, 60.0f);
LLQuaternion quat(23.5f, 6.5f, 3.23f, 56.5f);
LLVector3 result = vect * quat;
ensure(
"1. LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot) failed",
is_approx_equal(97182.953125f,result.mV[0]) &&
is_approx_equal(-135405.640625f, result.mV[1]) &&
is_approx_equal(162986.140f, result.mV[2]));
LLVector3 vect1(5.0f, 40.0f, 78.1f);
LLQuaternion quat1(2.034f, 45.5f, 37.23f, 7.5f);
result = vect1 * quat1;
ensure(
"2. LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot) failed",
is_approx_equal(33217.703f, result.mV[0]) &&
is_approx_equal(295383.8125f, result.mV[1]) &&
is_approx_equal(84718.140f, result.mV[2]));
}
//test case for LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot) fn.
template<> template<>
void llquat_test_object_t::test<12>()
{
LLVector3d vect(-2.0f, 5.0f, -6.0f);
LLQuaternion quat(-3.5f, 4.5f, 3.5f, 6.5f);
LLVector3d result = vect * quat;
ensure(
"1. LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot) failed ",
(-633.0f == result.mdV[0]) &&
(-300.0f == result.mdV[1]) &&
(-36.0f == result.mdV[2]));
LLVector3d vect1(5.0f, -4.5f, 8.21f);
LLQuaternion quat1(2.0f, 4.5f, -7.2f, 9.5f);
result = vect1 * quat1;
ensure(
"2. LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot) failed",
is_approx_equal_fraction(-120.29f, (F32) result.mdV[0], 8) &&
is_approx_equal_fraction(-1683.958f, (F32) result.mdV[1], 8) &&
is_approx_equal_fraction(516.56f, (F32) result.mdV[2], 8));
LLVector3d vect2(2.0f, 3.5f, 1.1f);
LLQuaternion quat2(1.0f, 4.0f, 2.0f, 5.0f);
result = vect2 * quat2;
ensure(
"3. LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot) failed",
is_approx_equal_fraction(18.400001f, (F32) result.mdV[0], 8) &&
is_approx_equal_fraction(188.6f, (F32) result.mdV[1], 8) &&
is_approx_equal_fraction(32.20f, (F32) result.mdV[2], 8));
}
//test case for inline LLQuaternion operator-(const LLQuaternion &a) fn.
template<> template<>
void llquat_test_object_t::test<13>()
{
LLQuaternion quat(23.5f, 34.5f, 16723.4f, 324.7f);
LLQuaternion result = -quat;
ensure(
"1. LLQuaternion operator-(const LLQuaternion &a) failed",
(-23.5f == result.mQ[0]) &&
(-34.5f == result.mQ[1]) &&
(-16723.4f == result.mQ[2]) &&
(-324.7f == result.mQ[3]));
LLQuaternion quat1(-3.5f, -34.5f, -16.4f, -154.7f);
result = -quat1;
ensure(
"2. LLQuaternion operator-(const LLQuaternion &a) failed.",
(3.5f == result.mQ[0]) &&
(34.5f == result.mQ[1]) &&
(16.4f == result.mQ[2]) &&
(154.7f == result.mQ[3]));
}
//test case for inline LLQuaternion operator*(F32 a, const LLQuaternion &q) and
//inline LLQuaternion operator*(F32 a, const LLQuaternion &q) fns.
template<> template<>
void llquat_test_object_t::test<14>()
{
LLQuaternion quat_value(9.0f, 8.0f, 7.0f, 6.0f);
F32 a =3.5f;
LLQuaternion result = a * quat_value;
LLQuaternion result1 = quat_value * a;
ensure(
"1. LLQuaternion operator* failed",
(result.mQ[0] == result1.mQ[0]) &&
(result.mQ[1] == result1.mQ[1]) &&
(result.mQ[2] == result1.mQ[2]) &&
(result.mQ[3] == result1.mQ[3]));
LLQuaternion quat_val(9454.0f, 43568.3450f, 456343247.0343f, 2346.03434f);
a =-3324.3445f;
result = a * quat_val;
result1 = quat_val * a;
ensure(
"2. LLQuaternion operator* failed",
(result.mQ[0] == result1.mQ[0]) &&
(result.mQ[1] == result1.mQ[1]) &&
(result.mQ[2] == result1.mQ[2]) &&
(result.mQ[3] == result1.mQ[3]));
}
template<> template<>
void llquat_test_object_t::test<15>()
{
// test cases for inline LLQuaternion operator~(const LLQuaternion &a)
LLQuaternion quat_val(2323.634f, -43535.4f, 3455.88f, -32232.45f);
LLQuaternion result = ~quat_val;
ensure(
"1. LLQuaternion operator~(const LLQuaternion &a) failed ",
(-2323.634f == result.mQ[0]) &&
(43535.4f == result.mQ[1]) &&
(-3455.88f == result.mQ[2]) &&
(-32232.45f == result.mQ[3]));
//test case for inline bool LLQuaternion::operator==(const LLQuaternion &b) const
LLQuaternion quat_val1(2323.634f, -43535.4f, 3455.88f, -32232.45f);
LLQuaternion quat_val2(2323.634f, -43535.4f, 3455.88f, -32232.45f);
ensure(
"2. LLQuaternion::operator==(const LLQuaternion &b) failed",
quat_val1 == quat_val2);
}
template<> template<>
void llquat_test_object_t::test<16>()
{
//test case for inline bool LLQuaternion::operator!=(const LLQuaternion &b) const
LLQuaternion quat_val1(2323.634f, -43535.4f, 3455.88f, -32232.45f);
LLQuaternion quat_val2(0, -43535.4f, 3455.88f, -32232.45f);
ensure("LLQuaternion::operator!=(const LLQuaternion &b) failed", quat_val1 != quat_val2);
}
template<> template<>
void llquat_test_object_t::test<17>()
{
//test case for LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order)
F32 x = 2.0f;
F32 y = 1.0f;
F32 z = 3.0f;
LLQuaternion result = mayaQ(x, y, z, LLQuaternion::XYZ);
ensure(
"1. LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for XYZ",
is_approx_equal_fraction(0.0172174f, result.mQ[0], 16) &&
is_approx_equal_fraction(0.009179f, result.mQ[1], 16) &&
is_approx_equal_fraction(0.026020f, result.mQ[2], 16) &&
is_approx_equal_fraction(0.999471f, result.mQ[3], 16));
LLQuaternion result1 = mayaQ(x, y, z, LLQuaternion::YZX);
ensure(
"2. LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for XYZ",
is_approx_equal_fraction(0.017217f, result1.mQ[0], 16) &&
is_approx_equal_fraction(0.008265f, result1.mQ[1], 16) &&
is_approx_equal_fraction(0.026324f, result1.mQ[2], 16) &&
is_approx_equal_fraction(0.999471f, result1.mQ[3], 16));
LLQuaternion result2 = mayaQ(x, y, z, LLQuaternion::ZXY);
ensure(
"3. LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for ZXY",
is_approx_equal_fraction(0.017674f, result2.mQ[0], 16) &&
is_approx_equal_fraction(0.008265f, result2.mQ[1], 16) &&
is_approx_equal_fraction(0.026020f, result2.mQ[2], 16) &&
is_approx_equal_fraction(0.999471f, result2.mQ[3], 16));
LLQuaternion result3 = mayaQ(x, y, z, LLQuaternion::XZY);
ensure(
"4. TLLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for XZY",
is_approx_equal_fraction(0.017674f, result3.mQ[0], 16) &&
is_approx_equal_fraction(0.009179f, result3.mQ[1], 16) &&
is_approx_equal_fraction(0.026020f, result3.mQ[2], 16) &&
is_approx_equal_fraction(0.999463f, result3.mQ[3], 16));
LLQuaternion result4 = mayaQ(x, y, z, LLQuaternion::YXZ);
ensure(
"5. LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for YXZ",
is_approx_equal_fraction(0.017217f, result4.mQ[0], 16) &&
is_approx_equal_fraction(0.009179f, result4.mQ[1], 16) &&
is_approx_equal_fraction(0.026324f, result4.mQ[2], 16) &&
is_approx_equal_fraction(0.999463f, result4.mQ[3], 16));
LLQuaternion result5 = mayaQ(x, y, z, LLQuaternion::ZYX);
ensure(
"6. LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for ZYX",
is_approx_equal_fraction(0.017674f, result5.mQ[0], 16) &&
is_approx_equal_fraction(0.008265f, result5.mQ[1], 16) &&
is_approx_equal_fraction(0.026324f, result5.mQ[2], 16) &&
is_approx_equal_fraction(0.999463f, result5.mQ[3], 16));
}
template<> template<>
void llquat_test_object_t::test<18>()
{
// test case for friend std::ostream& operator<<(std::ostream &s, const LLQuaternion &a) fn
LLQuaternion a(1.0f, 1.0f, 1.0f, 1.0f);
std::ostringstream result_value;
result_value << a;
ensure_equals("1. Operator << failed", result_value.str(), "{ 1, 1, 1, 1 }");
LLQuaternion b(-31.034f, 231.2340f, 3451.344320f, -341.0f);
std::ostringstream result_value1;
result_value1 << b;
ensure_equals("2. Operator << failed", result_value1.str(), "{ -31.034, 231.234, 3451.34, -341 }");
LLQuaternion c(1.0f, 2.2f, 3.3f, 4.4f);
result_value << c;
ensure_equals("3. Operator << failed", result_value.str(), "{ 1, 1, 1, 1 }{ 1, 2.2, 3.3, 4.4 }");
}
template<> template<>
void llquat_test_object_t::test<19>()
{
//test case for const char *OrderToString( const LLQuaternion::Order order ) fn
const char* result = OrderToString(LLQuaternion::XYZ);
ensure("1. OrderToString failed for XYZ", (0 == strcmp("XYZ", result)));
result = OrderToString(LLQuaternion::YZX);
ensure("2. OrderToString failed for YZX", (0 == strcmp("YZX", result)));
result = OrderToString(LLQuaternion::ZXY);
ensure(
"3. OrderToString failed for ZXY",
(0 == strcmp("ZXY", result)) &&
(0 != strcmp("XYZ", result)) &&
(0 != strcmp("YXZ", result)) &&
(0 != strcmp("ZYX", result)) &&
(0 != strcmp("XYZ", result)));
result = OrderToString(LLQuaternion::XZY);
ensure("4. OrderToString failed for XZY", (0 == strcmp("XZY", result)));
result = OrderToString(LLQuaternion::ZYX);
ensure("5. OrderToString failed for ZYX", (0 == strcmp("ZYX", result)));
result = OrderToString(LLQuaternion::YXZ);
ensure("6.OrderToString failed for YXZ", (0 == strcmp("YXZ", result)));
}
template<> template<>
void llquat_test_object_t::test<20>()
{
//test case for LLQuaternion::Order StringToOrder( const char *str ) fn
int result = StringToOrder("XYZ");
ensure("1. LLQuaternion::Order StringToOrder(const char *str ) failed for XYZ", 0 == result);
result = StringToOrder("YZX");
ensure("2. LLQuaternion::Order StringToOrder(const char *str) failed for YZX", 1 == result);
result = StringToOrder("ZXY");
ensure("3. LLQuaternion::Order StringToOrder(const char *str) failed for ZXY", 2 == result);
result = StringToOrder("XZY");
ensure("4. LLQuaternion::Order StringToOrder(const char *str) failed for XZY", 3 == result);
result = StringToOrder("YXZ");
ensure("5. LLQuaternion::Order StringToOrder(const char *str) failed for YXZ", 4 == result);
result = StringToOrder("ZYX");
ensure("6. LLQuaternion::Order StringToOrder(const char *str) failed for ZYX", 5 == result);
}
template<> template<>
void llquat_test_object_t::test<21>()
{
//void LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) const fn
F32 angle_value = 90.0f;
LLVector3 vect(12.0f, 4.0f, 1.0f);
LLQuaternion llquat(angle_value, vect);
llquat.getAngleAxis(&angle_value, vect);
ensure(
"LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) failed",
is_approx_equal_fraction(2.035406f, angle_value, 16) &&
is_approx_equal_fraction(0.315244f, vect.mV[1], 16) &&
is_approx_equal_fraction(0.078811f, vect.mV[2], 16) &&
is_approx_equal_fraction(0.945733f, vect.mV[0], 16));
}
template<> template<>
void llquat_test_object_t::test<22>()
{
//test case for void LLQuaternion::getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) const fn
F32 roll = -12.0f;
F32 pitch = -22.43f;
F32 yaw = 11.0f;
LLQuaternion llquat;
llquat.getEulerAngles(&roll, &pitch, &yaw);
ensure(
"LLQuaternion::getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) failed",
is_approx_equal(0.000f, llquat.mQ[0]) &&
is_approx_equal(0.000f, llquat.mQ[1]) &&
is_approx_equal(0.000f, llquat.mQ[2]) &&
is_approx_equal(1.000f, llquat.mQ[3]));
}
}

View File

@ -0,0 +1,532 @@
/**
* @file llrect_tut.cpp
* @author Martin Reddy
* @date 2009-06-25
* @brief Test for llrect.cpp.
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
* Copyright (c) 2009-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "../test/lltut.h"
#include "../llrect.h"
namespace tut
{
struct LLRectData
{
};
typedef test_group<LLRectData> factory;
typedef factory::object object;
}
namespace
{
tut::factory llrect_test_factory("LLRect");
}
namespace tut
{
template<> template<>
void object::test<1>()
{
//
// test the LLRect default constructor
//
LLSD zero;
zero.append(0); zero.append(0); zero.append(0); zero.append(0);
// default constructor
LLRect rect1;
ensure_equals("Empty rect", rect1.getValue(), zero);
ensure_equals("Empty rect left", rect1.mLeft, 0);
ensure_equals("Empty rect top", rect1.mTop, 0);
ensure_equals("Empty rect right", rect1.mRight, 0);
ensure_equals("Empty rect bottom", rect1.mBottom, 0);
ensure_equals("Empty rect width", rect1.getWidth(), 0);
ensure_equals("Empty rect height", rect1.getHeight(), 0);
ensure_equals("Empty rect centerx", rect1.getCenterX(), 0);
ensure_equals("Empty rect centery", rect1.getCenterY(), 0);
}
template<> template<>
void object::test<2>()
{
//
// test the LLRectf default constructor
//
LLSD zerof;
zerof.append(0.0f); zerof.append(0.0f); zerof.append(0.0f); zerof.append(0.0f);
LLRectf rect2;
ensure_equals("Empty rectf", rect2.getValue(), zerof);
ensure_equals("Empty rectf left", rect2.mLeft, 0.0f);
ensure_equals("Empty rectf top", rect2.mTop, 0.0f);
ensure_equals("Empty rectf right", rect2.mRight, 0.0f);
ensure_equals("Empty rectf bottom", rect2.mBottom, 0.0f);
ensure_equals("Empty rectf width", rect2.getWidth(), 0.0f);
ensure_equals("Empty rectf height", rect2.getHeight(), 0.0f);
ensure_equals("Empty rectf centerx", rect2.getCenterX(), 0.0f);
ensure_equals("Empty rectf centery", rect2.getCenterY(), 0.0f);
}
template<> template<>
void object::test<3>()
{
//
// test the LLRect constructor from another LLRect
//
LLRect rect3(LLRect(1, 6, 7, 2));
ensure_equals("Default rect left", rect3.mLeft, 1);
ensure_equals("Default rect top", rect3.mTop, 6);
ensure_equals("Default rect right", rect3.mRight, 7);
ensure_equals("Default rect bottom", rect3.mBottom, 2);
ensure_equals("Default rect width", rect3.getWidth(), 6);
ensure_equals("Default rect height", rect3.getHeight(), 4);
ensure_equals("Default rect centerx", rect3.getCenterX(), 4);
ensure_equals("Default rect centery", rect3.getCenterY(), 4);
}
template<> template<>
void object::test<4>()
{
//
// test the LLRectf four-float constructor
//
LLRectf rect4(1.0f, 5.0f, 6.0f, 2.0f);
ensure_equals("Default rectf left", rect4.mLeft, 1.0f);
ensure_equals("Default rectf top", rect4.mTop, 5.0f);
ensure_equals("Default rectf right", rect4.mRight, 6.0f);
ensure_equals("Default rectf bottom", rect4.mBottom, 2.0f);
ensure_equals("Default rectf width", rect4.getWidth(), 5.0f);
ensure_equals("Default rectf height", rect4.getHeight(), 3.0f);
ensure_equals("Default rectf centerx", rect4.getCenterX(), 3.5f);
ensure_equals("Default rectf centery", rect4.getCenterY(), 3.5f);
}
template<> template<>
void object::test<5>()
{
//
// test the LLRectf LLSD constructor
//
LLSD array;
array.append(-1.0f); array.append(0.0f); array.append(0.0f); array.append(-1.0f);
LLRectf rect5(array);
ensure_equals("LLSD rectf left", rect5.mLeft, -1.0f);
ensure_equals("LLSD rectf top", rect5.mTop, 0.0f);
ensure_equals("LLSD rectf right", rect5.mRight, 0.0f);
ensure_equals("LLSD rectf bottom", rect5.mBottom, -1.0f);
ensure_equals("LLSD rectf width", rect5.getWidth(), 1.0f);
ensure_equals("LLSD rectf height", rect5.getHeight(), 1.0f);
ensure_equals("LLSD rectf centerx", rect5.getCenterX(), -0.5f);
ensure_equals("LLSD rectf centery", rect5.getCenterY(), -0.5f);
}
template<> template<>
void object::test<6>()
{
//
// test directly setting the member variables for dimensions
//
LLRectf rectf;
rectf.mLeft = -1.0f;
rectf.mTop = 1.0f;
rectf.mRight = 1.0f;
rectf.mBottom = -1.0f;
ensure_equals("Member-set rectf left", rectf.mLeft, -1.0f);
ensure_equals("Member-set rectf top", rectf.mTop, 1.0f);
ensure_equals("Member-set rectf right", rectf.mRight, 1.0f);
ensure_equals("Member-set rectf bottom", rectf.mBottom, -1.0f);
ensure_equals("Member-set rectf width", rectf.getWidth(), 2.0f);
ensure_equals("Member-set rectf height", rectf.getHeight(), 2.0f);
ensure_equals("Member-set rectf centerx", rectf.getCenterX(), 0.0f);
ensure_equals("Member-set rectf centery", rectf.getCenterY(), 0.0f);
}
template<> template<>
void object::test<7>()
{
//
// test the setValue() method
//
LLRectf rectf;
LLSD array;
array.append(-1.0f); array.append(0.0f); array.append(0.0f); array.append(-1.0f);
rectf.setValue(array);
ensure_equals("setValue() rectf left", rectf.mLeft, -1.0f);
ensure_equals("setValue() rectf top", rectf.mTop, 0.0f);
ensure_equals("setValue() rectf right", rectf.mRight, 0.0f);
ensure_equals("setValue() rectf bottom", rectf.mBottom, -1.0f);
ensure_equals("setValue() rectf width", rectf.getWidth(), 1.0f);
ensure_equals("setValue() rectf height", rectf.getHeight(), 1.0f);
ensure_equals("setValue() rectf centerx", rectf.getCenterX(), -0.5f);
ensure_equals("setValue() rectf centery", rectf.getCenterY(), -0.5f);
}
template<> template<>
void object::test<8>()
{
//
// test the set() method
//
LLRect rect;
rect.set(10, 90, 70, 10);
ensure_equals("set() rectf left", rect.mLeft, 10);
ensure_equals("set() rectf top", rect.mTop, 90);
ensure_equals("set() rectf right", rect.mRight, 70);
ensure_equals("set() rectf bottom", rect.mBottom, 10);
ensure_equals("set() rectf width", rect.getWidth(), 60);
ensure_equals("set() rectf height", rect.getHeight(), 80);
ensure_equals("set() rectf centerx", rect.getCenterX(), 40);
ensure_equals("set() rectf centery", rect.getCenterY(), 50);
}
template<> template<>
void object::test<9>()
{
//
// test the setOriginAndSize() method
//
LLRectf rectf;
rectf.setOriginAndSize(0.0f, 0.0f, 2.0f, 1.0f);
ensure_equals("setOriginAndSize() rectf left", rectf.mLeft, 0.0f);
ensure_equals("setOriginAndSize() rectf top", rectf.mTop, 1.0f);
ensure_equals("setOriginAndSize() rectf right", rectf.mRight, 2.0f);
ensure_equals("setOriginAndSize() rectf bottom", rectf.mBottom, 0.0f);
ensure_equals("setOriginAndSize() rectf width", rectf.getWidth(), 2.0f);
ensure_equals("setOriginAndSize() rectf height", rectf.getHeight(), 1.0f);
ensure_equals("setOriginAndSize() rectf centerx", rectf.getCenterX(), 1.0f);
ensure_equals("setOriginAndSize() rectf centery", rectf.getCenterY(), 0.5f);
}
template<> template<>
void object::test<10>()
{
//
// test the setLeftTopAndSize() method
//
LLRectf rectf;
rectf.setLeftTopAndSize(0.0f, 0.0f, 2.0f, 1.0f);
ensure_equals("setLeftTopAndSize() rectf left", rectf.mLeft, 0.0f);
ensure_equals("setLeftTopAndSize() rectf top", rectf.mTop, 0.0f);
ensure_equals("setLeftTopAndSize() rectf right", rectf.mRight, 2.0f);
ensure_equals("setLeftTopAndSize() rectf bottom", rectf.mBottom, -1.0f);
ensure_equals("setLeftTopAndSize() rectf width", rectf.getWidth(), 2.0f);
ensure_equals("setLeftTopAndSize() rectf height", rectf.getHeight(), 1.0f);
ensure_equals("setLeftTopAndSize() rectf centerx", rectf.getCenterX(), 1.0f);
ensure_equals("setLeftTopAndSize() rectf centery", rectf.getCenterY(), -0.5f);
}
template<> template<>
void object::test<11>()
{
//
// test the setCenterAndSize() method
//
LLRectf rectf;
rectf.setCenterAndSize(0.0f, 0.0f, 2.0f, 1.0f);
ensure_equals("setCenterAndSize() rectf left", rectf.mLeft, -1.0f);
ensure_equals("setCenterAndSize() rectf top", rectf.mTop, 0.5f);
ensure_equals("setCenterAndSize() rectf right", rectf.mRight, 1.0f);
ensure_equals("setCenterAndSize() rectf bottom", rectf.mBottom, -0.5f);
ensure_equals("setCenterAndSize() rectf width", rectf.getWidth(), 2.0f);
ensure_equals("setCenterAndSize() rectf height", rectf.getHeight(), 1.0f);
ensure_equals("setCenterAndSize() rectf centerx", rectf.getCenterX(), 0.0f);
ensure_equals("setCenterAndSize() rectf centery", rectf.getCenterY(), 0.0f);
}
template<> template<>
void object::test<12>()
{
//
// test the validity checking method
//
LLRectf rectf;
rectf.set(-1.0f, 1.0f, 1.0f, -1.0f);
ensure("BBox is valid", rectf.isValid());
rectf.mLeft = 2.0f;
ensure("BBox is not valid", ! rectf.isValid());
rectf.makeValid();
ensure("BBox forced valid", rectf.isValid());
rectf.set(-1.0f, -1.0f, -1.0f, -1.0f);
ensure("BBox(0,0,0,0) is valid", rectf.isValid());
}
template<> template<>
void object::test<13>()
{
//
// test the null checking methods
//
LLRectf rectf;
rectf.set(-1.0f, 1.0f, 1.0f, -1.0f);
ensure("BBox is not Null", ! rectf.isEmpty());
ensure("BBox notNull", rectf.notEmpty());
rectf.mLeft = 2.0f;
rectf.makeValid();
ensure("BBox is now Null", rectf.isEmpty());
rectf.set(-1.0f, -1.0f, -1.0f, -1.0f);
ensure("BBox(0,0,0,0) is Null", rectf.isEmpty());
}
template<> template<>
void object::test<14>()
{
//
// test the (in)equality operators
//
LLRectf rect1, rect2;
rect1.set(-1.0f, 1.0f, 1.0f, -1.0f);
rect2.set(-1.0f, 0.9f, 1.0f, -1.0f);
ensure("rect1 == rect2 (false)", ! (rect1 == rect2));
ensure("rect1 != rect2 (true)", rect1 != rect2);
ensure("rect1 == rect1 (true)", rect1 == rect1);
ensure("rect1 != rect1 (false)", ! (rect1 != rect1));
}
template<> template<>
void object::test<15>()
{
//
// test the copy constructor
//
LLRectf rect1, rect2(rect1);
ensure("rect1 == rect2 (true)", rect1 == rect2);
ensure("rect1 != rect2 (false)", ! (rect1 != rect2));
}
template<> template<>
void object::test<16>()
{
//
// test the translate() method
//
LLRectf rect1(-1.0f, 1.0f, 1.0f, -1.0f);
LLRectf rect2(rect1);
rect1.translate(0.0f, 0.0f);
ensure("translate(0, 0)", rect1 == rect2);
rect1.translate(100.0f, 100.0f);
rect1.translate(-100.0f, -100.0f);
ensure("translate(100, 100) + translate(-100, -100)", rect1 == rect2);
rect1.translate(10.0f, 0.0f);
rect2.set(9.0f, 1.0f, 11.0f, -1.0f);
ensure("translate(10, 0)", rect1 == rect2);
rect1.translate(0.0f, 10.0f);
rect2.set(9.0f, 11.0f, 11.0f, 9.0f);
ensure("translate(0, 10)", rect1 == rect2);
rect1.translate(-10.0f, -10.0f);
rect2.set(-1.0f, 1.0f, 1.0f, -1.0f);
ensure("translate(-10, -10)", rect1 == rect2);
}
template<> template<>
void object::test<17>()
{
//
// test the stretch() method
//
LLRectf rect1(-1.0f, 1.0f, 1.0f, -1.0f);
LLRectf rect2(rect1);
rect1.stretch(0.0f);
ensure("stretch(0)", rect1 == rect2);
rect1.stretch(0.0f, 0.0f);
ensure("stretch(0, 0)", rect1 == rect2);
rect1.stretch(10.0f);
rect1.stretch(-10.0f);
ensure("stretch(10) + stretch(-10)", rect1 == rect2);
rect1.stretch(2.0f, 1.0f);
rect2.set(-3.0f, 2.0f, 3.0f, -2.0f);
ensure("stretch(2, 1)", rect1 == rect2);
}
template<> template<>
void object::test<18>()
{
//
// test the unionWith() method
//
LLRectf rect1, rect2, rect3;
rect1.set(-1.0f, 1.0f, 1.0f, -1.0f);
rect2.set(-1.0f, 1.0f, 1.0f, -1.0f);
rect3 = rect1;
rect3.unionWith(rect2);
ensure_equals("union with self", rect3, rect1);
rect1.set(-1.0f, 1.0f, 1.0f, -1.0f);
rect2.set(-2.0f, 2.0f, 0.0f, 0.0f);
rect3 = rect1;
rect3.unionWith(rect2);
ensure_equals("union - overlap", rect3, LLRectf(-2.0f, 2.0f, 1.0f, -1.0f));
rect1.set(-1.0f, 1.0f, 1.0f, -1.0f);
rect2.set(5.0f, 10.0f, 10.0f, 5.0f);
rect3 = rect1;
rect3.unionWith(rect2);
ensure_equals("union - no overlap", rect3, LLRectf(-1.0f, 10.0f, 10.0f, -1.0f));
}
template<> template<>
void object::test<19>()
{
//
// test the intersectWith() methods
//
LLRectf rect1, rect2, rect3;
rect1.set(-1.0f, 1.0f, 1.0f, -1.0f);
rect2.set(-1.0f, 1.0f, 1.0f, -1.0f);
rect3 = rect1;
rect3.intersectWith(rect2);
ensure_equals("intersect with self", rect3, rect1);
rect1.set(-1.0f, 1.0f, 1.0f, -1.0f);
rect2.set(-2.0f, 2.0f, 0.0f, 0.0f);
rect3 = rect1;
rect3.intersectWith(rect2);
ensure_equals("intersect - overlap", rect3, LLRectf(-1.0f, 1.0f, 0.0f, 0.0f));
rect1.set(-1.0f, 1.0f, 1.0f, -1.0f);
rect2.set(5.0f, 10.0f, 10.0f, 5.0f);
rect3 = rect1;
rect3.intersectWith(rect2);
ensure("intersect - no overlap", rect3.isEmpty());
}
template<> template<>
void object::test<20>()
{
//
// test the pointInRect() method
//
LLRectf rect(1.0f, 3.0f, 3.0f, 1.0f);
ensure("(0,0) not in rect", rect.pointInRect(0.0f, 0.0f) == FALSE);
ensure("(2,2) in rect", rect.pointInRect(2.0f, 2.0f) == TRUE);
ensure("(1,1) in rect", rect.pointInRect(1.0f, 1.0f) == TRUE);
ensure("(3,3) not in rect", rect.pointInRect(3.0f, 3.0f) == FALSE);
ensure("(2.999,2.999) in rect", rect.pointInRect(2.999f, 2.999f) == TRUE);
ensure("(2.999,3.0) not in rect", rect.pointInRect(2.999f, 3.0f) == FALSE);
ensure("(3.0,2.999) not in rect", rect.pointInRect(3.0f, 2.999f) == FALSE);
}
template<> template<>
void object::test<21>()
{
//
// test the localPointInRect() method
//
LLRectf rect(1.0f, 3.0f, 3.0f, 1.0f);
ensure("(0,0) in local rect", rect.localPointInRect(0.0f, 0.0f) == TRUE);
ensure("(-0.0001,-0.0001) not in local rect", rect.localPointInRect(-0.0001f, -0.001f) == FALSE);
ensure("(1,1) in local rect", rect.localPointInRect(1.0f, 1.0f) == TRUE);
ensure("(2,2) not in local rect", rect.localPointInRect(2.0f, 2.0f) == FALSE);
ensure("(1.999,1.999) in local rect", rect.localPointInRect(1.999f, 1.999f) == TRUE);
ensure("(1.999,2.0) not in local rect", rect.localPointInRect(1.999f, 2.0f) == FALSE);
ensure("(2.0,1.999) not in local rect", rect.localPointInRect(2.0f, 1.999f) == FALSE);
}
template<> template<>
void object::test<22>()
{
//
// test the clampPointToRect() method
//
LLRectf rect(1.0f, 3.0f, 3.0f, 1.0f);
F32 x, y;
x = 2.0f; y = 2.0f;
rect.clampPointToRect(x, y);
ensure_equals("clamp x-coord within rect", x, 2.0f);
ensure_equals("clamp y-coord within rect", y, 2.0f);
x = -100.0f; y = 100.0f;
rect.clampPointToRect(x, y);
ensure_equals("clamp x-coord outside rect", x, 1.0f);
ensure_equals("clamp y-coord outside rect", y, 3.0f);
x = 3.0f; y = 1.0f;
rect.clampPointToRect(x, y);
ensure_equals("clamp x-coord edge rect", x, 3.0f);
ensure_equals("clamp y-coord edge rect", y, 1.0f);
}
}

View File

@ -0,0 +1,327 @@
/**
* @file m3math_test.cpp
* @author Adroit
* @date 2007-03
* @brief Test cases of m3math.h
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "../m3math.h"
#include "../v3math.h"
#include "../v4math.h"
#include "../m4math.h"
#include "../llquaternion.h"
#include "../v3dmath.h"
#include "../test/lltut.h"
namespace tut
{
struct m3math_test
{
};
typedef test_group<m3math_test> m3math_test_t;
typedef m3math_test_t::object m3math_test_object_t;
tut::m3math_test_t tut_m3math_test("m3math_test");
//test case for setIdentity() fn.
template<> template<>
void m3math_test_object_t::test<1>()
{
LLMatrix3 llmat3_obj;
llmat3_obj.setIdentity();
ensure("LLMatrix3::setIdentity failed", 1.f == llmat3_obj.mMatrix[0][0] &&
0.f == llmat3_obj.mMatrix[0][1] &&
0.f == llmat3_obj.mMatrix[0][2] &&
0.f == llmat3_obj.mMatrix[1][0] &&
1.f == llmat3_obj.mMatrix[1][1] &&
0.f == llmat3_obj.mMatrix[1][2] &&
0.f == llmat3_obj.mMatrix[2][0] &&
0.f == llmat3_obj.mMatrix[2][1] &&
1.f == llmat3_obj.mMatrix[2][2]);
}
//test case for LLMatrix3& setZero() fn.
template<> template<>
void m3math_test_object_t::test<2>()
{
LLMatrix3 llmat3_obj(30, 1, 2, 3);
llmat3_obj.setZero();
ensure("LLMatrix3::setZero failed", 0.f == llmat3_obj.setZero().mMatrix[0][0] &&
0.f == llmat3_obj.setZero().mMatrix[0][1] &&
0.f == llmat3_obj.setZero().mMatrix[0][2] &&
0.f == llmat3_obj.setZero().mMatrix[1][0] &&
0.f == llmat3_obj.setZero().mMatrix[1][1] &&
0.f == llmat3_obj.setZero().mMatrix[1][2] &&
0.f == llmat3_obj.setZero().mMatrix[2][0] &&
0.f == llmat3_obj.setZero().mMatrix[2][1] &&
0.f == llmat3_obj.setZero().mMatrix[2][2]);
}
//test case for setRows(const LLVector3 &x_axis, const LLVector3 &y_axis, const LLVector3 &z_axis) fns.
template<> template<>
void m3math_test_object_t::test<3>()
{
LLMatrix3 llmat3_obj;
LLVector3 vect1(2, 1, 4);
LLVector3 vect2(3, 5, 7);
LLVector3 vect3(6, 9, 7);
llmat3_obj.setRows(vect1, vect2, vect3);
ensure("LLVector3::setRows failed ", 2 == llmat3_obj.mMatrix[0][0] &&
1 == llmat3_obj.mMatrix[0][1] &&
4 == llmat3_obj.mMatrix[0][2] &&
3 == llmat3_obj.mMatrix[1][0] &&
5 == llmat3_obj.mMatrix[1][1] &&
7 == llmat3_obj.mMatrix[1][2] &&
6 == llmat3_obj.mMatrix[2][0] &&
9 == llmat3_obj.mMatrix[2][1] &&
7 == llmat3_obj.mMatrix[2][2]);
}
//test case for getFwdRow(), getLeftRow(), getUpRow() fns.
template<> template<>
void m3math_test_object_t::test<4>()
{
LLMatrix3 llmat3_obj;
LLVector3 vect1(2, 1, 4);
LLVector3 vect2(3, 5, 7);
LLVector3 vect3(6, 9, 7);
llmat3_obj.setRows(vect1, vect2, vect3);
ensure("LLVector3::getFwdRow failed ", vect1 == llmat3_obj.getFwdRow());
ensure("LLVector3::getLeftRow failed ", vect2 == llmat3_obj.getLeftRow());
ensure("LLVector3::getUpRow failed ", vect3 == llmat3_obj.getUpRow());
}
//test case for operator*(const LLMatrix3 &a, const LLMatrix3 &b)
template<> template<>
void m3math_test_object_t::test<5>()
{
LLMatrix3 llmat_obj1;
LLMatrix3 llmat_obj2;
LLMatrix3 llmat_obj3;
LLVector3 llvec1(1, 3, 5);
LLVector3 llvec2(3, 6, 1);
LLVector3 llvec3(4, 6, 9);
LLVector3 llvec4(1, 1, 5);
LLVector3 llvec5(3, 6, 8);
LLVector3 llvec6(8, 6, 2);
LLVector3 llvec7(0, 0, 0);
LLVector3 llvec8(0, 0, 0);
LLVector3 llvec9(0, 0, 0);
llmat_obj1.setRows(llvec1, llvec2, llvec3);
llmat_obj2.setRows(llvec4, llvec5, llvec6);
llmat_obj3.setRows(llvec7, llvec8, llvec9);
llmat_obj3 = llmat_obj1 * llmat_obj2;
ensure("LLMatrix3::operator*(const LLMatrix3 &a, const LLMatrix3 &b) failed",
50 == llmat_obj3.mMatrix[0][0] &&
49 == llmat_obj3.mMatrix[0][1] &&
39 == llmat_obj3.mMatrix[0][2] &&
29 == llmat_obj3.mMatrix[1][0] &&
45 == llmat_obj3.mMatrix[1][1] &&
65 == llmat_obj3.mMatrix[1][2] &&
94 == llmat_obj3.mMatrix[2][0] &&
94 == llmat_obj3.mMatrix[2][1] &&
86 == llmat_obj3.mMatrix[2][2]);
}
//test case for operator*(const LLVector3 &a, const LLMatrix3 &b)
template<> template<>
void m3math_test_object_t::test<6>()
{
LLMatrix3 llmat_obj1;
LLVector3 llvec(1, 3, 5);
LLVector3 res_vec(0, 0, 0);
LLVector3 llvec1(1, 3, 5);
LLVector3 llvec2(3, 6, 1);
LLVector3 llvec3(4, 6, 9);
llmat_obj1.setRows(llvec1, llvec2, llvec3);
res_vec = llvec * llmat_obj1;
LLVector3 expected_result(30, 51, 53);
ensure("LLMatrix3::operator*(const LLVector3 &a, const LLMatrix3 &b) failed", res_vec == expected_result);
}
//test case for operator*(const LLVector3d &a, const LLMatrix3 &b)
template<> template<>
void m3math_test_object_t::test<7>()
{
LLMatrix3 llmat_obj1;
LLVector3d llvec3d1;
LLVector3d llvec3d2(0, 3, 4);
LLVector3 llvec1(1, 3, 5);
LLVector3 llvec2(3, 2, 1);
LLVector3 llvec3(4, 6, 0);
llmat_obj1.setRows(llvec1, llvec2, llvec3);
llvec3d1 = llvec3d2 * llmat_obj1;
LLVector3d expected_result(25, 30, 3);
ensure("LLMatrix3::operator*(const LLVector3 &a, const LLMatrix3 &b) failed", llvec3d1 == expected_result);
}
// test case for operator==(const LLMatrix3 &a, const LLMatrix3 &b)
template<> template<>
void m3math_test_object_t::test<8>()
{
LLMatrix3 llmat_obj1;
LLMatrix3 llmat_obj2;
LLVector3 llvec1(1, 3, 5);
LLVector3 llvec2(3, 6, 1);
LLVector3 llvec3(4, 6, 9);
llmat_obj1.setRows(llvec1, llvec2, llvec3);
llmat_obj2.setRows(llvec1, llvec2, llvec3);
ensure("LLMatrix3::operator==(const LLMatrix3 &a, const LLMatrix3 &b) failed", llmat_obj1 == llmat_obj2);
llmat_obj2.setRows(llvec2, llvec2, llvec3);
ensure("LLMatrix3::operator!=(const LLMatrix3 &a, const LLMatrix3 &b) failed", llmat_obj1 != llmat_obj2);
}
//test case for quaternion() fn.
template<> template<>
void m3math_test_object_t::test<9>()
{
LLMatrix3 llmat_obj1;
LLQuaternion llmat_quat;
LLVector3 llmat1(2.0f, 1.0f, 6.0f);
LLVector3 llmat2(1.0f, 1.0f, 3.0f);
LLVector3 llmat3(1.0f, 7.0f, 5.0f);
llmat_obj1.setRows(llmat1, llmat2, llmat3);
llmat_quat = llmat_obj1.quaternion();
ensure("LLMatrix3::quaternion failed ", is_approx_equal(-0.66666669f, llmat_quat.mQ[0]) &&
is_approx_equal(-0.83333337f, llmat_quat.mQ[1]) &&
is_approx_equal(0.0f, llmat_quat.mQ[2]) &&
is_approx_equal(1.5f, llmat_quat.mQ[3]));
}
//test case for transpose() fn.
template<> template<>
void m3math_test_object_t::test<10>()
{
LLMatrix3 llmat_obj;
LLVector3 llvec1(1, 2, 3);
LLVector3 llvec2(3, 2, 1);
LLVector3 llvec3(2, 2, 2);
llmat_obj.setRows(llvec1, llvec2, llvec3);
llmat_obj.transpose();
LLVector3 resllvec1(1, 3, 2);
LLVector3 resllvec2(2, 2, 2);
LLVector3 resllvec3(3, 1, 2);
LLMatrix3 expectedllmat_obj;
expectedllmat_obj.setRows(resllvec1, resllvec2, resllvec3);
ensure("LLMatrix3::transpose failed ", llmat_obj == expectedllmat_obj);
}
//test case for determinant() fn.
template<> template<>
void m3math_test_object_t::test<11>()
{
LLMatrix3 llmat_obj1;
LLVector3 llvec1(1, 2, 3);
LLVector3 llvec2(3, 2, 1);
LLVector3 llvec3(2, 2, 2);
llmat_obj1.setRows(llvec1, llvec2, llvec3);
ensure("LLMatrix3::determinant failed ", 0.0f == llmat_obj1.determinant());
}
//test case for orthogonalize() fn.
template<> template<>
void m3math_test_object_t::test<12>()
{
LLMatrix3 llmat_obj;
LLVector3 llvec1(1, 4, 3);
LLVector3 llvec2(1, 2, 0);
LLVector3 llvec3(2, 4, 2);
llmat_obj.setRows(llvec1, llvec2, llvec3);
llmat_obj.orthogonalize();
skip("Grr, LLMatrix3::orthogonalize test is failing. Has it ever worked?");
ensure("LLMatrix3::orthogonalize failed ",
is_approx_equal(0.19611613f, llmat_obj.mMatrix[0][0]) &&
is_approx_equal(0.78446454f, llmat_obj.mMatrix[0][1]) &&
is_approx_equal(0.58834839f, llmat_obj.mMatrix[0][2]) &&
is_approx_equal(0.47628206f, llmat_obj.mMatrix[1][0]) &&
is_approx_equal(0.44826555f, llmat_obj.mMatrix[1][1]) &&
is_approx_equal(-0.75644791f, llmat_obj.mMatrix[1][2]) &&
is_approx_equal(-0.85714287f, llmat_obj.mMatrix[2][0]) &&
is_approx_equal(0.42857143f, llmat_obj.mMatrix[2][1]) &&
is_approx_equal(-0.28571427f, llmat_obj.mMatrix[2][2]));
}
//test case for adjointTranspose() fn.
template<> template<>
void m3math_test_object_t::test<13>()
{
LLMatrix3 llmat_obj;
LLVector3 llvec1(3, 2, 1);
LLVector3 llvec2(6, 2, 1);
LLVector3 llvec3(3, 6, 8);
llmat_obj.setRows(llvec1, llvec2, llvec3);
llmat_obj.adjointTranspose();
ensure("LLMatrix3::adjointTranspose failed ", 10 == llmat_obj.mMatrix[0][0] &&
-45 == llmat_obj.mMatrix[1][0] &&
30 == llmat_obj.mMatrix[2][0] &&
-10 == llmat_obj.mMatrix[0][1] &&
21 == llmat_obj.mMatrix[1][1] &&
-12 == llmat_obj.mMatrix[2][1] &&
0 == llmat_obj.mMatrix[0][2] &&
3 == llmat_obj.mMatrix[1][2] &&
-6 == llmat_obj.mMatrix[2][2]);
}
/* TBD: Need to add test cases for getEulerAngles() and setRot() functions */
}

View File

@ -0,0 +1,727 @@
/**
* @file math.cpp
* @author Phoenix
* @date 2005-09-26
* @brief Tests for the llmath library.
*
* $LicenseInfo:firstyear=2005&license=viewergpl$
*
* Copyright (c) 2005-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "../test/lltut.h"
#include "llcrc.h"
#include "llrand.h"
#include "lluuid.h"
#include "../llline.h"
#include "../llmath.h"
#include "../llsphere.h"
#include "../v3math.h"
namespace tut
{
struct math_data
{
};
typedef test_group<math_data> math_test;
typedef math_test::object math_object;
tut::math_test tm("basic_linden_math");
template<> template<>
void math_object::test<1>()
{
S32 val = 89543;
val = llabs(val);
ensure("integer absolute value 1", (89543 == val));
val = -500;
val = llabs(val);
ensure("integer absolute value 2", (500 == val));
}
template<> template<>
void math_object::test<2>()
{
F32 val = -2583.4f;
val = llabs(val);
ensure("float absolute value 1", (2583.4f == val));
val = 430903.f;
val = llabs(val);
ensure("float absolute value 2", (430903.f == val));
}
template<> template<>
void math_object::test<3>()
{
F64 val = 387439393.987329839;
val = llabs(val);
ensure("double absolute value 1", (387439393.987329839 == val));
val = -8937843.9394878;
val = llabs(val);
ensure("double absolute value 2", (8937843.9394878 == val));
}
template<> template<>
void math_object::test<4>()
{
F32 val = 430903.9f;
S32 val1 = lltrunc(val);
ensure("float truncate value 1", (430903 == val1));
val = -2303.9f;
val1 = lltrunc(val);
ensure("float truncate value 2", (-2303 == val1));
}
template<> template<>
void math_object::test<5>()
{
F64 val = 387439393.987329839 ;
S32 val1 = lltrunc(val);
ensure("float truncate value 1", (387439393 == val1));
val = -387439393.987329839;
val1 = lltrunc(val);
ensure("float truncate value 2", (-387439393 == val1));
}
template<> template<>
void math_object::test<6>()
{
F32 val = 430903.2f;
S32 val1 = llfloor(val);
ensure("float llfloor value 1", (430903 == val1));
val = -430903.9f;
val1 = llfloor(val);
ensure("float llfloor value 2", (-430904 == val1));
}
template<> template<>
void math_object::test<7>()
{
F32 val = 430903.2f;
S32 val1 = llceil(val);
ensure("float llceil value 1", (430904 == val1));
val = -430903.9f;
val1 = llceil(val);
ensure("float llceil value 2", (-430903 == val1));
}
template<> template<>
void math_object::test<8>()
{
F32 val = 430903.2f;
S32 val1 = llround(val);
ensure("float llround value 1", (430903 == val1));
val = -430903.9f;
val1 = llround(val);
ensure("float llround value 2", (-430904 == val1));
}
template<> template<>
void math_object::test<9>()
{
F32 val = 430905.2654f, nearest = 100.f;
val = llround(val, nearest);
ensure("float llround value 1", (430900 == val));
val = -430905.2654f, nearest = 10.f;
val = llround(val, nearest);
ensure("float llround value 1", (-430910 == val));
}
template<> template<>
void math_object::test<10>()
{
F64 val = 430905.2654, nearest = 100.0;
val = llround(val, nearest);
ensure("double llround value 1", (430900 == val));
val = -430905.2654, nearest = 10.0;
val = llround(val, nearest);
ensure("double llround value 1", (-430910.00000 == val));
}
template<> template<>
void math_object::test<11>()
{
const F32 F_PI = 3.1415926535897932384626433832795f;
F32 angle = 3506.f;
angle = llsimple_angle(angle);
ensure("llsimple_angle value 1", (angle <=F_PI && angle >= -F_PI));
angle = -431.f;
angle = llsimple_angle(angle);
ensure("llsimple_angle value 1", (angle <=F_PI && angle >= -F_PI));
}
}
namespace tut
{
struct uuid_data
{
LLUUID id;
};
typedef test_group<uuid_data> uuid_test;
typedef uuid_test::object uuid_object;
tut::uuid_test tu("uuid");
template<> template<>
void uuid_object::test<1>()
{
ensure("uuid null", id.isNull());
id.generate();
ensure("generate not null", id.notNull());
id.setNull();
ensure("set null", id.isNull());
}
template<> template<>
void uuid_object::test<2>()
{
id.generate();
LLUUID a(id);
ensure_equals("copy equal", id, a);
a.generate();
ensure_not_equals("generate not equal", id, a);
a = id;
ensure_equals("assignment equal", id, a);
}
template<> template<>
void uuid_object::test<3>()
{
id.generate();
LLUUID copy(id);
LLUUID mask;
mask.generate();
copy ^= mask;
ensure_not_equals("mask not equal", id, copy);
copy ^= mask;
ensure_equals("mask back", id, copy);
}
template<> template<>
void uuid_object::test<4>()
{
id.generate();
std::string id_str = id.asString();
LLUUID copy(id_str.c_str());
ensure_equals("string serialization", id, copy);
}
}
namespace tut
{
struct crc_data
{
};
typedef test_group<crc_data> crc_test;
typedef crc_test::object crc_object;
tut::crc_test tc("crc");
template<> template<>
void crc_object::test<1>()
{
/* Test buffer update and individual char update */
const char TEST_BUFFER[] = "hello &#$)$&Nd0";
LLCRC c1, c2;
c1.update((U8*)TEST_BUFFER, sizeof(TEST_BUFFER) - 1);
char* rh = (char*)TEST_BUFFER;
while(*rh != '\0')
{
c2.update(*rh);
++rh;
}
ensure_equals("crc update 1", c1.getCRC(), c2.getCRC());
}
template<> template<>
void crc_object::test<2>()
{
/* Test mixing of buffer and individual char update */
const char TEST_BUFFER1[] = "Split Buffer one $^%$%#@$";
const char TEST_BUFFER2[] = "Split Buffer two )(8723#5dsds";
LLCRC c1, c2;
c1.update((U8*)TEST_BUFFER1, sizeof(TEST_BUFFER1) - 1);
char* rh = (char*)TEST_BUFFER2;
while(*rh != '\0')
{
c1.update(*rh);
++rh;
}
rh = (char*)TEST_BUFFER1;
while(*rh != '\0')
{
c2.update(*rh);
++rh;
}
c2.update((U8*)TEST_BUFFER2, sizeof(TEST_BUFFER2) - 1);
ensure_equals("crc update 2", c1.getCRC(), c2.getCRC());
}
}
namespace tut
{
struct sphere_data
{
};
typedef test_group<sphere_data> sphere_test;
typedef sphere_test::object sphere_object;
tut::sphere_test tsphere("LLSphere");
template<> template<>
void sphere_object::test<1>()
{
// test LLSphere::contains() and ::overlaps()
S32 number_of_tests = 10;
for (S32 test = 0; test < number_of_tests; ++test)
{
LLVector3 first_center(1.f, 1.f, 1.f);
F32 first_radius = 3.f;
LLSphere first_sphere( first_center, first_radius );
F32 half_millimeter = 0.0005f;
LLVector3 direction( ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f);
direction.normalize();
F32 distance = ll_frand(first_radius - 2.f * half_millimeter);
LLVector3 second_center = first_center + distance * direction;
F32 second_radius = first_radius - distance - half_millimeter;
LLSphere second_sphere( second_center, second_radius );
ensure("first sphere should contain the second", first_sphere.contains(second_sphere));
ensure("first sphere should overlap the second", first_sphere.overlaps(second_sphere));
distance = first_radius + ll_frand(first_radius);
second_center = first_center + distance * direction;
second_radius = distance - first_radius + half_millimeter;
second_sphere.set( second_center, second_radius );
ensure("first sphere should NOT contain the second", !first_sphere.contains(second_sphere));
ensure("first sphere should overlap the second", first_sphere.overlaps(second_sphere));
distance = first_radius + ll_frand(first_radius) + half_millimeter;
second_center = first_center + distance * direction;
second_radius = distance - first_radius - half_millimeter;
second_sphere.set( second_center, second_radius );
ensure("first sphere should NOT contain the second", !first_sphere.contains(second_sphere));
ensure("first sphere should NOT overlap the second", !first_sphere.overlaps(second_sphere));
}
}
template<> template<>
void sphere_object::test<2>()
{
// test LLSphere::getBoundingSphere()
S32 number_of_tests = 100;
S32 number_of_spheres = 10;
F32 sphere_center_range = 32.f;
F32 sphere_radius_range = 5.f;
for (S32 test = 0; test < number_of_tests; ++test)
{
// gegnerate a bunch of random sphere
std::vector< LLSphere > sphere_list;
for (S32 sphere_count=0; sphere_count < number_of_spheres; ++sphere_count)
{
LLVector3 direction( ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f);
direction.normalize();
F32 distance = ll_frand(sphere_center_range);
LLVector3 center = distance * direction;
F32 radius = ll_frand(sphere_radius_range);
LLSphere sphere( center, radius );
sphere_list.push_back(sphere);
}
// compute the bounding sphere
LLSphere bounding_sphere = LLSphere::getBoundingSphere(sphere_list);
// make sure all spheres are inside the bounding sphere
{
std::vector< LLSphere >::const_iterator sphere_itr;
for (sphere_itr = sphere_list.begin(); sphere_itr != sphere_list.end(); ++sphere_itr)
{
ensure("sphere should be contained by the bounding sphere", bounding_sphere.contains(*sphere_itr));
}
}
// TODO -- improve LLSphere::getBoundingSphere() to the point where
// we can reduce the 'expansion' in the two tests below to about
// 2 mm or less
F32 expansion = 0.005f;
// move all spheres out a little bit
// and count how many are NOT contained
{
std::vector< LLVector3 > uncontained_directions;
std::vector< LLSphere >::iterator sphere_itr;
for (sphere_itr = sphere_list.begin(); sphere_itr != sphere_list.end(); ++sphere_itr)
{
LLVector3 direction = sphere_itr->getCenter() - bounding_sphere.getCenter();
direction.normalize();
sphere_itr->setCenter( sphere_itr->getCenter() + expansion * direction );
if (! bounding_sphere.contains( *sphere_itr ) )
{
uncontained_directions.push_back(direction);
}
}
ensure("when moving spheres out there should be at least two uncontained spheres",
uncontained_directions.size() > 1);
/* TODO -- when the bounding sphere algorithm is improved we can open up this test
* at the moment it occasionally fails when the sphere collection is tight and small
* (2 meters or less)
if (2 == uncontained_directions.size() )
{
// if there were only two uncontained spheres then
// the two directions should be nearly opposite
F32 dir_dot = uncontained_directions[0] * uncontained_directions[1];
ensure("two uncontained spheres should lie opposite the bounding center", dir_dot < -0.95f);
}
*/
}
// compute the new bounding sphere
bounding_sphere = LLSphere::getBoundingSphere(sphere_list);
// increase the size of all spheres a little bit
// and count how many are NOT contained
{
std::vector< LLVector3 > uncontained_directions;
std::vector< LLSphere >::iterator sphere_itr;
for (sphere_itr = sphere_list.begin(); sphere_itr != sphere_list.end(); ++sphere_itr)
{
LLVector3 direction = sphere_itr->getCenter() - bounding_sphere.getCenter();
direction.normalize();
sphere_itr->setRadius( sphere_itr->getRadius() + expansion );
if (! bounding_sphere.contains( *sphere_itr ) )
{
uncontained_directions.push_back(direction);
}
}
ensure("when boosting sphere radii there should be at least two uncontained spheres",
uncontained_directions.size() > 1);
/* TODO -- when the bounding sphere algorithm is improved we can open up this test
* at the moment it occasionally fails when the sphere collection is tight and small
* (2 meters or less)
if (2 == uncontained_directions.size() )
{
// if there were only two uncontained spheres then
// the two directions should be nearly opposite
F32 dir_dot = uncontained_directions[0] * uncontained_directions[1];
ensure("two uncontained spheres should lie opposite the bounding center", dir_dot < -0.95f);
}
*/
}
}
}
}
namespace tut
{
F32 SMALL_RADIUS = 1.0f;
F32 MEDIUM_RADIUS = 5.0f;
F32 LARGE_RADIUS = 10.0f;
struct line_data
{
};
typedef test_group<line_data> line_test;
typedef line_test::object line_object;
tut::line_test tline("LLLine");
template<> template<>
void line_object::test<1>()
{
// this is a test for LLLine::intersects(point) which returns TRUE
// if the line passes within some tolerance of point
// these tests will have some floating point error,
// so we need to specify how much error is ok
F32 allowable_relative_error = 0.00001f;
S32 number_of_tests = 100;
for (S32 test = 0; test < number_of_tests; ++test)
{
// generate some random point to be on the line
LLVector3 point_on_line( ll_frand(2.f) - 1.f,
ll_frand(2.f) - 1.f,
ll_frand(2.f) - 1.f);
point_on_line.normalize();
point_on_line *= ll_frand(LARGE_RADIUS);
// generate some random point to "intersect"
LLVector3 random_direction ( ll_frand(2.f) - 1.f,
ll_frand(2.f) - 1.f,
ll_frand(2.f) - 1.f);
random_direction.normalize();
LLVector3 random_offset( ll_frand(2.f) - 1.f,
ll_frand(2.f) - 1.f,
ll_frand(2.f) - 1.f);
random_offset.normalize();
random_offset *= ll_frand(SMALL_RADIUS);
LLVector3 point = point_on_line + MEDIUM_RADIUS * random_direction
+ random_offset;
// compute the axis of approach (a unit vector between the points)
LLVector3 axis_of_approach = point - point_on_line;
axis_of_approach.normalize();
// compute the direction of the the first line (perp to axis_of_approach)
LLVector3 first_dir( ll_frand(2.f) - 1.f,
ll_frand(2.f) - 1.f,
ll_frand(2.f) - 1.f);
first_dir.normalize();
F32 dot = first_dir * axis_of_approach;
first_dir -= dot * axis_of_approach; // subtract component parallel to axis
first_dir.normalize();
// construct the line
LLVector3 another_point_on_line = point_on_line + ll_frand(LARGE_RADIUS) * first_dir;
LLLine line(another_point_on_line, point_on_line);
// test that the intersection point is within MEDIUM_RADIUS + SMALL_RADIUS
F32 test_radius = MEDIUM_RADIUS + SMALL_RADIUS;
test_radius += (LARGE_RADIUS * allowable_relative_error);
ensure("line should pass near intersection point", line.intersects(point, test_radius));
test_radius = allowable_relative_error * (point - point_on_line).length();
ensure("line should intersect point used to define it", line.intersects(point_on_line, test_radius));
}
}
template<> template<>
void line_object::test<2>()
{
/*
These tests fail intermittently on all platforms - see DEV-16600
Commenting this out until dev has time to investigate.
// this is a test for LLLine::nearestApproach(LLLIne) method
// which computes the point on a line nearest another line
// these tests will have some floating point error,
// so we need to specify how much error is ok
// TODO -- make nearestApproach() algorithm more accurate so
// we can tighten the allowable_error. Most tests are tighter
// than one milimeter, however when doing randomized testing
// you can walk into inaccurate cases.
F32 allowable_relative_error = 0.001f;
S32 number_of_tests = 100;
for (S32 test = 0; test < number_of_tests; ++test)
{
// generate two points to be our known nearest approaches
LLVector3 some_point( ll_frand(2.f) - 1.f,
ll_frand(2.f) - 1.f,
ll_frand(2.f) - 1.f);
some_point.normalize();
some_point *= ll_frand(LARGE_RADIUS);
LLVector3 another_point( ll_frand(2.f) - 1.f,
ll_frand(2.f) - 1.f,
ll_frand(2.f) - 1.f);
another_point.normalize();
another_point *= ll_frand(LARGE_RADIUS);
// compute the axis of approach (a unit vector between the points)
LLVector3 axis_of_approach = another_point - some_point;
axis_of_approach.normalize();
// compute the direction of the the first line (perp to axis_of_approach)
LLVector3 first_dir( ll_frand(2.f) - 1.f,
ll_frand(2.f) - 1.f,
ll_frand(2.f) - 1.f);
F32 dot = first_dir * axis_of_approach;
first_dir -= dot * axis_of_approach; // subtract component parallel to axis
first_dir.normalize(); // normalize
// compute the direction of the the second line
LLVector3 second_dir( ll_frand(2.f) - 1.f,
ll_frand(2.f) - 1.f,
ll_frand(2.f) - 1.f);
dot = second_dir * axis_of_approach;
second_dir -= dot * axis_of_approach;
second_dir.normalize();
// make sure the lines aren't too parallel,
dot = fabsf(first_dir * second_dir);
if (dot > 0.99f)
{
// skip this test, we're not interested in testing
// the intractible cases
continue;
}
// construct the lines
LLVector3 first_point = some_point + ll_frand(LARGE_RADIUS) * first_dir;
LLLine first_line(first_point, some_point);
LLVector3 second_point = another_point + ll_frand(LARGE_RADIUS) * second_dir;
LLLine second_line(second_point, another_point);
// compute the points of nearest approach
LLVector3 some_computed_point = first_line.nearestApproach(second_line);
LLVector3 another_computed_point = second_line.nearestApproach(first_line);
// compute the error
F32 first_error = (some_point - some_computed_point).length();
F32 scale = llmax((some_point - another_point).length(), some_point.length());
scale = llmax(scale, another_point.length());
scale = llmax(scale, 1.f);
F32 first_relative_error = first_error / scale;
F32 second_error = (another_point - another_computed_point).length();
F32 second_relative_error = second_error / scale;
//if (first_relative_error > allowable_relative_error)
//{
// std::cout << "first_error = " << first_error
// << " first_relative_error = " << first_relative_error
// << " scale = " << scale
// << " dir_dot = " << (first_dir * second_dir)
// << std::endl;
//}
//if (second_relative_error > allowable_relative_error)
//{
// std::cout << "second_error = " << second_error
// << " second_relative_error = " << second_relative_error
// << " scale = " << scale
// << " dist = " << (some_point - another_point).length()
// << " dir_dot = " << (first_dir * second_dir)
// << std::endl;
//}
// test that the errors are small
ensure("first line should accurately compute its closest approach",
first_relative_error <= allowable_relative_error);
ensure("second line should accurately compute its closest approach",
second_relative_error <= allowable_relative_error);
}
*/
}
F32 ALMOST_PARALLEL = 0.99f;
template<> template<>
void line_object::test<3>()
{
// this is a test for LLLine::getIntersectionBetweenTwoPlanes() method
// first some known tests
LLLine xy_plane(LLVector3(0.f, 0.f, 2.f), LLVector3(0.f, 0.f, 3.f));
LLLine yz_plane(LLVector3(2.f, 0.f, 0.f), LLVector3(3.f, 0.f, 0.f));
LLLine zx_plane(LLVector3(0.f, 2.f, 0.f), LLVector3(0.f, 3.f, 0.f));
LLLine x_line;
LLLine y_line;
LLLine z_line;
bool x_success = LLLine::getIntersectionBetweenTwoPlanes(x_line, xy_plane, zx_plane);
bool y_success = LLLine::getIntersectionBetweenTwoPlanes(y_line, yz_plane, xy_plane);
bool z_success = LLLine::getIntersectionBetweenTwoPlanes(z_line, zx_plane, yz_plane);
ensure("xy and zx planes should intersect", x_success);
ensure("yz and xy planes should intersect", y_success);
ensure("zx and yz planes should intersect", z_success);
LLVector3 direction = x_line.getDirection();
ensure("x_line should be parallel to x_axis", fabs(direction.mV[VX]) == 1.f
&& 0.f == direction.mV[VY]
&& 0.f == direction.mV[VZ] );
direction = y_line.getDirection();
ensure("y_line should be parallel to y_axis", 0.f == direction.mV[VX]
&& fabs(direction.mV[VY]) == 1.f
&& 0.f == direction.mV[VZ] );
direction = z_line.getDirection();
ensure("z_line should be parallel to z_axis", 0.f == direction.mV[VX]
&& 0.f == direction.mV[VY]
&& fabs(direction.mV[VZ]) == 1.f );
// next some random tests
F32 allowable_relative_error = 0.0001f;
S32 number_of_tests = 20;
for (S32 test = 0; test < number_of_tests; ++test)
{
// generate the known line
LLVector3 some_point( ll_frand(2.f) - 1.f,
ll_frand(2.f) - 1.f,
ll_frand(2.f) - 1.f);
some_point.normalize();
some_point *= ll_frand(LARGE_RADIUS);
LLVector3 another_point( ll_frand(2.f) - 1.f,
ll_frand(2.f) - 1.f,
ll_frand(2.f) - 1.f);
another_point.normalize();
another_point *= ll_frand(LARGE_RADIUS);
LLLine known_intersection(some_point, another_point);
// compute a plane that intersect the line
LLVector3 point_on_plane( ll_frand(2.f) - 1.f,
ll_frand(2.f) - 1.f,
ll_frand(2.f) - 1.f);
point_on_plane.normalize();
point_on_plane *= ll_frand(LARGE_RADIUS);
LLVector3 plane_normal = (point_on_plane - some_point) % known_intersection.getDirection();
plane_normal.normalize();
LLLine first_plane(point_on_plane, point_on_plane + plane_normal);
// compute a different plane that intersect the line
LLVector3 point_on_different_plane( ll_frand(2.f) - 1.f,
ll_frand(2.f) - 1.f,
ll_frand(2.f) - 1.f);
point_on_different_plane.normalize();
point_on_different_plane *= ll_frand(LARGE_RADIUS);
LLVector3 different_plane_normal = (point_on_different_plane - another_point) % known_intersection.getDirection();
different_plane_normal.normalize();
LLLine second_plane(point_on_different_plane, point_on_different_plane + different_plane_normal);
if (fabs(plane_normal * different_plane_normal) > ALMOST_PARALLEL)
{
// the two planes are approximately parallel, so we won't test this case
continue;
}
LLLine measured_intersection;
bool success = LLLine::getIntersectionBetweenTwoPlanes(
measured_intersection,
first_plane,
second_plane);
ensure("plane intersection should succeed", success);
F32 dot = fabs(known_intersection.getDirection() * measured_intersection.getDirection());
ensure("measured intersection should be parallel to known intersection",
dot > ALMOST_PARALLEL);
ensure("measured intersection should pass near known point",
measured_intersection.intersects(some_point, LARGE_RADIUS * allowable_relative_error));
}
}
}

View File

@ -0,0 +1,454 @@
/**
* @file v2math_tut.cpp
* @author Adroit
* @date 2007-02
* @brief v2math test cases.
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "../test/lltut.h"
#include "../v2math.h"
namespace tut
{
struct v2math_data
{
};
typedef test_group<v2math_data> v2math_test;
typedef v2math_test::object v2math_object;
tut::v2math_test v2math_testcase("v2math");
template<> template<>
void v2math_object::test<1>()
{
LLVector2 vec2;
ensure("LLVector2:Fail to initialize ", (0.f == vec2.mV[VX] && 0.f == vec2.mV[VY]));
F32 x =2.0f, y = 3.2f ;
LLVector2 vec3(x,y);
ensure("LLVector2(F32 x, F32 y):Fail to initialize ", (x == vec3.mV[VX]) && (y == vec3.mV[VY]));
const F32 vec[2] = {3.2f, 4.5f};
LLVector2 vec4(vec);
ensure("LLVector2(const F32 *vec):Fail to initialize ", (vec[0] == vec4.mV[VX]) && (vec[1] == vec4.mV[VY]));
vec4.clearVec();
ensure("clearVec():Fail to clean the values ", (0.f == vec4.mV[VX] && 0.f == vec4.mV[VY]));
vec3.zeroVec();
ensure("zeroVec():Fail to fill the zero ", (0.f == vec3.mV[VX] && 0.f == vec3.mV[VY]));
}
template<> template<>
void v2math_object::test<2>()
{
F32 x = 123.356f, y = 2387.453f;
LLVector2 vec2,vec3;
vec2.setVec(x, y);
ensure("1:setVec: Fail ", (x == vec2.mV[VX]) && (y == vec2.mV[VY]));
vec3.setVec(vec2);
ensure("2:setVec: Fail " ,(vec2 == vec3));
vec3.zeroVec();
const F32 vec[2] = {3.24653f, 457653.4f};
vec3.setVec(vec);
ensure("3:setVec: Fail ", (vec[0] == vec3.mV[VX]) && (vec[1] == vec3.mV[VY]));
}
template<> template<>
void v2math_object::test<3>()
{
F32 x = 2.2345f, y = 3.5678f ;
LLVector2 vec2(x,y);
ensure("magVecSquared:Fail ", is_approx_equal(vec2.magVecSquared(), (x*x + y*y)));
ensure("magVec:Fail ", is_approx_equal(vec2.magVec(), fsqrtf(x*x + y*y)));
}
template<> template<>
void v2math_object::test<4>()
{
F32 x =-2.0f, y = -3.0f ;
LLVector2 vec2(x,y);
ensure_equals("abs():Fail", vec2.abs(), TRUE);
ensure("abs() x", is_approx_equal(vec2.mV[VX], 2.f));
ensure("abs() y", is_approx_equal(vec2.mV[VY], 3.f));
ensure("isNull():Fail ", FALSE == vec2.isNull()); //Returns TRUE if vector has a _very_small_ length
x =.00000001f, y = .000001001f;
vec2.setVec(x, y);
ensure("isNull(): Fail ", TRUE == vec2.isNull());
}
template<> template<>
void v2math_object::test<5>()
{
F32 x =1.f, y = 2.f;
LLVector2 vec2(x, y), vec3;
vec3 = vec3.scaleVec(vec2);
ensure("scaleVec: Fail ", vec3.mV[VX] == 0. && vec3.mV[VY] == 0.);
ensure("isExactlyZero(): Fail", TRUE == vec3.isExactlyZero());
vec3.setVec(2.f, 1.f);
vec3 = vec3.scaleVec(vec2);
ensure("scaleVec: Fail ", (2.f == vec3.mV[VX]) && (2.f == vec3.mV[VY]));
ensure("isExactlyZero():Fail", FALSE == vec3.isExactlyZero());
}
template<> template<>
void v2math_object::test<6>()
{
F32 x1 =1.f, y1 = 2.f, x2 = -2.3f, y2 = 1.11f;
F32 val1, val2;
LLVector2 vec2(x1, y1), vec3(x2, y2), vec4;
vec4 = vec2 + vec3 ;
val1 = x1+x2;
val2 = y1+y2;
ensure("1:operator+ failed",(val1 == vec4.mV[VX]) && ((val2 == vec4.mV[VY])));
vec2.clearVec();
vec3.clearVec();
x1 = -.235f, y1 = -24.32f, x2 = -2.3f, y2 = 1.f;
vec2.setVec(x1, y1);
vec3.setVec(x2, y2);
vec4 = vec2 + vec3;
val1 = x1+x2;
val2 = y1+y2;
ensure("2:operator+ failed",(val1 == vec4.mV[VX]) && ((val2 == vec4.mV[VY])));
}
template<> template<>
void v2math_object::test<7>()
{
F32 x1 =1.f, y1 = 2.f, x2 = -2.3f, y2 = 1.11f;
F32 val1, val2;
LLVector2 vec2(x1, y1), vec3(x2, y2), vec4;
vec4 = vec2 - vec3 ;
val1 = x1-x2;
val2 = y1-y2;
ensure("1:operator- failed",(val1 == vec4.mV[VX]) && ((val2 == vec4.mV[VY])));
vec2.clearVec();
vec3.clearVec();
vec4.clearVec();
x1 = -.235f, y1 = -24.32f, x2 = -2.3f, y2 = 1.f;
vec2.setVec(x1, y1);
vec3.setVec(x2, y2);
vec4 = vec2 - vec3;
val1 = x1-x2;
val2 = y1-y2;
ensure("2:operator- failed",(val1 == vec4.mV[VX]) && ((val2 == vec4.mV[VY])));
}
template<> template<>
void v2math_object::test<8>()
{
F32 x1 =1.f, y1 = 2.f, x2 = -2.3f, y2 = 1.11f;
F32 val1, val2;
LLVector2 vec2(x1, y1), vec3(x2, y2);
val1 = vec2 * vec3;
val2 = x1*x2 + y1*y2;
ensure("1:operator* failed",(val1 == val2));
vec3.clearVec();
F32 mulVal = 4.332f;
vec3 = vec2 * mulVal;
val1 = x1*mulVal;
val2 = y1*mulVal;
ensure("2:operator* failed",(val1 == vec3.mV[VX]) && (val2 == vec3.mV[VY]));
vec3.clearVec();
vec3 = mulVal * vec2;
ensure("3:operator* failed",(val1 == vec3.mV[VX]) && (val2 == vec3.mV[VY]));
}
template<> template<>
void v2math_object::test<9>()
{
F32 x1 =1.f, y1 = 2.f, div = 3.2f;
F32 val1, val2;
LLVector2 vec2(x1, y1), vec3;
vec3 = vec2 / div;
val1 = x1 / div;
val2 = y1 / div;
ensure("1:operator/ failed", is_approx_equal(val1, vec3.mV[VX]) && is_approx_equal(val2, vec3.mV[VY]));
vec3.clearVec();
x1 = -.235f, y1 = -24.32f, div = -2.2f;
vec2.setVec(x1, y1);
vec3 = vec2 / div;
val1 = x1 / div;
val2 = y1 / div;
ensure("2:operator/ failed", is_approx_equal(val1, vec3.mV[VX]) && is_approx_equal(val2, vec3.mV[VY]));
}
template<> template<>
void v2math_object::test<10>()
{
F32 x1 =1.f, y1 = 2.f, x2 = -2.3f, y2 = 1.11f;
F32 val1, val2;
LLVector2 vec2(x1, y1), vec3(x2, y2), vec4;
vec4 = vec2 % vec3;
val1 = x1*y2 - x2*y1;
val2 = y1*x2 - y2*x1;
ensure("1:operator% failed",(val1 == vec4.mV[VX]) && (val2 == vec4.mV[VY]));
vec2.clearVec();
vec3.clearVec();
vec4.clearVec();
x1 = -.235f, y1 = -24.32f, x2 = -2.3f, y2 = 1.f;
vec2.setVec(x1, y1);
vec3.setVec(x2, y2);
vec4 = vec2 % vec3;
val1 = x1*y2 - x2*y1;
val2 = y1*x2 - y2*x1;
ensure("2:operator% failed",(val1 == vec4.mV[VX]) && (val2 == vec4.mV[VY]));
}
template<> template<>
void v2math_object::test<11>()
{
F32 x1 =1.f, y1 = 2.f;
LLVector2 vec2(x1, y1), vec3(x1, y1);
ensure("1:operator== failed",(vec2 == vec3));
vec2.clearVec();
vec3.clearVec();
x1 = -.235f, y1 = -24.32f;
vec2.setVec(x1, y1);
vec3.setVec(vec2);
ensure("2:operator== failed",(vec2 == vec3));
}
template<> template<>
void v2math_object::test<12>()
{
F32 x1 = 1.f, y1 = 2.f,x2 = 2.332f, y2 = -1.23f;
LLVector2 vec2(x1, y1), vec3(x2, y2);
ensure("1:operator!= failed",(vec2 != vec3));
vec2.clearVec();
vec3.clearVec();
vec2.setVec(x1, y1);
vec3.setVec(vec2);
ensure("2:operator!= failed", (FALSE == (vec2 != vec3)));
}
template<> template<>
void v2math_object::test<13>()
{
F32 x1 = 1.f, y1 = 2.f,x2 = 2.332f, y2 = -1.23f;
F32 val1, val2;
LLVector2 vec2(x1, y1), vec3(x2, y2);
vec2 +=vec3;
val1 = x1+x2;
val2 = y1+y2;
ensure("1:operator+= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY]));
vec2.setVec(x1, y1);
vec2 -=vec3;
val1 = x1-x2;
val2 = y1-y2;
ensure("2:operator-= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY]));
vec2.clearVec();
vec3.clearVec();
x1 = -21.000466f, y1 = 2.98382f,x2 = 0.332f, y2 = -01.23f;
vec2.setVec(x1, y1);
vec3.setVec(x2, y2);
vec2 +=vec3;
val1 = x1+x2;
val2 = y1+y2;
ensure("3:operator+= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY]));
vec2.setVec(x1, y1);
vec2 -=vec3;
val1 = x1-x2;
val2 = y1-y2;
ensure("4:operator-= failed", is_approx_equal(val1, vec2.mV[VX]) && is_approx_equal(val2, vec2.mV[VY]));
}
template<> template<>
void v2math_object::test<14>()
{
F32 x1 =1.f, y1 = 2.f;
F32 val1, val2, mulVal = 4.332f;
LLVector2 vec2(x1, y1);
vec2 /=mulVal;
val1 = x1 / mulVal;
val2 = y1 / mulVal;
ensure("1:operator/= failed", is_approx_equal(val1, vec2.mV[VX]) && is_approx_equal(val2, vec2.mV[VY]));
vec2.clearVec();
x1 = .213f, y1 = -2.34f, mulVal = -.23f;
vec2.setVec(x1, y1);
vec2 /=mulVal;
val1 = x1 / mulVal;
val2 = y1 / mulVal;
ensure("2:operator/= failed", is_approx_equal(val1, vec2.mV[VX]) && is_approx_equal(val2, vec2.mV[VY]));
}
template<> template<>
void v2math_object::test<15>()
{
F32 x1 =1.f, y1 = 2.f;
F32 val1, val2, mulVal = 4.332f;
LLVector2 vec2(x1, y1);
vec2 *=mulVal;
val1 = x1*mulVal;
val2 = y1*mulVal;
ensure("1:operator*= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY]));
vec2.clearVec();
x1 = .213f, y1 = -2.34f, mulVal = -.23f;
vec2.setVec(x1, y1);
vec2 *=mulVal;
val1 = x1*mulVal;
val2 = y1*mulVal;
ensure("2:operator*= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY]));
}
template<> template<>
void v2math_object::test<16>()
{
F32 x1 =1.f, y1 = 2.f, x2 = -2.3f, y2 = 1.11f;
F32 val1, val2;
LLVector2 vec2(x1, y1), vec3(x2, y2);
vec2 %= vec3;
val1 = x1*y2 - x2*y1;
val2 = y1*x2 - y2*x1;
ensure("1:operator%= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY]));
}
template<> template<>
void v2math_object::test<17>()
{
F32 x1 =1.f, y1 = 2.f;
LLVector2 vec2(x1, y1),vec3;
vec3 = -vec2;
ensure("1:operator- failed",(-vec3 == vec2));
}
template<> template<>
void v2math_object::test<18>()
{
F32 x1 =1.f, y1 = 2.f;
std::ostringstream stream1, stream2;
LLVector2 vec2(x1, y1),vec3;
stream1 << vec2;
vec3.setVec(x1, y1);
stream2 << vec3;
ensure("1:operator << failed",(stream1.str() == stream2.str()));
}
template<> template<>
void v2math_object::test<19>()
{
F32 x1 =1.0f, y1 = 2.0f, x2 = -.32f, y2 = .2234f;
LLVector2 vec2(x1, y1),vec3(x2, y2);
ensure("1:operator < failed",(vec3 < vec2));
x1 = 1.0f, y1 = 2.0f, x2 = 1.0f, y2 = 3.2234f;
vec2.setVec(x1, y1);
vec3.setVec(x2, y2);
ensure("2:operator < failed", (FALSE == (vec3 < vec2)));
}
template<> template<>
void v2math_object::test<20>()
{
F32 x1 =1.0f, y1 = 2.0f;
LLVector2 vec2(x1, y1);
ensure("1:operator [] failed",( x1 == vec2[0]));
ensure("2:operator [] failed",( y1 == vec2[1]));
vec2.clearVec();
x1 = 23.0f, y1 = -.2361f;
vec2.setVec(x1, y1);
F32 ref1 = vec2[0];
ensure("3:operator [] failed", ( ref1 == x1));
F32 ref2 = vec2[1];
ensure("4:operator [] failed", ( ref2 == y1));
}
template<> template<>
void v2math_object::test<21>()
{
F32 x1 =1.f, y1 = 2.f, x2 = -.32f, y2 = .2234f;
F32 val1, val2;
LLVector2 vec2(x1, y1),vec3(x2, y2);
val1 = dist_vec_squared2D(vec2, vec3);
val2 = (x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2);
ensure_equals("dist_vec_squared2D values are not equal",val2, val1);
val1 = dist_vec_squared(vec2, vec3);
ensure_equals("dist_vec_squared values are not equal",val2, val1);
val1 = dist_vec(vec2, vec3);
val2 = fsqrtf((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2));
ensure_equals("dist_vec values are not equal",val2, val1);
}
template<> template<>
void v2math_object::test<22>()
{
F32 x1 =1.f, y1 = 2.f, x2 = -.32f, y2 = .2234f,fVal = .0121f;
F32 val1, val2;
LLVector2 vec2(x1, y1),vec3(x2, y2);
LLVector2 vec4 = lerp(vec2, vec3, fVal);
val1 = x1 + (x2 - x1) * fVal;
val2 = y1 + (y2 - y1) * fVal;
ensure("lerp values are not equal", ((val1 == vec4.mV[VX]) && (val2 == vec4.mV[VY])));
}
template<> template<>
void v2math_object::test<23>()
{
F32 x1 =1.f, y1 = 2.f;
F32 val1, val2;
LLVector2 vec2(x1, y1);
F32 vecMag = vec2.normVec();
F32 mag = fsqrtf(x1*x1 + y1*y1);
F32 oomag = 1.f / mag;
val1 = x1 * oomag;
val2 = y1 * oomag;
ensure("normVec failed", is_approx_equal(val1, vec2.mV[VX]) && is_approx_equal(val2, vec2.mV[VY]) && is_approx_equal(vecMag, mag));
x1 =.00000001f, y1 = 0.f;
vec2.setVec(x1, y1);
vecMag = vec2.normVec();
ensure("normVec failed should be 0.", 0. == vec2.mV[VX] && 0. == vec2.mV[VY] && vecMag == 0.);
}
}

View File

@ -0,0 +1,315 @@
/**
* @file v3color_tut.cpp
* @author Adroit
* @date 2007-03
* @brief v3color test cases.
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "../test/lltut.h"
#include "../v3color.h"
namespace tut
{
struct v3color_data
{
};
typedef test_group<v3color_data> v3color_test;
typedef v3color_test::object v3color_object;
tut::v3color_test v3color_testcase("v3color");
template<> template<>
void v3color_object::test<1>()
{
LLColor3 llcolor3;
ensure("1:LLColor3:Fail to default-initialize ", (0.0f == llcolor3.mV[0]) && (0.0f == llcolor3.mV[1]) && (0.0f == llcolor3.mV[2]));
F32 r = 2.0f, g = 3.2f, b = 1.f;
F32 v1,v2,v3;
LLColor3 llcolor3a(r,g,b);
ensure("2:LLColor3:Fail to initialize " ,(2.0f == llcolor3a.mV[0]) && (3.2f == llcolor3a.mV[1]) && (1.f == llcolor3a.mV[2]));
const F32 vec[3] = {2.0f, 3.2f,1.f};
LLColor3 llcolor3b(vec);
ensure("3:LLColor3:Fail to initialize " ,(2.0f == llcolor3b.mV[0]) && (3.2f == llcolor3b.mV[1]) && (1.f == llcolor3b.mV[2]));
const char* str = "561122";
LLColor3 llcolor3c(str);
v1 = (F32)86.0f/255.0f; // 0x56 = 86
v2 = (F32)17.0f/255.0f; // 0x11 = 17
v3 = (F32)34.0f/255.f; // 0x22 = 34
ensure("4:LLColor3:Fail to initialize " , is_approx_equal(v1, llcolor3c.mV[0]) && is_approx_equal(v2, llcolor3c.mV[1]) && is_approx_equal(v3, llcolor3c.mV[2]));
}
template<> template<>
void v3color_object::test<2>()
{
LLColor3 llcolor3;
llcolor3.setToBlack();
ensure("setToBlack:Fail to set black ", ((llcolor3.mV[0] == 0.f) && (llcolor3.mV[1] == 0.f) && (llcolor3.mV[2] == 0.f)));
llcolor3.setToWhite();
ensure("setToWhite:Fail to set white ", ((llcolor3.mV[0] == 1.f) && (llcolor3.mV[1] == 1.f) && (llcolor3.mV[2] == 1.f)));
}
template<> template<>
void v3color_object::test<3>()
{
F32 r = 2.3436212f, g = 1231.f, b = 4.7849321232f;
LLColor3 llcolor3, llcolor3a;
llcolor3.setVec(r,g,b);
ensure("1:setVec(r,g,b) Fail ",((r == llcolor3.mV[0]) && (g == llcolor3.mV[1]) && (b == llcolor3.mV[2])));
llcolor3a.setVec(llcolor3);
ensure_equals("2:setVec(LLColor3) Fail ", llcolor3,llcolor3a);
F32 vec[3] = {1.2324f, 2.45634f, .234563f};
llcolor3.setToBlack();
llcolor3.setVec(vec);
ensure("3:setVec(F32*) Fail ",((vec[0] == llcolor3.mV[0]) && (vec[1] == llcolor3.mV[1]) && (vec[2] == llcolor3.mV[2])));
}
template<> template<>
void v3color_object::test<4>()
{
F32 r = 2.3436212f, g = 1231.f, b = 4.7849321232f;
LLColor3 llcolor3(r,g,b);
ensure("magVecSquared:Fail ", is_approx_equal(llcolor3.magVecSquared(), (r*r + g*g + b*b)));
ensure("magVec:Fail ", is_approx_equal(llcolor3.magVec(), fsqrtf(r*r + g*g + b*b)));
}
template<> template<>
void v3color_object::test<5>()
{
F32 r = 2.3436212f, g = 1231.f, b = 4.7849321232f;
F32 val1, val2,val3;
LLColor3 llcolor3(r,g,b);
F32 vecMag = llcolor3.normVec();
F32 mag = fsqrtf(r*r + g*g + b*b);
F32 oomag = 1.f / mag;
val1 = r * oomag;
val2 = g * oomag;
val3 = b * oomag;
ensure("1:normVec failed ", (is_approx_equal(val1, llcolor3.mV[0]) && is_approx_equal(val2, llcolor3.mV[1]) && is_approx_equal(val3, llcolor3.mV[2]) && is_approx_equal(vecMag, mag)));
r = .000000000f, g = 0.f, b = 0.0f;
llcolor3.setVec(r,g,b);
vecMag = llcolor3.normVec();
ensure("2:normVec failed should be 0. ", (0. == llcolor3.mV[0] && 0. == llcolor3.mV[1] && 0. == llcolor3.mV[2] && vecMag == 0.));
}
template<> template<>
void v3color_object::test<6>()
{
F32 r = 2.3436212f, g = -1231.f, b = .7849321232f;
std::ostringstream stream1, stream2;
LLColor3 llcolor3(r,g,b),llcolor3a;
stream1 << llcolor3;
llcolor3a.setVec(r,g,b);
stream2 << llcolor3a;
ensure("operator << failed ", (stream1.str() == stream2.str()));
}
template<> template<>
void v3color_object::test<7>()
{
F32 r = 2.3436212f, g = -1231.f, b = .7849321232f;
LLColor3 llcolor3(r,g,b),llcolor3a;
llcolor3a = llcolor3;
ensure("operator == failed ", (llcolor3a == llcolor3));
}
template<> template<>
void v3color_object::test<8>()
{
F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f;
LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2),llcolor3b;
llcolor3b = llcolor3 + llcolor3a ;
ensure("1:operator+ failed",is_approx_equal(r1+r2 ,llcolor3b.mV[0]) && is_approx_equal(g1+g2,llcolor3b.mV[1])&& is_approx_equal(b1+b2,llcolor3b.mV[2]));
r1 = -.235f, g1 = -24.32f, b1 = 2.13f, r2 = -2.3f, g2 = 1.f, b2 = 34.21f;
llcolor3.setVec(r1,g1,b1);
llcolor3a.setVec(r2,g2,b2);
llcolor3b = llcolor3 + llcolor3a;
ensure("2:operator+ failed",is_approx_equal(r1+r2 ,llcolor3b.mV[0]) && is_approx_equal(g1+g2,llcolor3b.mV[1])&& is_approx_equal(b1+b2,llcolor3b.mV[2]));
}
template<> template<>
void v3color_object::test<9>()
{
F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f;
LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2),llcolor3b;
llcolor3b = llcolor3 - llcolor3a ;
ensure("1:operator- failed",is_approx_equal(r1-r2 ,llcolor3b.mV[0]) && is_approx_equal(g1-g2,llcolor3b.mV[1])&& is_approx_equal(b1-b2,llcolor3b.mV[2]));
r1 = -.235f, g1 = -24.32f, b1 = 2.13f, r2 = -2.3f, g2 = 1.f, b2 = 34.21f;
llcolor3.setVec(r1,g1,b1);
llcolor3a.setVec(r2,g2,b2);
llcolor3b = llcolor3 - llcolor3a;
ensure("2:operator- failed",is_approx_equal(r1-r2 ,llcolor3b.mV[0]) && is_approx_equal(g1-g2,llcolor3b.mV[1])&& is_approx_equal(b1-b2,llcolor3b.mV[2]));
}
template<> template<>
void v3color_object::test<10>()
{
F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f;
LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2),llcolor3b;
llcolor3b = llcolor3 * llcolor3a;
ensure("1:operator* failed",is_approx_equal(r1*r2 ,llcolor3b.mV[0]) && is_approx_equal(g1*g2,llcolor3b.mV[1])&& is_approx_equal(b1*b2,llcolor3b.mV[2]));
llcolor3a.setToBlack();
F32 mulVal = 4.332f;
llcolor3a = llcolor3 * mulVal;
ensure("2:operator* failed",is_approx_equal(r1*mulVal ,llcolor3a.mV[0]) && is_approx_equal(g1*mulVal,llcolor3a.mV[1])&& is_approx_equal(b1*mulVal,llcolor3a.mV[2]));
llcolor3a.setToBlack();
llcolor3a = mulVal * llcolor3;
ensure("3:operator* failed",is_approx_equal(r1*mulVal ,llcolor3a.mV[0]) && is_approx_equal(g1*mulVal,llcolor3a.mV[1])&& is_approx_equal(b1*mulVal,llcolor3a.mV[2]));
}
template<> template<>
void v3color_object::test<11>()
{
F32 r = 2.3436212f, g = 1231.f, b = 4.7849321232f;
LLColor3 llcolor3(r,g,b),llcolor3a;
llcolor3a = -llcolor3;
ensure("operator- failed ", (-llcolor3a == llcolor3));
}
template<> template<>
void v3color_object::test<12>()
{
F32 r = 2.3436212f, g = 1231.f, b = 4.7849321232f;
LLColor3 llcolor3(r,g,b),llcolor3a(r,g,b);
ensure_equals("1:operator== failed",llcolor3a,llcolor3);
r = 13.3436212f, g = -11.f, b = .7849321232f;
llcolor3.setVec(r,g,b);
llcolor3a.setVec(r,g,b);
ensure_equals("2:operator== failed",llcolor3a,llcolor3);
}
template<> template<>
void v3color_object::test<13>()
{
F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f;
LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2);
ensure("1:operator!= failed",(llcolor3 != llcolor3a));
llcolor3.setToBlack();
llcolor3a.setVec(llcolor3);
ensure("2:operator!= failed", ( FALSE == (llcolor3a != llcolor3)));
}
template<> template<>
void v3color_object::test<14>()
{
F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f;
LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2);
llcolor3a += llcolor3;
ensure("1:operator+= failed",is_approx_equal(r1+r2 ,llcolor3a.mV[0]) && is_approx_equal(g1+g2,llcolor3a.mV[1])&& is_approx_equal(b1+b2,llcolor3a.mV[2]));
llcolor3.setVec(r1,g1,b1);
llcolor3a.setVec(r2,g2,b2);
llcolor3a += llcolor3;
ensure("2:operator+= failed",is_approx_equal(r1+r2 ,llcolor3a.mV[0]) && is_approx_equal(g1+g2,llcolor3a.mV[1])&& is_approx_equal(b1+b2,llcolor3a.mV[2]));
}
template<> template<>
void v3color_object::test<15>()
{
F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f;
LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2);
llcolor3a -= llcolor3;
ensure("1:operator-= failed", is_approx_equal(r2-r1, llcolor3a.mV[0]));
ensure("2:operator-= failed", is_approx_equal(g2-g1, llcolor3a.mV[1]));
ensure("3:operator-= failed", is_approx_equal(b2-b1, llcolor3a.mV[2]));
llcolor3.setVec(r1,g1,b1);
llcolor3a.setVec(r2,g2,b2);
llcolor3a -= llcolor3;
ensure("4:operator-= failed", is_approx_equal(r2-r1, llcolor3a.mV[0]));
ensure("5:operator-= failed", is_approx_equal(g2-g1, llcolor3a.mV[1]));
ensure("6:operator-= failed", is_approx_equal(b2-b1, llcolor3a.mV[2]));
}
template<> template<>
void v3color_object::test<16>()
{
F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f;
LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2);
llcolor3a *= llcolor3;
ensure("1:operator*= failed",is_approx_equal(r1*r2 ,llcolor3a.mV[0]) && is_approx_equal(g1*g2,llcolor3a.mV[1])&& is_approx_equal(b1*b2,llcolor3a.mV[2]));
F32 mulVal = 4.332f;
llcolor3 *=mulVal;
ensure("2:operator*= failed",is_approx_equal(r1*mulVal ,llcolor3.mV[0]) && is_approx_equal(g1*mulVal,llcolor3.mV[1])&& is_approx_equal(b1*mulVal,llcolor3.mV[2]));
}
template<> template<>
void v3color_object::test<17>()
{
F32 r = 2.3436212f, g = -1231.f, b = .7849321232f;
LLColor3 llcolor3(r,g,b);
llcolor3.clamp();
ensure("1:clamp:Fail to clamp " ,(1.0f == llcolor3.mV[0]) && (0.f == llcolor3.mV[1]) && (b == llcolor3.mV[2]));
r = -2.3436212f, g = -1231.f, b = 67.7849321232f;
llcolor3.setVec(r,g,b);
llcolor3.clamp();
ensure("2:clamp:Fail to clamp " ,(0.f == llcolor3.mV[0]) && (0.f == llcolor3.mV[1]) && (1.f == llcolor3.mV[2]));
}
template<> template<>
void v3color_object::test<18>()
{
F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f;
F32 val = 2.3f,val1,val2,val3;
LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2);
val1 = r1 + (r2 - r1)* val;
val2 = g1 + (g2 - g1)* val;
val3 = b1 + (b2 - b1)* val;
LLColor3 llcolor3b = lerp(llcolor3,llcolor3a,val);
ensure("lerp failed ", ((val1 ==llcolor3b.mV[0])&& (val2 ==llcolor3b.mV[1]) && (val3 ==llcolor3b.mV[2])));
}
template<> template<>
void v3color_object::test<19>()
{
F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f;
LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2);
F32 val = distVec(llcolor3,llcolor3a);
ensure("distVec failed ", is_approx_equal(fsqrtf((r1-r2)*(r1-r2) + (g1-g2)*(g1-g2) + (b1-b2)*(b1-b2)) ,val));
F32 val1 = distVec_squared(llcolor3,llcolor3a);
ensure("distVec_squared failed ", is_approx_equal(((r1-r2)*(r1-r2) + (g1-g2)*(g1-g2) + (b1-b2)*(b1-b2)) ,val1));
}
template<> template<>
void v3color_object::test<20>()
{
F32 r1 = 1.02223f, g1 = 22222.212f, b1 = 122222.00002f;
LLColor3 llcolor31(r1,g1,b1);
LLSD sd = llcolor31.getValue();
LLColor3 llcolor32;
llcolor32.setValue(sd);
ensure_equals("LLColor3::setValue/getValue failed", llcolor31, llcolor32);
LLColor3 llcolor33(sd);
ensure_equals("LLColor3(LLSD) failed", llcolor31, llcolor33);
}
}

View File

@ -0,0 +1,532 @@
/**
* @file v3dmath_tut.cpp
* @author Adroit
* @date 2007-03
* @brief v3dmath test cases.
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llsd.h"
#include "../test/lltut.h"
#include "../llquaternion.h"
#include "../m3math.h"
#include "../v4math.h"
#include "../v3dmath.h"
#include "../v3dmath.h"
namespace tut
{
struct v3dmath_data
{
};
typedef test_group<v3dmath_data> v3dmath_test;
typedef v3dmath_test::object v3dmath_object;
tut::v3dmath_test v3dmath_testcase("v3dmath");
template<> template<>
void v3dmath_object::test<1>()
{
LLVector3d vec3D;
ensure("1:LLVector3d:Fail to initialize ", ((0 == vec3D.mdV[VX]) && (0 == vec3D.mdV[VY]) && (0 == vec3D.mdV[VZ])));
F64 x = 2.32f, y = 1.212f, z = -.12f;
LLVector3d vec3Da(x,y,z);
ensure("2:LLVector3d:Fail to initialize ", ((2.32f == vec3Da.mdV[VX]) && (1.212f == vec3Da.mdV[VY]) && (-.12f == vec3Da.mdV[VZ])));
const F64 vec[3] = {1.2f ,3.2f, -4.2f};
LLVector3d vec3Db(vec);
ensure("3:LLVector3d:Fail to initialize ", ((1.2f == vec3Db.mdV[VX]) && (3.2f == vec3Db.mdV[VY]) && (-4.2f == vec3Db.mdV[VZ])));
LLVector3 vec3((F32)x,(F32)y,(F32)z);
LLVector3d vec3Dc(vec3);
ensure_equals("4:LLVector3d Fail to initialize",vec3Da,vec3Dc);
}
template<> template<>
void v3dmath_object::test<2>()
{
S32 a = -235;
LLSD llsd(a);
LLVector3d vec3d(llsd);
LLSD sd = vec3d.getValue();
LLVector3d vec3da(sd);
ensure("1:getValue:Fail ", (vec3d == vec3da));
}
template<> template<>
void v3dmath_object::test<3>()
{
F64 a = 232345521.411132;
LLSD llsd(a);
LLVector3d vec3d;
vec3d.setValue(llsd);
LLSD sd = vec3d.getValue();
LLVector3d vec3da(sd);
ensure("1:setValue:Fail to initialize ", (vec3d == vec3da));
}
template<> template<>
void v3dmath_object::test<4>()
{
F64 a[3] = {222231.43222, 12345.2343, -434343.33222};
LLSD llsd;
llsd[0] = a[0];
llsd[1] = a[1];
llsd[2] = a[2];
LLVector3d vec3D;
vec3D = (LLVector3d)llsd;
ensure("1:operator=:Fail to initialize ", ((llsd[0].asReal()== vec3D.mdV[VX]) && (llsd[1].asReal() == vec3D.mdV[VY]) && (llsd[2].asReal() == vec3D.mdV[VZ])));
}
template<> template<>
void v3dmath_object::test<5>()
{
F64 x = 2.32f, y = 1.212f, z = -.12f;
LLVector3d vec3D(x,y,z);
vec3D.clearVec();
ensure("1:clearVec:Fail to initialize ", ((0 == vec3D.mdV[VX]) && (0 == vec3D.mdV[VY]) && (0 == vec3D.mdV[VZ])));
vec3D.setVec(x,y,z);
ensure("2:setVec:Fail to initialize ", ((x == vec3D.mdV[VX]) && (y == vec3D.mdV[VY]) && (z == vec3D.mdV[VZ])));
vec3D.zeroVec();
ensure("3:zeroVec:Fail to initialize ", ((0 == vec3D.mdV[VX]) && (0 == vec3D.mdV[VY]) && (0 == vec3D.mdV[VZ])));
vec3D.clearVec();
LLVector3 vec3((F32)x,(F32)y,(F32)z);
vec3D.setVec(vec3);
ensure("4:setVec:Fail to initialize ", ((x == vec3D.mdV[VX]) && (y == vec3D.mdV[VY]) && (z == vec3D.mdV[VZ])));
vec3D.clearVec();
const F64 vec[3] = {x,y,z};
vec3D.setVec(vec);
ensure("5:setVec:Fail to initialize ", ((x == vec3D.mdV[VX]) && (y == vec3D.mdV[VY]) && (z == vec3D.mdV[VZ])));
LLVector3d vec3Da;
vec3Da.setVec(vec3D);
ensure_equals("6:setVec: Fail to initialize", vec3D, vec3Da);
}
template<> template<>
void v3dmath_object::test<6>()
{
F64 x = -2.32, y = 1.212, z = -.12;
LLVector3d vec3D(x,y,z);
vec3D.abs();
ensure("1:abs:Fail ", ((-x == vec3D.mdV[VX]) && (y == vec3D.mdV[VY]) && (-z == vec3D.mdV[VZ])));
ensure("2:isNull():Fail ", (FALSE == vec3D.isNull()));
vec3D.clearVec();
x =.00000001, y = .000001001, z = .000001001;
vec3D.setVec(x,y,z);
ensure("3:isNull():Fail ", (TRUE == vec3D.isNull()));
ensure("4:isExactlyZero():Fail ", (FALSE == vec3D.isExactlyZero()));
x =.0000000, y = .00000000, z = .00000000;
vec3D.setVec(x,y,z);
ensure("5:isExactlyZero():Fail ", (TRUE == vec3D.isExactlyZero()));
}
template<> template<>
void v3dmath_object::test<7>()
{
F64 x = -2.32, y = 1.212, z = -.12;
LLVector3d vec3D(x,y,z);
ensure("1:operator [] failed",( x == vec3D[0]));
ensure("2:operator [] failed",( y == vec3D[1]));
ensure("3:operator [] failed",( z == vec3D[2]));
vec3D.clearVec();
x = 23.23, y = -.2361, z = 3.25;
vec3D.setVec(x,y,z);
F64 &ref1 = vec3D[0];
ensure("4:operator [] failed",( ref1 == vec3D[0]));
F64 &ref2 = vec3D[1];
ensure("5:operator [] failed",( ref2 == vec3D[1]));
F64 &ref3 = vec3D[2];
ensure("6:operator [] failed",( ref3 == vec3D[2]));
}
template<> template<>
void v3dmath_object::test<8>()
{
F32 x = 1.f, y = 2.f, z = -1.f;
LLVector4 vec4(x,y,z);
LLVector3d vec3D;
vec3D = vec4;
ensure("1:operator=:Fail to initialize ", ((vec4.mV[VX] == vec3D.mdV[VX]) && (vec4.mV[VY] == vec3D.mdV[VY]) && (vec4.mV[VZ] == vec3D.mdV[VZ])));
}
template<> template<>
void v3dmath_object::test<9>()
{
F64 x1 = 1.78787878, y1 = 232322.2121, z1 = -12121.121212;
F64 x2 = 1.2, y2 = 2.5, z2 = 1.;
LLVector3d vec3D(x1,y1,z1),vec3Da(x2,y2,z2),vec3Db;
vec3Db = vec3Da+ vec3D;
ensure("1:operator+:Fail to initialize ", ((x1+x2 == vec3Db.mdV[VX]) && (y1+y2 == vec3Db.mdV[VY]) && (z1+z2 == vec3Db.mdV[VZ])));
x1 = -2.45, y1 = 2.1, z1 = 3.0;
vec3D.clearVec();
vec3Da.clearVec();
vec3D.setVec(x1,y1,z1);
vec3Da += vec3D;
ensure_equals("2:operator+=: Fail to initialize", vec3Da,vec3D);
vec3Da += vec3D;
ensure("3:operator+=:Fail to initialize ", ((2*x1 == vec3Da.mdV[VX]) && (2*y1 == vec3Da.mdV[VY]) && (2*z1 == vec3Da.mdV[VZ])));
}
template<> template<>
void v3dmath_object::test<10>()
{
F64 x1 = 1., y1 = 2., z1 = -1.1;
F64 x2 = 1.2, y2 = 2.5, z2 = 1.;
LLVector3d vec3D(x1,y1,z1),vec3Da(x2,y2,z2),vec3Db;
vec3Db = vec3Da - vec3D;
ensure("1:operator-:Fail to initialize ", ((x2-x1 == vec3Db.mdV[VX]) && (y2-y1 == vec3Db.mdV[VY]) && (z2-z1 == vec3Db.mdV[VZ])));
x1 = -2.45, y1 = 2.1, z1 = 3.0;
vec3D.clearVec();
vec3Da.clearVec();
vec3D.setVec(x1,y1,z1);
vec3Da -=vec3D;
ensure("2:operator-=:Fail to initialize ", ((2.45 == vec3Da.mdV[VX]) && (-2.1 == vec3Da.mdV[VY]) && (-3.0 == vec3Da.mdV[VZ])));
vec3Da -= vec3D;
ensure("3:operator-=:Fail to initialize ", ((-2*x1 == vec3Da.mdV[VX]) && (-2*y1 == vec3Da.mdV[VY]) && (-2*z1 == vec3Da.mdV[VZ])));
}
template<> template<>
void v3dmath_object::test<11>()
{
F64 x1 = 1., y1 = 2., z1 = -1.1;
F64 x2 = 1.2, y2 = 2.5, z2 = 1.;
LLVector3d vec3D(x1,y1,z1),vec3Da(x2,y2,z2);
F64 res = vec3D * vec3Da;
ensure_approximately_equals(
"1:operator* failed",
res,
(x1*x2 + y1*y2 + z1*z2),
8);
vec3Da.clearVec();
F64 mulVal = 4.2;
vec3Da = vec3D * mulVal;
ensure_approximately_equals(
"2a:operator* failed",
vec3Da.mdV[VX],
x1*mulVal,
8);
ensure_approximately_equals(
"2b:operator* failed",
vec3Da.mdV[VY],
y1*mulVal,
8);
ensure_approximately_equals(
"2c:operator* failed",
vec3Da.mdV[VZ],
z1*mulVal,
8);
vec3Da.clearVec();
vec3Da = mulVal * vec3D;
ensure_approximately_equals(
"3a:operator* failed",
vec3Da.mdV[VX],
x1*mulVal,
8);
ensure_approximately_equals(
"3b:operator* failed",
vec3Da.mdV[VY],
y1*mulVal,
8);
ensure_approximately_equals(
"3c:operator* failed",
vec3Da.mdV[VZ],
z1*mulVal,
8);
vec3D *= mulVal;
ensure_approximately_equals(
"4a:operator*= failed",
vec3D.mdV[VX],
x1*mulVal,
8);
ensure_approximately_equals(
"4b:operator*= failed",
vec3D.mdV[VY],
y1*mulVal,
8);
ensure_approximately_equals(
"4c:operator*= failed",
vec3D.mdV[VZ],
z1*mulVal,
8);
}
template<> template<>
void v3dmath_object::test<12>()
{
F64 x1 = 1., y1 = 2., z1 = -1.1;
F64 x2 = 1.2, y2 = 2.5, z2 = 1.;
F64 val1, val2, val3;
LLVector3d vec3D(x1,y1,z1),vec3Da(x2,y2,z2), vec3Db;
vec3Db = vec3D % vec3Da;
val1 = y1*z2 - y2*z1;
val2 = z1*x2 -z2*x1;
val3 = x1*y2-x2*y1;
ensure("1:operator% failed",(val1 == vec3Db.mdV[VX]) && (val2 == vec3Db.mdV[VY]) && (val3 == vec3Db.mdV[VZ]));
vec3D %= vec3Da;
ensure("2:operator%= failed",
is_approx_equal(vec3D.mdV[VX],vec3Db.mdV[VX]) &&
is_approx_equal(vec3D.mdV[VY],vec3Db.mdV[VY]) &&
is_approx_equal(vec3D.mdV[VZ],vec3Db.mdV[VZ]) );
}
template<> template<>
void v3dmath_object::test<13>()
{
F64 x1 = 1., y1 = 2., z1 = -1.1,div = 4.2;
F64 t = 1.f / div;
LLVector3d vec3D(x1,y1,z1), vec3Da;
vec3Da = vec3D/div;
ensure_approximately_equals(
"1a:operator/ failed",
vec3Da.mdV[VX],
x1*t,
8);
ensure_approximately_equals(
"1b:operator/ failed",
vec3Da.mdV[VY],
y1*t,
8);
ensure_approximately_equals(
"1c:operator/ failed",
vec3Da.mdV[VZ],
z1*t,
8);
x1 = 1.23, y1 = 4., z1 = -2.32;
vec3D.clearVec();
vec3Da.clearVec();
vec3D.setVec(x1,y1,z1);
vec3Da = vec3D/div;
ensure_approximately_equals(
"2a:operator/ failed",
vec3Da.mdV[VX],
x1*t,
8);
ensure_approximately_equals(
"2b:operator/ failed",
vec3Da.mdV[VY],
y1*t,
8);
ensure_approximately_equals(
"2c:operator/ failed",
vec3Da.mdV[VZ],
z1*t,
8);
vec3D /= div;
ensure_approximately_equals(
"3a:operator/= failed",
vec3D.mdV[VX],
x1*t,
8);
ensure_approximately_equals(
"3b:operator/= failed",
vec3D.mdV[VY],
y1*t,
8);
ensure_approximately_equals(
"3c:operator/= failed",
vec3D.mdV[VZ],
z1*t,
8);
}
template<> template<>
void v3dmath_object::test<14>()
{
F64 x1 = 1., y1 = 2., z1 = -1.1;
LLVector3d vec3D(x1,y1,z1), vec3Da;
ensure("1:operator!= failed",(TRUE == (vec3D !=vec3Da)));
vec3Da = vec3D;
ensure("2:operator== failed",(vec3D ==vec3Da));
vec3D.clearVec();
vec3Da.clearVec();
x1 = .211, y1 = 21.111, z1 = 23.22;
vec3D.setVec(x1,y1,z1);
vec3Da.setVec(x1,y1,z1);
ensure("3:operator== failed",(vec3D ==vec3Da));
ensure("4:operator!= failed",(FALSE == (vec3D !=vec3Da)));
}
template<> template<>
void v3dmath_object::test<15>()
{
F64 x1 = 1., y1 = 2., z1 = -1.1;
LLVector3d vec3D(x1,y1,z1), vec3Da;
std::ostringstream stream1, stream2;
stream1 << vec3D;
vec3Da.setVec(x1,y1,z1);
stream2 << vec3Da;
ensure("1:operator << failed",(stream1.str() == stream2.str()));
}
template<> template<>
void v3dmath_object::test<16>()
{
F64 x1 = 1.23, y1 = 2.0, z1 = 4.;
std::string buf("1.23 2. 4");
LLVector3d vec3D, vec3Da(x1,y1,z1);
LLVector3d::parseVector3d(buf, &vec3D);
ensure_equals("1:parseVector3d: failed " , vec3D, vec3Da);
}
template<> template<>
void v3dmath_object::test<17>()
{
F64 x1 = 1., y1 = 2., z1 = -1.1;
LLVector3d vec3D(x1,y1,z1), vec3Da;
vec3Da = -vec3D;
ensure("1:operator- failed", (vec3D == - vec3Da));
}
template<> template<>
void v3dmath_object::test<18>()
{
F64 x = 1., y = 2., z = -1.1;
LLVector3d vec3D(x,y,z);
F64 res = (x*x + y*y + z*z) - vec3D.magVecSquared();
ensure("1:magVecSquared:Fail ", ((-F_APPROXIMATELY_ZERO <= res)&& (res <=F_APPROXIMATELY_ZERO)));
res = fsqrtf(x*x + y*y + z*z) - vec3D.magVec();
ensure("2:magVec: Fail ", ((-F_APPROXIMATELY_ZERO <= res)&& (res <=F_APPROXIMATELY_ZERO)));
}
template<> template<>
void v3dmath_object::test<19>()
{
F64 x = 1., y = 2., z = -1.1;
LLVector3d vec3D(x,y,z);
F64 mag = vec3D.normVec();
mag = 1.f/ mag;
ensure_approximately_equals(
"1a:normVec: Fail ",
vec3D.mdV[VX],
x * mag,
8);
ensure_approximately_equals(
"1b:normVec: Fail ",
vec3D.mdV[VY],
y * mag,
8);
ensure_approximately_equals(
"1c:normVec: Fail ",
vec3D.mdV[VZ],
z * mag,
8);
x = 0.000000001, y = 0.000000001, z = 0.000000001;
vec3D.clearVec();
vec3D.setVec(x,y,z);
mag = vec3D.normVec();
ensure_approximately_equals(
"2a:normVec: Fail ",
vec3D.mdV[VX],
x * mag,
8);
ensure_approximately_equals(
"2b:normVec: Fail ",
vec3D.mdV[VY],
y * mag,
8);
ensure_approximately_equals(
"2c:normVec: Fail ",
vec3D.mdV[VZ],
z * mag,
8);
}
template<> template<>
void v3dmath_object::test<20>()
{
F64 x1 = 1111.232222;
F64 y1 = 2222222222.22;
F64 z1 = 422222222222.0;
std::string buf("1111.232222 2222222222.22 422222222222");
LLVector3d vec3Da, vec3Db(x1,y1,z1);
LLVector3d::parseVector3d(buf, &vec3Da);
ensure_equals("1:parseVector3 failed", vec3Da, vec3Db);
}
template<> template<>
void v3dmath_object::test<21>()
{
F64 x1 = 1., y1 = 2., z1 = -1.1;
F64 x2 = 1.2, y2 = 2.5, z2 = 1.;
F64 val = 2.3f,val1,val2,val3;
val1 = x1 + (x2 - x1)* val;
val2 = y1 + (y2 - y1)* val;
val3 = z1 + (z2 - z1)* val;
LLVector3d vec3Da(x1,y1,z1),vec3Db(x2,y2,z2);
LLVector3d vec3d = lerp(vec3Da,vec3Db,val);
ensure("1:lerp failed", ((val1 ==vec3d.mdV[VX])&& (val2 ==vec3d.mdV[VY]) && (val3 ==vec3d.mdV[VZ])));
}
template<> template<>
void v3dmath_object::test<22>()
{
F64 x = 2.32, y = 1.212, z = -.12;
F64 min = 0.0001, max = 3.0;
LLVector3d vec3d(x,y,z);
ensure("1:clamp:Fail ", (TRUE == (vec3d.clamp(min, max))));
x = 0.000001f, z = 5.3f;
vec3d.setVec(x,y,z);
ensure("2:clamp:Fail ", (TRUE == (vec3d.clamp(min, max))));
}
template<> template<>
void v3dmath_object::test<23>()
{
F64 x = 10., y = 20., z = -15.;
F64 epsilon = .23425;
LLVector3d vec3Da(x,y,z), vec3Db(x,y,z);
ensure("1:are_parallel: Fail ", (TRUE == are_parallel(vec3Da,vec3Db,epsilon)));
F64 x1 = -12., y1 = -20., z1 = -100.;
vec3Db.clearVec();
vec3Db.setVec(x1,y1,z1);
ensure("2:are_parallel: Fail ", (FALSE == are_parallel(vec3Da,vec3Db,epsilon)));
}
template<> template<>
void v3dmath_object::test<24>()
{
#if LL_WINDOWS && _MSC_VER < 1400
skip("This fails on VS2003!");
#else
F64 x = 10., y = 20., z = -15.;
F64 angle1, angle2;
LLVector3d vec3Da(x,y,z), vec3Db(x,y,z);
angle1 = angle_between(vec3Da, vec3Db);
ensure("1:angle_between: Fail ", (0 == angle1));
F64 x1 = -1., y1 = -20., z1 = -1.;
vec3Da.clearVec();
vec3Da.setVec(x1,y1,z1);
angle2 = angle_between(vec3Da, vec3Db);
vec3Db.normVec();
vec3Da.normVec();
F64 angle = vec3Db*vec3Da;
angle = acos(angle);
ensure("2:angle_between: Fail ", (angle == angle2));
#endif
}
}

View File

@ -0,0 +1,573 @@
/**
* @file v3math_tut.cpp
* @author Adroit
* @date 2007-02
* @brief v3math test cases.
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "../test/lltut.h"
#include "llsd.h"
#include "../llquaternion.h"
#include "../llquantize.h"
#include "../v3dmath.h"
#include "../m3math.h"
#include "../v4math.h"
#include "../v3math.h"
namespace tut
{
struct v3math_data
{
};
typedef test_group<v3math_data> v3math_test;
typedef v3math_test::object v3math_object;
tut::v3math_test v3math_testcase("v3math");
template<> template<>
void v3math_object::test<1>()
{
LLVector3 vec3;
ensure("1:LLVector3:Fail to initialize ", ((0.f == vec3.mV[VX]) && (0.f == vec3.mV[VY]) && (0.f == vec3.mV[VZ])));
F32 x = 2.32f, y = 1.212f, z = -.12f;
LLVector3 vec3a(x,y,z);
ensure("2:LLVector3:Fail to initialize ", ((2.32f == vec3a.mV[VX]) && (1.212f == vec3a.mV[VY]) && (-.12f == vec3a.mV[VZ])));
const F32 vec[3] = {1.2f ,3.2f, -4.2f};
LLVector3 vec3b(vec);
ensure("3:LLVector3:Fail to initialize ", ((1.2f == vec3b.mV[VX]) && (3.2f == vec3b.mV[VY]) && (-4.2f == vec3b.mV[VZ])));
}
template<> template<>
void v3math_object::test<2>()
{
F32 x = 2.32f, y = 1.212f, z = -.12f;
LLVector3 vec3(x,y,z);
LLVector3d vector3d(vec3);
LLVector3 vec3a(vector3d);
ensure("1:LLVector3:Fail to initialize ", vec3 == vec3a);
LLVector4 vector4(vec3);
LLVector3 vec3b(vector4);
ensure("2:LLVector3:Fail to initialize ", vec3 == vec3b);
}
template<> template<>
void v3math_object::test<3>()
{
S32 a = 231;
LLSD llsd(a);
LLVector3 vec3(llsd);
LLSD sd = vec3.getValue();
LLVector3 vec3a(sd);
ensure("1:LLVector3:Fail to initialize ", (vec3 == vec3a));
}
template<> template<>
void v3math_object::test<4>()
{
S32 a = 231;
LLSD llsd(a);
LLVector3 vec3(llsd),vec3a;
vec3a = vec3;
ensure("1:Operator= Fail to initialize " ,(vec3 == vec3a));
}
template<> template<>
void v3math_object::test<5>()
{
F32 x = 2.32f, y = 1.212f, z = -.12f;
LLVector3 vec3(x,y,z);
ensure("1:isFinite= Fail to initialize ", (TRUE == vec3.isFinite()));//need more test cases:
vec3.clearVec();
ensure("2:clearVec:Fail to set values ", ((0.f == vec3.mV[VX]) && (0.f == vec3.mV[VY]) && (0.f == vec3.mV[VZ])));
vec3.setVec(x,y,z);
ensure("3:setVec:Fail to set values ", ((2.32f == vec3.mV[VX]) && (1.212f == vec3.mV[VY]) && (-.12f == vec3.mV[VZ])));
vec3.zeroVec();
ensure("4:zeroVec:Fail to set values ", ((0.f == vec3.mV[VX]) && (0.f == vec3.mV[VY]) && (0.f == vec3.mV[VZ])));
}
template<> template<>
void v3math_object::test<6>()
{
F32 x = 2.32f, y = 1.212f, z = -.12f;
LLVector3 vec3(x,y,z),vec3a;
vec3.abs();
ensure("1:abs:Fail ", ((x == vec3.mV[VX]) && (y == vec3.mV[VY]) && (-z == vec3.mV[VZ])));
vec3a.setVec(vec3);
ensure("2:setVec:Fail to initialize ", (vec3a == vec3));
const F32 vec[3] = {1.2f ,3.2f, -4.2f};
vec3.clearVec();
vec3.setVec(vec);
ensure("3:setVec:Fail to initialize ", ((1.2f == vec3.mV[VX]) && (3.2f == vec3.mV[VY]) && (-4.2f == vec3.mV[VZ])));
vec3a.clearVec();
LLVector3d vector3d(vec3);
vec3a.setVec(vector3d);
ensure("4:setVec:Fail to initialize ", (vec3 == vec3a));
LLVector4 vector4(vec3);
vec3a.clearVec();
vec3a.setVec(vector4);
ensure("5:setVec:Fail to initialize ", (vec3 == vec3a));
}
template<> template<>
void v3math_object::test<7>()
{
F32 x = 2.32f, y = 3.212f, z = -.12f;
F32 min = 0.0001f, max = 3.0f;
LLVector3 vec3(x,y,z);
ensure("1:clamp:Fail ", TRUE == vec3.clamp(min, max) && x == vec3.mV[VX] && max == vec3.mV[VY] && min == vec3.mV[VZ]);
x = 1.f, y = 2.2f, z = 2.8f;
vec3.setVec(x,y,z);
ensure("2:clamp:Fail ", FALSE == vec3.clamp(min, max));
}
template<> template<>
void v3math_object::test<8>()
{
F32 x = 2.32f, y = 1.212f, z = -.12f;
LLVector3 vec3(x,y,z);
ensure("1:magVecSquared:Fail ", is_approx_equal(vec3.magVecSquared(), (x*x + y*y + z*z)));
ensure("2:magVec:Fail ", is_approx_equal(vec3.magVec(), fsqrtf(x*x + y*y + z*z)));
}
template<> template<>
void v3math_object::test<9>()
{
F32 x =-2.0f, y = -3.0f, z = 1.23f ;
LLVector3 vec3(x,y,z);
ensure("1:abs():Fail ", (TRUE == vec3.abs()));
ensure("2:isNull():Fail", (FALSE == vec3.isNull())); //Returns TRUE if vector has a _very_small_ length
x =.00000001f, y = .000001001f, z = .000001001f;
vec3.setVec(x,y,z);
ensure("3:isNull(): Fail ", (TRUE == vec3.isNull()));
}
template<> template<>
void v3math_object::test<10>()
{
F32 x =-2.0f, y = -3.0f, z = 1.f ;
LLVector3 vec3(x,y,z),vec3a;
ensure("1:isExactlyZero():Fail ", (TRUE == vec3a.isExactlyZero()));
vec3a = vec3a.scaleVec(vec3);
ensure("2:scaleVec: Fail ", vec3a.mV[VX] == 0.f && vec3a.mV[VY] == 0.f && vec3a.mV[VZ] == 0.f);
vec3a.setVec(x,y,z);
vec3a = vec3a.scaleVec(vec3);
ensure("3:scaleVec: Fail ", ((4 == vec3a.mV[VX]) && (9 == vec3a.mV[VY]) &&(1 == vec3a.mV[VZ])));
ensure("4:isExactlyZero():Fail ", (FALSE == vec3.isExactlyZero()));
}
template<> template<>
void v3math_object::test<11>()
{
F32 x =20.0f, y = 30.0f, z = 15.f ;
F32 angle = 100.f;
LLVector3 vec3(x,y,z),vec3a(1.f,2.f,3.f);
vec3a = vec3a.rotVec(angle, vec3);
LLVector3 vec3b(1.f,2.f,3.f);
vec3b = vec3b.rotVec(angle, vec3);
ensure_equals("rotVec():Fail" ,vec3b,vec3a);
}
template<> template<>
void v3math_object::test<12>()
{
F32 x =-2.0f, y = -3.0f, z = 1.f ;
LLVector3 vec3(x,y,z);
ensure("1:operator [] failed",( x == vec3[0]));
ensure("2:operator [] failed",( y == vec3[1]));
ensure("3:operator [] failed",( z == vec3[2]));
vec3.clearVec();
x = 23.f, y = -.2361f, z = 3.25;
vec3.setVec(x,y,z);
F32 &ref1 = vec3[0];
ensure("4:operator [] failed",( ref1 == vec3[0]));
F32 &ref2 = vec3[1];
ensure("5:operator [] failed",( ref2 == vec3[1]));
F32 &ref3 = vec3[2];
ensure("6:operator [] failed",( ref3 == vec3[2]));
}
template<> template<>
void v3math_object::test<13>()
{
F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f;
F32 val1, val2, val3;
LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2), vec3b;
vec3b = vec3 + vec3a ;
val1 = x1+x2;
val2 = y1+y2;
val3 = z1+z2;
ensure("1:operator+ failed",(val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ]));
vec3.clearVec();
vec3a.clearVec();
vec3b.clearVec();
x1 = -.235f, y1 = -24.32f,z1 = 2.13f, x2 = -2.3f, y2 = 1.f, z2 = 34.21f;
vec3.setVec(x1,y1,z1);
vec3a.setVec(x2,y2,z2);
vec3b = vec3 + vec3a;
val1 = x1+x2;
val2 = y1+y2;
val3 = z1+z2;
ensure("2:operator+ failed",(val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ]));
}
template<> template<>
void v3math_object::test<14>()
{
F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f;
F32 val1, val2, val3;
LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2), vec3b;
vec3b = vec3 - vec3a ;
val1 = x1-x2;
val2 = y1-y2;
val3 = z1-z2;
ensure("1:operator- failed",(val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ]));
vec3.clearVec();
vec3a.clearVec();
vec3b.clearVec();
x1 = -.235f, y1 = -24.32f,z1 = 2.13f, x2 = -2.3f, y2 = 1.f, z2 = 34.21f;
vec3.setVec(x1,y1,z1);
vec3a.setVec(x2,y2,z2);
vec3b = vec3 - vec3a;
val1 = x1-x2;
val2 = y1-y2;
val3 = z1-z2;
ensure("2:operator- failed",(val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ]));
}
template<> template<>
void v3math_object::test<15>()
{
F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f;
F32 val1, val2, val3;
LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2);
val1 = vec3 * vec3a;
val2 = x1*x2 + y1*y2 + z1*z2;
ensure_equals("1:operator* failed",val1,val2);
vec3a.clearVec();
F32 mulVal = 4.332f;
vec3a = vec3 * mulVal;
val1 = x1*mulVal;
val2 = y1*mulVal;
val3 = z1*mulVal;
ensure("2:operator* failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY])&& (val3 == vec3a.mV[VZ]));
vec3a.clearVec();
vec3a = mulVal * vec3;
ensure("3:operator* failed ", (val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY])&& (val3 == vec3a.mV[VZ]));
}
template<> template<>
void v3math_object::test<16>()
{
F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f;
F32 val1, val2, val3;
LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2), vec3b;
vec3b = vec3 % vec3a ;
val1 = y1*z2 - y2*z1;
val2 = z1*x2 -z2*x1;
val3 = x1*y2-x2*y1;
ensure("1:operator% failed",(val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ]));
vec3.clearVec();
vec3a.clearVec();
vec3b.clearVec();
x1 =112.f, y1 = 22.3f,z1 = 1.2f, x2 = -2.3f, y2 = 341.11f, z2 = 1234.234f;
vec3.setVec(x1,y1,z1);
vec3a.setVec(x2,y2,z2);
vec3b = vec3 % vec3a ;
val1 = y1*z2 - y2*z1;
val2 = z1*x2 -z2*x1;
val3 = x1*y2-x2*y1;
ensure("2:operator% failed ", (val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ]));
}
template<> template<>
void v3math_object::test<17>()
{
F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, div = 3.2f;
F32 t = 1.f / div, val1, val2, val3;
LLVector3 vec3(x1,y1,z1), vec3a;
vec3a = vec3 / div;
val1 = x1 * t;
val2 = y1 * t;
val3 = z1 *t;
ensure("1:operator/ failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY]) && (val3 == vec3a.mV[VZ]));
vec3a.clearVec();
x1 = -.235f, y1 = -24.32f, z1 = .342f, div = -2.2f;
t = 1.f / div;
vec3.setVec(x1,y1,z1);
vec3a = vec3 / div;
val1 = x1 * t;
val2 = y1 * t;
val3 = z1 *t;
ensure("2:operator/ failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY]) && (val3 == vec3a.mV[VZ]));
}
template<> template<>
void v3math_object::test<18>()
{
F32 x1 =1.f, y1 = 2.f,z1 = 1.2f;
LLVector3 vec3(x1,y1,z1), vec3a(x1,y1,z1);
ensure("1:operator== failed",(vec3 == vec3a));
vec3a.clearVec();
x1 = -.235f, y1 = -24.32f, z1 = .342f;
vec3.clearVec();
vec3a.clearVec();
vec3.setVec(x1,y1,z1);
vec3a.setVec(x1,y1,z1);
ensure("2:operator== failed ", (vec3 == vec3a));
}
template<> template<>
void v3math_object::test<19>()
{
F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 =112.f, y2 = 2.234f,z2 = 11.2f;;
LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2);
ensure("1:operator!= failed",(vec3a != vec3));
vec3.clearVec();
vec3.clearVec();
vec3a.setVec(vec3);
ensure("2:operator!= failed", ( FALSE == (vec3a != vec3)));
}
template<> template<>
void v3math_object::test<20>()
{
F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 =112.f, y2 = 2.2f,z2 = 11.2f;;
LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2);
vec3a += vec3;
F32 val1, val2, val3;
val1 = x1+x2;
val2 = y1+y2;
val3 = z1+z2;
ensure("1:operator+= failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY])&& (val3 == vec3a.mV[VZ]));
}
template<> template<>
void v3math_object::test<21>()
{
F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 =112.f, y2 = 2.2f,z2 = 11.2f;;
LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2);
vec3a -= vec3;
F32 val1, val2, val3;
val1 = x2-x1;
val2 = y2-y1;
val3 = z2-z1;
ensure("1:operator-= failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY])&& (val3 == vec3a.mV[VZ]));
}
template<> template<>
void v3math_object::test<22>()
{
F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f;
F32 val1,val2,val3;
LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2);
vec3a *= vec3;
val1 = x1*x2;
val2 = y1*y2;
val3 = z1*z2;
ensure("1:operator*= failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY])&& (val3 == vec3a.mV[VZ]));
F32 mulVal = 4.332f;
vec3 *=mulVal;
val1 = x1*mulVal;
val2 = y1*mulVal;
val3 = z1*mulVal;
ensure("2:operator*= failed ", is_approx_equal(val1, vec3.mV[VX]) && is_approx_equal(val2, vec3.mV[VY]) && is_approx_equal(val3, vec3.mV[VZ]));
}
template<> template<>
void v3math_object::test<23>()
{
F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f;
LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2),vec3b;
vec3b = vec3a % vec3;
vec3a %= vec3;
ensure_equals("1:operator%= failed",vec3a,vec3b);
}
template<> template<>
void v3math_object::test<24>()
{
F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, div = 3.2f;
F32 t = 1.f / div, val1, val2, val3;
LLVector3 vec3a(x1,y1,z1);
vec3a /= div;
val1 = x1 * t;
val2 = y1 * t;
val3 = z1 *t;
ensure("1:operator/= failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY]) && (val3 == vec3a.mV[VZ]));
}
template<> template<>
void v3math_object::test<25>()
{
F32 x1 =1.f, y1 = 2.f,z1 = 1.2f;
LLVector3 vec3(x1,y1,z1), vec3a;
vec3a = -vec3;
ensure("1:operator- failed",(-vec3a == vec3));
}
template<> template<>
void v3math_object::test<26>()
{
F32 x1 =1.f, y1 = 2.f,z1 = 1.2f;
std::ostringstream stream1, stream2;
LLVector3 vec3(x1,y1,z1), vec3a;
stream1 << vec3;
vec3a.setVec(x1,y1,z1);
stream2 << vec3a;
ensure("1:operator << failed",(stream1.str() == stream2.str()));
}
template<> template<>
void v3math_object::test<27>()
{
F32 x1 =-2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, y2 = 1.11f, z2 = 1234.234f;
LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2);
ensure("1:operator< failed", (TRUE == (vec3 < vec3a)));
x1 =-2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, y2 = 2.f, z2 = 1234.234f;
vec3.setVec(x1,y1,z1);
vec3a.setVec(x2,y2,z2);
ensure("2:operator< failed ", (TRUE == (vec3 < vec3a)));
x1 =2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f,
vec3.setVec(x1,y1,z1);
vec3a.setVec(x2,y2,z2);
ensure("3:operator< failed ", (FALSE == (vec3 < vec3a)));
}
template<> template<>
void v3math_object::test<28>()
{
F32 x1 =1.23f, y1 = 2.f,z1 = 4.f;
std::string buf("1.23 2. 4");
LLVector3 vec3, vec3a(x1,y1,z1);
LLVector3::parseVector3(buf, &vec3);
ensure_equals("1:parseVector3 failed", vec3, vec3a);
}
template<> template<>
void v3math_object::test<29>()
{
F32 x1 =1.f, y1 = 2.f,z1 = 4.f;
LLVector3 vec3(x1,y1,z1),vec3a,vec3b;
vec3a.setVec(1,1,1);
vec3a.scaleVec(vec3);
ensure_equals("1:scaleVec failed", vec3, vec3a);
vec3a.clearVec();
vec3a.setVec(x1,y1,z1);
vec3a.scaleVec(vec3);
ensure("2:scaleVec failed", ((1.f ==vec3a.mV[VX])&& (4.f ==vec3a.mV[VY]) && (16.f ==vec3a.mV[VZ])));
}
template<> template<>
void v3math_object::test<30>()
{
F32 x1 =-2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, y2 = 1.11f, z2 = 1234.234f;
F32 val = 2.3f,val1,val2,val3;
val1 = x1 + (x2 - x1)* val;
val2 = y1 + (y2 - y1)* val;
val3 = z1 + (z2 - z1)* val;
LLVector3 vec3(x1,y1,z1),vec3a(x2,y2,z2);
LLVector3 vec3b = lerp(vec3,vec3a,val);
ensure("1:lerp failed", ((val1 ==vec3b.mV[VX])&& (val2 ==vec3b.mV[VY]) && (val3 ==vec3b.mV[VZ])));
}
template<> template<>
void v3math_object::test<31>()
{
F32 x1 =-2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, y2 = 1.f, z2 = 1.f;
F32 val1,val2;
LLVector3 vec3(x1,y1,z1),vec3a(x2,y2,z2);
val1 = dist_vec(vec3,vec3a);
val2 = fsqrtf((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2));
ensure_equals("1:dist_vec: Fail ",val2, val1);
val1 = dist_vec_squared(vec3,vec3a);
val2 =((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2));
ensure_equals("2:dist_vec_squared: Fail ",val2, val1);
val1 = dist_vec_squared2D(vec3, vec3a);
val2 =(x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2);
ensure_equals("3:dist_vec_squared2D: Fail ",val2, val1);
}
template<> template<>
void v3math_object::test<32>()
{
F32 x =12.3524f, y = -342.f,z = 4.126341f;
LLVector3 vec3(x,y,z);
F32 mag = vec3.normVec();
mag = 1.f/ mag;
F32 val1 = x* mag, val2 = y* mag, val3 = z* mag;
ensure("1:normVec: Fail ", is_approx_equal(val1, vec3.mV[VX]) && is_approx_equal(val2, vec3.mV[VY]) && is_approx_equal(val3, vec3.mV[VZ]));
x = 0.000000001f, y = 0.f, z = 0.f;
vec3.clearVec();
vec3.setVec(x,y,z);
mag = vec3.normVec();
val1 = x* mag, val2 = y* mag, val3 = z* mag;
ensure("2:normVec: Fail ", (mag == 0.) && (0. == vec3.mV[VX]) && (0. == vec3.mV[VY])&& (0. == vec3.mV[VZ]));
}
template<> template<>
void v3math_object::test<33>()
{
F32 x = -202.23412f, y = 123.2312f, z = -89.f;
LLVector3 vec(x,y,z);
vec.snap(2);
ensure("1:snap: Fail ", is_approx_equal(-202.23f, vec.mV[VX]) && is_approx_equal(123.23f, vec.mV[VY]) && is_approx_equal(-89.f, vec.mV[VZ]));
}
template<> template<>
void v3math_object::test<34>()
{
F32 x = 10.f, y = 20.f, z = -15.f;
F32 x1, y1, z1;
F32 lowerxy = 0.f, upperxy = 1.0f, lowerz = -1.0f, upperz = 1.f;
LLVector3 vec3(x,y,z);
vec3.quantize16(lowerxy,upperxy,lowerz,upperz);
x1 = U16_to_F32(F32_to_U16(x, lowerxy, upperxy), lowerxy, upperxy);
y1 = U16_to_F32(F32_to_U16(y, lowerxy, upperxy), lowerxy, upperxy);
z1 = U16_to_F32(F32_to_U16(z, lowerz, upperz), lowerz, upperz);
ensure("1:quantize16: Fail ", is_approx_equal(x1, vec3.mV[VX]) && is_approx_equal(y1, vec3.mV[VY]) && is_approx_equal(z1, vec3.mV[VZ]));
LLVector3 vec3a(x,y,z);
vec3a.quantize8(lowerxy,upperxy,lowerz,upperz);
x1 = U8_to_F32(F32_to_U8(x, lowerxy, upperxy), lowerxy, upperxy);
y1 = U8_to_F32(F32_to_U8(y, lowerxy, upperxy), lowerxy, upperxy);
z1 = U8_to_F32(F32_to_U8(z, lowerz, upperz), lowerz, upperz);
ensure("2:quantize8: Fail ", is_approx_equal(x1, vec3a.mV[VX]) && is_approx_equal(y1, vec3a.mV[VY]) && is_approx_equal(z1, vec3a.mV[VZ]));
}
}

View File

@ -0,0 +1,365 @@
/**
* @file v4color_tut.cpp
* @author Adroit
* @date 2007-03
* @brief v4color test cases.
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "../test/lltut.h"
#include "../v4coloru.h"
#include "llsd.h"
#include "../v3color.h"
#include "../v4color.h"
namespace tut
{
struct v4color_data
{
};
typedef test_group<v4color_data> v4color_test;
typedef v4color_test::object v4color_object;
tut::v4color_test v4color_testcase("v4color");
template<> template<>
void v4color_object::test<1>()
{
LLColor4 llcolor4;
ensure("1:LLColor4:Fail to initialize ", ((0 == llcolor4.mV[VX]) && (0 == llcolor4.mV[VY]) && (0 == llcolor4.mV[VZ])&& (1.0f == llcolor4.mV[VW])));
F32 r = 0x20, g = 0xFFFF, b = 0xFF, a = 0xAF;
LLColor4 llcolor4a(r,g,b);
ensure("2:LLColor4:Fail to initialize ", ((r == llcolor4a.mV[VX]) && (g == llcolor4a.mV[VY]) && (b == llcolor4a.mV[VZ])&& (1.0f == llcolor4a.mV[VW])));
LLColor4 llcolor4b(r,g,b,a);
ensure("3:LLColor4:Fail to initialize ", ((r == llcolor4b.mV[VX]) && (g == llcolor4b.mV[VY]) && (b == llcolor4b.mV[VZ])&& (a == llcolor4b.mV[VW])));
const F32 vec[4] = {.112f ,23.2f, -4.2f, -.0001f};
LLColor4 llcolor4c(vec);
ensure("4:LLColor4:Fail to initialize ", ((vec[0] == llcolor4c.mV[VX]) && (vec[1] == llcolor4c.mV[VY]) && (vec[2] == llcolor4c.mV[VZ])&& (vec[3] == llcolor4c.mV[VW])));
LLColor3 llcolor3(-2.23f,1.01f,42.3f);
F32 val = -.1f;
LLColor4 llcolor4d(llcolor3,val);
ensure("5:LLColor4:Fail to initialize ", ((llcolor3.mV[VX] == llcolor4d.mV[VX]) && (llcolor3.mV[VY] == llcolor4d.mV[VY]) && (llcolor3.mV[VZ] == llcolor4d.mV[VZ])&& (val == llcolor4d.mV[VW])));
LLSD sd = llcolor4d.getValue();
LLColor4 llcolor4e(sd);
ensure_equals("6:LLColor4:(LLSD) failed ", llcolor4d, llcolor4e);
U8 r1 = 0xF2, g1 = 0xFA, b1 = 0xBF;
LLColor4U color4u(r1,g1,b1);
LLColor4 llcolor4g(color4u);
const F32 SCALE = 1.f/255.f;
F32 r2 = r1*SCALE, g2 = g1* SCALE, b2 = b1* SCALE;
ensure("7:LLColor4:Fail to initialize ", ((r2 == llcolor4g.mV[VX]) && (g2 == llcolor4g.mV[VY]) && (b2 == llcolor4g.mV[VZ])));
}
template<> template<>
void v4color_object::test<2>()
{
LLColor4 llcolor(1.0, 2.0, 3.0, 4.0);
LLSD llsd = llcolor.getValue();
LLColor4 llcolor4(llsd), llcolor4a;
llcolor4a.setValue(llsd);
ensure("setValue: failed", (llcolor4 == llcolor4a));
LLSD sd = llcolor4a.getValue();
LLColor4 llcolor4b(sd);
ensure("getValue: Failed ", (llcolor4b == llcolor4a));
}
template<> template<>
void v4color_object::test<3>()
{
F32 r = 0x20, g = 0xFFFF, b = 0xFF,a = 0xAF;
LLColor4 llcolor4(r,g,b,a);
llcolor4.setToBlack();
ensure("setToBlack:Fail to set the black ", ((0 == llcolor4.mV[VX]) && (0 == llcolor4.mV[VY]) && (0 == llcolor4.mV[VZ])&& (1.0f == llcolor4.mV[VW])));
llcolor4.setToWhite();
ensure("setToWhite:Fail to set the white ", ((1.f == llcolor4.mV[VX]) && (1.f == llcolor4.mV[VY]) && (1.f == llcolor4.mV[VZ])&& (1.0f == llcolor4.mV[VW])));
}
template<> template<>
void v4color_object::test<4>()
{
F32 r = 0x20, g = 0xFFFF, b = 0xFF, a = 0xAF;
LLColor4 llcolor4;
llcolor4.setVec(r,g,b);
ensure("1:setVec:Fail to set the values ", ((r == llcolor4.mV[VX]) && (g == llcolor4.mV[VY]) && (b == llcolor4.mV[VZ])&& (1.f == llcolor4.mV[VW])));
llcolor4.setVec(r,g,b,a);
ensure("2:setVec:Fail to set the values ", ((r == llcolor4.mV[VX]) && (g == llcolor4.mV[VY]) && (b == llcolor4.mV[VZ])&& (a == llcolor4.mV[VW])));
LLColor4 llcolor4a;
llcolor4a.setVec(llcolor4);
ensure_equals("3:setVec:Fail to set the values ", llcolor4a,llcolor4);
LLColor3 llcolor3(-2.23f,1.01f,42.3f);
llcolor4a.setVec(llcolor3);
ensure("4:setVec:Fail to set the values ", ((llcolor3.mV[VX] == llcolor4a.mV[VX]) && (llcolor3.mV[VY] == llcolor4a.mV[VY]) && (llcolor3.mV[VZ] == llcolor4a.mV[VZ])));
F32 val = -.33f;
llcolor4a.setVec(llcolor3,val);
ensure("4:setVec:Fail to set the values ", ((llcolor3.mV[VX] == llcolor4a.mV[VX]) && (llcolor3.mV[VY] == llcolor4a.mV[VY]) && (llcolor3.mV[VZ] == llcolor4a.mV[VZ]) && (val == llcolor4a.mV[VW])));
const F32 vec[4] = {.112f ,23.2f, -4.2f, -.0001f};
LLColor4 llcolor4c;
llcolor4c.setVec(vec);
ensure("5:setVec:Fail to initialize ", ((vec[0] == llcolor4c.mV[VX]) && (vec[1] == llcolor4c.mV[VY]) && (vec[2] == llcolor4c.mV[VZ])&& (vec[3] == llcolor4c.mV[VW])));
U8 r1 = 0xF2, g1 = 0xFA, b1= 0xBF;
LLColor4U color4u(r1,g1,b1);
llcolor4.setVec(color4u);
const F32 SCALE = 1.f/255.f;
F32 r2 = r1*SCALE, g2 = g1* SCALE, b2 = b1* SCALE;
ensure("6:setVec:Fail to initialize ", ((r2 == llcolor4.mV[VX]) && (g2 == llcolor4.mV[VY]) && (b2 == llcolor4.mV[VZ])));
}
template<> template<>
void v4color_object::test<5>()
{
F32 alpha = 0xAF;
LLColor4 llcolor4;
llcolor4.setAlpha(alpha);
ensure("setAlpha:Fail to initialize ", (alpha == llcolor4.mV[VW]));
}
template<> template<>
void v4color_object::test<6>()
{
F32 r = 0x20, g = 0xFFFF, b = 0xFF;
LLColor4 llcolor4(r,g,b);
ensure("magVecSquared:Fail ", is_approx_equal(llcolor4.magVecSquared(), (r*r + g*g + b*b)));
ensure("magVec:Fail ", is_approx_equal(llcolor4.magVec(), fsqrtf(r*r + g*g + b*b)));
}
template<> template<>
void v4color_object::test<7>()
{
F32 r = 0x20, g = 0xFFFF, b = 0xFF;
LLColor4 llcolor4(r,g,b);
F32 vecMag = llcolor4.normVec();
F32 mag = fsqrtf(r*r + g*g + b*b);
F32 oomag = 1.f / mag;
F32 val1 = r * oomag, val2 = g * oomag, val3 = b * oomag;
ensure("1:normVec failed ", (is_approx_equal(val1, llcolor4.mV[0]) && is_approx_equal(val2, llcolor4.mV[1]) && is_approx_equal(val3, llcolor4.mV[2]) && is_approx_equal(vecMag, mag)));
}
template<> template<>
void v4color_object::test<8>()
{
LLColor4 llcolor4;
ensure("1:isOpaque failed ",(1 == llcolor4.isOpaque()));
F32 r = 0x20, g = 0xFFFF, b = 0xFF,a = 1.f;
llcolor4.setVec(r,g,b,a);
ensure("2:isOpaque failed ",(1 == llcolor4.isOpaque()));
a = 2.f;
llcolor4.setVec(r,g,b,a);
ensure("3:isOpaque failed ",(0 == llcolor4.isOpaque()));
}
template<> template<>
void v4color_object::test<9>()
{
F32 r = 0x20, g = 0xFFFF, b = 0xFF;
LLColor4 llcolor4(r,g,b);
ensure("1:operator [] failed",( r == llcolor4[0]));
ensure("2:operator [] failed",( g == llcolor4[1]));
ensure("3:operator [] failed",( b == llcolor4[2]));
r = 0xA20, g = 0xFBFF, b = 0xFFF;
llcolor4.setVec(r,g,b);
F32 &ref1 = llcolor4[0];
ensure("4:operator [] failed",( ref1 == llcolor4[0]));
F32 &ref2 = llcolor4[1];
ensure("5:operator [] failed",( ref2 == llcolor4[1]));
F32 &ref3 = llcolor4[2];
ensure("6:operator [] failed",( ref3 == llcolor4[2]));
}
template<> template<>
void v4color_object::test<10>()
{
F32 r = 0x20, g = 0xFFFF, b = 0xFF;
LLColor3 llcolor3(r,g,b);
LLColor4 llcolor4a,llcolor4b;
llcolor4a = llcolor3;
ensure("Operator=:Fail to initialize ", ((llcolor3.mV[0] == llcolor4a.mV[VX]) && (llcolor3.mV[1] == llcolor4a.mV[VY]) && (llcolor3.mV[2] == llcolor4a.mV[VZ])));
LLSD sd = llcolor4a.getValue();
llcolor4b = LLColor4(sd);
ensure_equals("Operator= LLSD:Fail ", llcolor4a, llcolor4b);
}
template<> template<>
void v4color_object::test<11>()
{
F32 r = 0x20, g = 0xFFFF, b = 0xFF;
std::ostringstream stream1, stream2;
LLColor4 llcolor4a(r,g,b),llcolor4b;
stream1 << llcolor4a;
llcolor4b.setVec(r,g,b);
stream2 << llcolor4b;
ensure("operator << failed ", (stream1.str() == stream2.str()));
}
template<> template<>
void v4color_object::test<12>()
{
F32 r1 = 0x20, g1 = 0xFFFF, b1 = 0xFF;
F32 r2 = 0xABF, g2 = 0xFB, b2 = 0xFFF;
LLColor4 llcolor4a(r1,g1,b1),llcolor4b(r2,g2,b2),llcolor4c;
llcolor4c = llcolor4b + llcolor4a;
ensure("operator+:Fail to Add the values ", (is_approx_equal(r1+r2,llcolor4c.mV[VX]) && is_approx_equal(g1+g2,llcolor4c.mV[VY]) && is_approx_equal(b1+b2,llcolor4c.mV[VZ])));
llcolor4b += llcolor4a;
ensure("operator+=:Fail to Add the values ", (is_approx_equal(r1+r2,llcolor4b.mV[VX]) && is_approx_equal(g1+g2,llcolor4b.mV[VY]) && is_approx_equal(b1+b2,llcolor4b.mV[VZ])));
}
template<> template<>
void v4color_object::test<13>()
{
F32 r1 = 0x20, g1 = 0xFFFF, b1 = 0xFF;
F32 r2 = 0xABF, g2 = 0xFB, b2 = 0xFFF;
LLColor4 llcolor4a(r1,g1,b1),llcolor4b(r2,g2,b2),llcolor4c;
llcolor4c = llcolor4a - llcolor4b;
ensure("operator-:Fail to subtract the values ", (is_approx_equal(r1-r2,llcolor4c.mV[VX]) && is_approx_equal(g1-g2,llcolor4c.mV[VY]) && is_approx_equal(b1-b2,llcolor4c.mV[VZ])));
llcolor4a -= llcolor4b;
ensure("operator-=:Fail to subtract the values ", (is_approx_equal(r1-r2,llcolor4a.mV[VX]) && is_approx_equal(g1-g2,llcolor4a.mV[VY]) && is_approx_equal(b1-b2,llcolor4a.mV[VZ])));
}
template<> template<>
void v4color_object::test<14>()
{
F32 r1 = 0x20, g1 = 0xFFFF, b1 = 0xFF;
F32 r2 = 0xABF, g2 = 0xFB, b2 = 0xFFF;
LLColor4 llcolor4a(r1,g1,b1),llcolor4b(r2,g2,b2),llcolor4c;
llcolor4c = llcolor4a * llcolor4b;
ensure("1:operator*:Fail to multiply the values", (is_approx_equal(r1*r2,llcolor4c.mV[VX]) && is_approx_equal(g1*g2,llcolor4c.mV[VY]) && is_approx_equal(b1*b2,llcolor4c.mV[VZ])));
F32 mulVal = 3.33f;
llcolor4c = llcolor4a * mulVal;
ensure("2:operator*:Fail ", (is_approx_equal(r1*mulVal,llcolor4c.mV[VX]) && is_approx_equal(g1*mulVal,llcolor4c.mV[VY]) && is_approx_equal(b1*mulVal,llcolor4c.mV[VZ])));
llcolor4c = mulVal * llcolor4a;
ensure("3:operator*:Fail to multiply the values", (is_approx_equal(r1*mulVal,llcolor4c.mV[VX]) && is_approx_equal(g1*mulVal,llcolor4c.mV[VY]) && is_approx_equal(b1*mulVal,llcolor4c.mV[VZ])));
llcolor4a *= mulVal;
ensure("4:operator*=:Fail to multiply the values ", (is_approx_equal(r1*mulVal,llcolor4a.mV[VX]) && is_approx_equal(g1*mulVal,llcolor4a.mV[VY]) && is_approx_equal(b1*mulVal,llcolor4a.mV[VZ])));
LLColor4 llcolor4d(r1,g1,b1),llcolor4e(r2,g2,b2);
llcolor4e *= llcolor4d;
ensure("5:operator*=:Fail to multiply the values ", (is_approx_equal(r1*r2,llcolor4e.mV[VX]) && is_approx_equal(g1*g2,llcolor4e.mV[VY]) && is_approx_equal(b1*b2,llcolor4e.mV[VZ])));
}
template<> template<>
void v4color_object::test<15>()
{
F32 r = 0x20, g = 0xFFFF, b = 0xFF,a = 0x30;
F32 div = 12.345f;
LLColor4 llcolor4a(r,g,b,a),llcolor4b;
llcolor4b = llcolor4a % div;//chnage only alpha value nor r,g,b;
ensure("1operator%:Fail ", (is_approx_equal(r,llcolor4b.mV[VX]) && is_approx_equal(g,llcolor4b.mV[VY]) && is_approx_equal(b,llcolor4b.mV[VZ])&& is_approx_equal(div*a,llcolor4b.mV[VW])));
llcolor4b = div % llcolor4a;
ensure("2operator%:Fail ", (is_approx_equal(r,llcolor4b.mV[VX]) && is_approx_equal(g,llcolor4b.mV[VY]) && is_approx_equal(b,llcolor4b.mV[VZ])&& is_approx_equal(div*a,llcolor4b.mV[VW])));
llcolor4a %= div;
ensure("operator%=:Fail ", (is_approx_equal(a*div,llcolor4a.mV[VW])));
}
template<> template<>
void v4color_object::test<16>()
{
F32 r = 0x20, g = 0xFFFF, b = 0xFF,a = 0x30;
LLColor4 llcolor4a(r,g,b,a),llcolor4b;
llcolor4b = llcolor4a;
ensure("1:operator== failed to ensure the equality ", (llcolor4b == llcolor4a));
F32 r1 = 0x2, g1 = 0xFF, b1 = 0xFA;
LLColor3 llcolor3(r1,g1,b1);
llcolor4b = llcolor3;
ensure("2:operator== failed to ensure the equality ", (llcolor4b == llcolor3));
ensure("2:operator!= failed to ensure the equality ", (llcolor4a != llcolor3));
}
template<> template<>
void v4color_object::test<17>()
{
F32 r = 0x20, g = 0xFFFF, b = 0xFF;
LLColor4 llcolor4a(r,g,b),llcolor4b;
LLColor3 llcolor3 = vec4to3(llcolor4a);
ensure("vec4to3:Fail to convert vec4 to vec3 ", (is_approx_equal(llcolor3.mV[VX],llcolor4a.mV[VX]) && is_approx_equal(llcolor3.mV[VY],llcolor4a.mV[VY]) && is_approx_equal(llcolor3.mV[VZ],llcolor4a.mV[VZ])));
llcolor4b = vec3to4(llcolor3);
ensure_equals("vec3to4:Fail to convert vec3 to vec4 ", llcolor4b, llcolor4a);
}
template<> template<>
void v4color_object::test<18>()
{
F32 r1 = 0x20, g1 = 0xFFFF, b1 = 0xFF, val = 0x20;
F32 r2 = 0xABF, g2 = 0xFB, b2 = 0xFFF;
LLColor4 llcolor4a(r1,g1,b1),llcolor4b(r2,g2,b2),llcolor4c;
llcolor4c = lerp(llcolor4a,llcolor4b,val);
ensure("lerp:Fail ", (is_approx_equal(r1 + (r2 - r1)* val,llcolor4c.mV[VX]) && is_approx_equal(g1 + (g2 - g1)* val,llcolor4c.mV[VY]) && is_approx_equal(b1 + (b2 - b1)* val,llcolor4c.mV[VZ])));
}
template<> template<>
void v4color_object::test<19>()
{
F32 r = 12.0f, g = -2.3f, b = 1.32f, a = 5.0f;
LLColor4 llcolor4a(r,g,b,a),llcolor4b;
std::string color("red");
LLColor4::parseColor(color, &llcolor4b);
ensure_equals("1:parseColor() failed to parse the color value ", llcolor4b, LLColor4::red);
color = "12.0, -2.3, 1.32, 5.0";
LLColor4::parseColor(color, &llcolor4b);
llcolor4a = llcolor4a * (1.f / 255.f);
ensure_equals("2:parseColor() failed to parse the color value ", llcolor4a,llcolor4b);
color = "yellow5";
llcolor4a.setVec(r,g,b);
LLColor4::parseColor(color, &llcolor4a);
ensure_equals("3:parseColor() failed to parse the color value ", llcolor4a, LLColor4::yellow5);
}
template<> template<>
void v4color_object::test<20>()
{
F32 r = 12.0f, g = -2.3f, b = 1.32f, a = 5.0f;
LLColor4 llcolor4a(r,g,b,a),llcolor4b;
std::string color("12.0, -2.3, 1.32, 5.0");
LLColor4::parseColor4(color, &llcolor4b);
ensure_equals("parseColor4() failed to parse the color value ", llcolor4a, llcolor4b);
}
}

View File

@ -0,0 +1,342 @@
/**
* @file v4coloru_tut.cpp
* @author Adroit
* @date 2007-03
* @brief v4coloru test cases.
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "../test/lltut.h"
#include "llsd.h"
#include "../v4coloru.h"
namespace tut
{
struct v4coloru_data
{
};
typedef test_group<v4coloru_data> v4coloru_test;
typedef v4coloru_test::object v4coloru_object;
tut::v4coloru_test v4coloru_testcase("v4coloru");
template<> template<>
void v4coloru_object::test<1>()
{
LLColor4U llcolor4u;
ensure("1:LLColor4u:Fail to initialize ", ((0 == llcolor4u.mV[VX]) && (0 == llcolor4u.mV[VY]) && (0 == llcolor4u.mV[VZ])&& (255 == llcolor4u.mV[VW])));
U8 r = 0x12, g = 0xFF, b = 0xAF, a = 0x23;
LLColor4U llcolor4u1(r,g,b);
ensure("2:LLColor4u:Fail to initialize ", ((r == llcolor4u1.mV[VX]) && (g == llcolor4u1.mV[VY]) && (b == llcolor4u1.mV[VZ])&& (255 == llcolor4u1.mV[VW])));
LLColor4U llcolor4u2(r,g,b,a);
ensure("3:LLColor4u:Fail to initialize ", ((r == llcolor4u2.mV[VX]) && (g == llcolor4u2.mV[VY]) && (b == llcolor4u2.mV[VZ])&& (a == llcolor4u2.mV[VW])));
const U8 vec[4] = {0x12,0xFF,0xAF,0x23};
LLColor4U llcolor4u3(vec);
ensure("4:LLColor4u:Fail to initialize ", ((vec[0] == llcolor4u3.mV[VX]) && (vec[1] == llcolor4u3.mV[VY]) && (vec[2] == llcolor4u3.mV[VZ])&& (vec[3] == llcolor4u3.mV[VW])));
LLSD sd = llcolor4u3.getValue();
LLColor4U llcolor4u4(sd);
ensure_equals("5:LLColor4u (LLSD) Failed ", llcolor4u4, llcolor4u3);
}
template<> template<>
void v4coloru_object::test<2>()
{
LLColor4U llcolor4ua(1, 2, 3, 4);
LLSD sd = llcolor4ua.getValue();
LLColor4U llcolor4u;
llcolor4u.setValue(sd);
ensure_equals("setValue(LLSD)/getValue Failed ", llcolor4u, llcolor4ua);
}
template<> template<>
void v4coloru_object::test<3>()
{
U8 r = 0x12, g = 0xFF, b = 0xAF, a = 0x23;
LLColor4U llcolor4u(r,g,b,a);
llcolor4u.setToBlack();
ensure("setToBlack:Fail to set black ", ((0 == llcolor4u.mV[VX]) && (0 == llcolor4u.mV[VY]) && (0 == llcolor4u.mV[VZ])&& (255 == llcolor4u.mV[VW])));
llcolor4u.setToWhite();
ensure("setToWhite:Fail to white ", ((255 == llcolor4u.mV[VX]) && (255 == llcolor4u.mV[VY]) && (255 == llcolor4u.mV[VZ])&& (255 == llcolor4u.mV[VW])));
}
template<> template<>
void v4coloru_object::test<4>()
{
U8 r = 0x12, g = 0xFF, b = 0xAF, a = 0x23;
LLColor4U llcolor4ua(r,g,b,a);
LLSD sd = llcolor4ua.getValue();
LLColor4U llcolor4u = (LLColor4U)sd;
ensure_equals("Operator=(LLSD) Failed ", llcolor4u, llcolor4ua);
}
template<> template<>
void v4coloru_object::test<5>()
{
U8 r = 0x12, g = 0xFF, b = 0xAF, a = 0x23;
LLColor4U llcolor4u;
llcolor4u.setVec(r,g,b,a);
ensure("1:setVec:Fail to set the values ", ((r == llcolor4u.mV[VX]) && (g == llcolor4u.mV[VY]) && (b == llcolor4u.mV[VZ])&& (a == llcolor4u.mV[VW])));
llcolor4u.setToBlack();
llcolor4u.setVec(r,g,b);
ensure("2:setVec:Fail to set the values ", ((r == llcolor4u.mV[VX]) && (g == llcolor4u.mV[VY]) && (b == llcolor4u.mV[VZ])&& (255 == llcolor4u.mV[VW])));
LLColor4U llcolor4u1;
llcolor4u1.setVec(llcolor4u);
ensure_equals("3:setVec:Fail to set the values ", llcolor4u1,llcolor4u);
const U8 vec[4] = {0x12,0xFF,0xAF,0x23};
LLColor4U llcolor4u2;
llcolor4u2.setVec(vec);
ensure("4:setVec:Fail to set the values ", ((vec[0] == llcolor4u2.mV[VX]) && (vec[1] == llcolor4u2.mV[VY]) && (vec[2] == llcolor4u2.mV[VZ])&& (vec[3] == llcolor4u2.mV[VW])));
}
template<> template<>
void v4coloru_object::test<6>()
{
U8 alpha = 0x12;
LLColor4U llcolor4u;
llcolor4u.setAlpha(alpha);
ensure("setAlpha:Fail to set alpha value ", (alpha == llcolor4u.mV[VW]));
}
template<> template<>
void v4coloru_object::test<7>()
{
U8 r = 0x12, g = 0xFF, b = 0xAF;
LLColor4U llcolor4u(r,g,b);
ensure("magVecSquared:Fail ", is_approx_equal(llcolor4u.magVecSquared(), (F32)(r*r + g*g + b*b)));
ensure("magVec:Fail ", is_approx_equal(llcolor4u.magVec(), fsqrtf(r*r + g*g + b*b)));
}
template<> template<>
void v4coloru_object::test<8>()
{
U8 r = 0x12, g = 0xFF, b = 0xAF;
std::ostringstream stream1, stream2;
LLColor4U llcolor4u1(r,g,b),llcolor4u2;
stream1 << llcolor4u1;
llcolor4u2.setVec(r,g,b);
stream2 << llcolor4u2;
ensure("operator << failed ", (stream1.str() == stream2.str()));
}
template<> template<>
void v4coloru_object::test<9>()
{
U8 r1 = 0x12, g1 = 0xFF, b1 = 0xAF;
U8 r2 = 0x1C, g2 = 0x9A, b2 = 0x1B;
LLColor4U llcolor4u1(r1,g1,b1), llcolor4u2(r2,g2,b2),llcolor4u3;
llcolor4u3 = llcolor4u1 + llcolor4u2;
ensure_equals(
"1a.operator+:Fail to Add the values ",
llcolor4u3.mV[VX],
(U8)(r1+r2));
ensure_equals(
"1b.operator+:Fail to Add the values ",
llcolor4u3.mV[VY],
(U8)(g1+g2));
ensure_equals(
"1c.operator+:Fail to Add the values ",
llcolor4u3.mV[VZ],
(U8)(b1+b2));
llcolor4u2 += llcolor4u1;
ensure_equals(
"2a.operator+=:Fail to Add the values ",
llcolor4u2.mV[VX],
(U8)(r1+r2));
ensure_equals(
"2b.operator+=:Fail to Add the values ",
llcolor4u2.mV[VY],
(U8)(g1+g2));
ensure_equals(
"2c.operator+=:Fail to Add the values ",
llcolor4u2.mV[VZ],
(U8)(b1+b2));
}
template<> template<>
void v4coloru_object::test<10>()
{
U8 r1 = 0x12, g1 = 0xFF, b1 = 0xAF;
U8 r2 = 0x1C, g2 = 0x9A, b2 = 0x1B;
LLColor4U llcolor4u1(r1,g1,b1), llcolor4u2(r2,g2,b2),llcolor4u3;
llcolor4u3 = llcolor4u1 - llcolor4u2;
ensure_equals(
"1a. operator-:Fail to Add the values ",
llcolor4u3.mV[VX],
(U8)(r1-r2));
ensure_equals(
"1b. operator-:Fail to Add the values ",
llcolor4u3.mV[VY],
(U8)(g1-g2));
ensure_equals(
"1c. operator-:Fail to Add the values ",
llcolor4u3.mV[VZ],
(U8)(b1-b2));
llcolor4u1 -= llcolor4u2;
ensure_equals(
"2a. operator-=:Fail to Add the values ",
llcolor4u1.mV[VX],
(U8)(r1-r2));
ensure_equals(
"2b. operator-=:Fail to Add the values ",
llcolor4u1.mV[VY],
(U8)(g1-g2));
ensure_equals(
"2c. operator-=:Fail to Add the values ",
llcolor4u1.mV[VZ],
(U8)(b1-b2));
}
template<> template<>
void v4coloru_object::test<11>()
{
U8 r1 = 0x12, g1 = 0xFF, b1 = 0xAF;
U8 r2 = 0x1C, g2 = 0x9A, b2 = 0x1B;
LLColor4U llcolor4u1(r1,g1,b1), llcolor4u2(r2,g2,b2),llcolor4u3;
llcolor4u3 = llcolor4u1 * llcolor4u2;
ensure_equals(
"1a. operator*:Fail to multiply the values",
llcolor4u3.mV[VX],
(U8)(r1*r2));
ensure_equals(
"1b. operator*:Fail to multiply the values",
llcolor4u3.mV[VY],
(U8)(g1*g2));
ensure_equals(
"1c. operator*:Fail to multiply the values",
llcolor4u3.mV[VZ],
(U8)(b1*b2));
U8 mulVal = 123;
llcolor4u1 *= mulVal;
ensure_equals(
"2a. operator*=:Fail to multiply the values",
llcolor4u1.mV[VX],
(U8)(r1*mulVal));
ensure_equals(
"2b. operator*=:Fail to multiply the values",
llcolor4u1.mV[VY],
(U8)(g1*mulVal));
ensure_equals(
"2c. operator*=:Fail to multiply the values",
llcolor4u1.mV[VZ],
(U8)(b1*mulVal));
}
template<> template<>
void v4coloru_object::test<12>()
{
U8 r = 0x12, g = 0xFF, b = 0xAF;
LLColor4U llcolor4u(r,g,b),llcolor4u1;
llcolor4u1 = llcolor4u;
ensure("operator== failed to ensure the equality ", (llcolor4u1 == llcolor4u));
llcolor4u1.setToBlack();
ensure("operator!= failed to ensure the equality ", (llcolor4u1 != llcolor4u));
}
template<> template<>
void v4coloru_object::test<13>()
{
U8 r = 0x12, g = 0xFF, b = 0xAF, a = 12;
LLColor4U llcolor4u(r,g,b,a);
U8 modVal = 45;
llcolor4u %= modVal;
ensure_equals("operator%=:Fail ", llcolor4u.mV[VW], (U8)(a * modVal));
}
template<> template<>
void v4coloru_object::test<14>()
{
U8 r = 0x12, g = 0xFF, b = 0xAF, a = 12;
LLColor4U llcolor4u1(r,g,b,a);
std::string color("12, 23, 132, 50");
LLColor4U::parseColor4U(color, &llcolor4u1);
ensure("parseColor4U() failed to parse the color value ", ((12 == llcolor4u1.mV[VX]) && (23 == llcolor4u1.mV[VY]) && (132 == llcolor4u1.mV[VZ])&& (50 == llcolor4u1.mV[VW])));
color = "12, 23, 132";
ensure("2:parseColor4U() failed to parse the color value ", (FALSE == LLColor4U::parseColor4U(color, &llcolor4u1)));
color = "12";
ensure("2:parseColor4U() failed to parse the color value ", (FALSE == LLColor4U::parseColor4U(color, &llcolor4u1)));
}
template<> template<>
void v4coloru_object::test<15>()
{
U8 r = 12, g = 123, b = 3, a = 2;
LLColor4U llcolor4u(r,g,b,a),llcolor4u1;
const F32 fVal = 3.f;
llcolor4u1 = llcolor4u.multAll(fVal);
ensure("multAll:Fail to multiply ", (((U8)llround(r * fVal) == llcolor4u1.mV[VX]) && (U8)llround(g * fVal) == llcolor4u1.mV[VY]
&& ((U8)llround(b * fVal) == llcolor4u1.mV[VZ])&& ((U8)llround(a * fVal) == llcolor4u1.mV[VW])));
}
template<> template<>
void v4coloru_object::test<16>()
{
U8 r1 = 12, g1 = 123, b1 = 3, a1 = 2;
U8 r2 = 23, g2 = 230, b2 = 124, a2 = 255;
LLColor4U llcolor4u(r1,g1,b1,a1),llcolor4u1(r2,g2,b2,a2);
llcolor4u1 = llcolor4u1.addClampMax(llcolor4u);
ensure("1:addClampMax():Fail to add the value ", ((r1+r2 == llcolor4u1.mV[VX]) && (255 == llcolor4u1.mV[VY]) && (b1+b2 == llcolor4u1.mV[VZ])&& (255 == llcolor4u1.mV[VW])));
r1 = 132, g1 = 3, b1 = 3, a1 = 2;
r2 = 123, g2 = 230, b2 = 154, a2 = 25;
LLColor4U llcolor4u2(r1,g1,b1,a1),llcolor4u3(r2,g2,b2,a2);
llcolor4u3 = llcolor4u3.addClampMax(llcolor4u2);
ensure("2:addClampMax():Fail to add the value ", ((255 == llcolor4u3.mV[VX]) && (g1+g2 == llcolor4u3.mV[VY]) && (b1+b2 == llcolor4u3.mV[VZ])&& (a1+a2 == llcolor4u3.mV[VW])));
}
template<> template<>
void v4coloru_object::test<17>()
{
F32 r = 23.f, g = 12.32f, b = -12.3f;
LLColor3 color3(r,g,b);
LLColor4U llcolor4u;
llcolor4u.setVecScaleClamp(color3);
const S32 MAX_COLOR = 255;
F32 color_scale_factor = MAX_COLOR/r;
S32 r2 = llround(r * color_scale_factor);
S32 g2 = llround(g * color_scale_factor);
ensure("setVecScaleClamp():Fail to add the value ", ((r2 == llcolor4u.mV[VX]) && (g2 == llcolor4u.mV[VY]) && (0 == llcolor4u.mV[VZ])&& (255 == llcolor4u.mV[VW])));
}
}

View File

@ -0,0 +1,388 @@
/**
* @file v4math_tut.cpp
* @author Adroit
* @date 2007-03
* @brief v4math test cases.
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "../test/lltut.h"
#include "llsd.h"
#include "../llquaternion.h"
#include "../m4math.h"
#include "../v4math.h"
namespace tut
{
struct v4math_data
{
};
typedef test_group<v4math_data> v4math_test;
typedef v4math_test::object v4math_object;
tut::v4math_test v4math_testcase("v4math");
template<> template<>
void v4math_object::test<1>()
{
LLVector4 vec4;
ensure("1:LLVector4:Fail to initialize " ,((0 == vec4.mV[VX]) && (0 == vec4.mV[VY]) && (0 == vec4.mV[VZ])&& (1.0f == vec4.mV[VW])));
F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f;
LLVector4 vec4a(x,y,z);
ensure("2:LLVector4:Fail to initialize " ,((x == vec4a.mV[VX]) && (y == vec4a.mV[VY]) && (z == vec4a.mV[VZ])&& (1.0f == vec4a.mV[VW])));
LLVector4 vec4b(x,y,z,w);
ensure("3:LLVector4:Fail to initialize " ,((x == vec4b.mV[VX]) && (y == vec4b.mV[VY]) && (z == vec4b.mV[VZ])&& (w == vec4b.mV[VW])));
const F32 vec[4] = {.112f ,23.2f, -4.2f, -.0001f};
LLVector4 vec4c(vec);
ensure("4:LLVector4:Fail to initialize " ,((vec[0] == vec4c.mV[VX]) && (vec[1] == vec4c.mV[VY]) && (vec[2] == vec4c.mV[VZ])&& (vec[3] == vec4c.mV[VW])));
LLVector3 vec3(-2.23f,1.01f,42.3f);
LLVector4 vec4d(vec3);
ensure("5:LLVector4:Fail to initialize " ,((vec3.mV[VX] == vec4d.mV[VX]) && (vec3.mV[VY] == vec4d.mV[VY]) && (vec3.mV[VZ] == vec4d.mV[VZ])&& (1.f == vec4d.mV[VW])));
F32 w1 = -.234f;
LLVector4 vec4e(vec3,w1);
ensure("6:LLVector4:Fail to initialize " ,((vec3.mV[VX] == vec4e.mV[VX]) && (vec3.mV[VY] == vec4e.mV[VY]) && (vec3.mV[VZ] == vec4e.mV[VZ])&& (w1 == vec4e.mV[VW])));
}
template<> template<>
void v4math_object::test<2>()
{
F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f;
LLVector4 vec4;
vec4.setVec(x,y,z);
ensure("1:setVec:Fail to initialize " ,((x == vec4.mV[VX]) && (y == vec4.mV[VY]) && (z == vec4.mV[VZ])&& (1.0f == vec4.mV[VW])));
vec4.clearVec();
ensure("2:clearVec:Fail " ,((0 == vec4.mV[VX]) && (0 == vec4.mV[VY]) && (0 == vec4.mV[VZ])&& (1.0f == vec4.mV[VW])));
vec4.setVec(x,y,z,w);
ensure("3:setVec:Fail to initialize " ,((x == vec4.mV[VX]) && (y == vec4.mV[VY]) && (z == vec4.mV[VZ])&& (w == vec4.mV[VW])));
vec4.zeroVec();
ensure("4:zeroVec:Fail " ,((0 == vec4.mV[VX]) && (0 == vec4.mV[VY]) && (0 == vec4.mV[VZ])&& (0 == vec4.mV[VW])));
LLVector3 vec3(-2.23f,1.01f,42.3f);
vec4.clearVec();
vec4.setVec(vec3);
ensure("5:setVec:Fail to initialize " ,((vec3.mV[VX] == vec4.mV[VX]) && (vec3.mV[VY] == vec4.mV[VY]) && (vec3.mV[VZ] == vec4.mV[VZ])&& (1.f == vec4.mV[VW])));
F32 w1 = -.234f;
vec4.zeroVec();
vec4.setVec(vec3,w1);
ensure("6:setVec:Fail to initialize " ,((vec3.mV[VX] == vec4.mV[VX]) && (vec3.mV[VY] == vec4.mV[VY]) && (vec3.mV[VZ] == vec4.mV[VZ])&& (w1 == vec4.mV[VW])));
const F32 vec[4] = {.112f ,23.2f, -4.2f, -.0001f};
LLVector4 vec4a;
vec4a.setVec(vec);
ensure("7:setVec:Fail to initialize " ,((vec[0] == vec4a.mV[VX]) && (vec[1] == vec4a.mV[VY]) && (vec[2] == vec4a.mV[VZ])&& (vec[3] == vec4a.mV[VW])));
}
template<> template<>
void v4math_object::test<3>()
{
F32 x = 10.f, y = -2.3f, z = -.023f;
LLVector4 vec4(x,y,z);
ensure("magVec:Fail ", is_approx_equal(vec4.magVec(), fsqrtf(x*x + y*y + z*z)));
ensure("magVecSquared:Fail ", is_approx_equal(vec4.magVecSquared(), (x*x + y*y + z*z)));
}
template<> template<>
void v4math_object::test<4>()
{
F32 x = 10.f, y = -2.3f, z = -.023f;
LLVector4 vec4(x,y,z);
F32 mag = vec4.normVec();
mag = 1.f/ mag;
ensure("1:normVec: Fail " ,is_approx_equal(mag*x,vec4.mV[VX]) && is_approx_equal(mag*y, vec4.mV[VY])&& is_approx_equal(mag*z, vec4.mV[VZ]));
x = 0.000000001f, y = 0.000000001f, z = 0.000000001f;
vec4.clearVec();
vec4.setVec(x,y,z);
mag = vec4.normVec();
ensure("2:normVec: Fail " ,is_approx_equal(mag*x,vec4.mV[VX]) && is_approx_equal(mag*y, vec4.mV[VY])&& is_approx_equal(mag*z, vec4.mV[VZ]));
}
template<> template<>
void v4math_object::test<5>()
{
F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f;
LLVector4 vec4(x,y,z,w);
vec4.abs();
ensure("abs:Fail " ,((x == vec4.mV[VX]) && (-y == vec4.mV[VY]) && (-z == vec4.mV[VZ])&& (-w == vec4.mV[VW])));
vec4.clearVec();
ensure("isExactlyClear:Fail " ,(TRUE == vec4.isExactlyClear()));
vec4.zeroVec();
ensure("isExactlyZero:Fail " ,(TRUE == vec4.isExactlyZero()));
}
template<> template<>
void v4math_object::test<6>()
{
F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f;
LLVector4 vec4(x,y,z,w),vec4a;
vec4a = vec4.scaleVec(vec4);
ensure("scaleVec:Fail " ,(is_approx_equal(x*x, vec4a.mV[VX]) && is_approx_equal(y*y, vec4a.mV[VY]) && is_approx_equal(z*z, vec4a.mV[VZ])&& is_approx_equal(w*w, vec4a.mV[VW])));
}
template<> template<>
void v4math_object::test<7>()
{
F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f;
LLVector4 vec4(x,y,z,w);
ensure("1:operator [] failed " ,( x == vec4[0]));
ensure("2:operator [] failed " ,( y == vec4[1]));
ensure("3:operator [] failed " ,( z == vec4[2]));
ensure("4:operator [] failed " ,( w == vec4[3]));
x = 23.f, y = -.2361f, z = 3.25;
vec4.setVec(x,y,z);
F32 &ref1 = vec4[0];
ensure("5:operator [] failed " ,( ref1 == vec4[0]));
F32 &ref2 = vec4[1];
ensure("6:operator [] failed " ,( ref2 == vec4[1]));
F32 &ref3 = vec4[2];
ensure("7:operator [] failed " ,( ref3 == vec4[2]));
F32 &ref4 = vec4[3];
ensure("8:operator [] failed " ,( ref4 == vec4[3]));
}
template<> template<>
void v4math_object::test<8>()
{
F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f;
const F32 val[16] = {
1.f, 2.f, 3.f, 0.f,
.34f, .1f, -.5f, 0.f,
2.f, 1.23f, 1.234f, 0.f,
.89f, 0.f, 0.f, 0.f
};
LLMatrix4 mat(val);
LLVector4 vec4(x,y,z,w),vec4a;
vec4.rotVec(mat);
vec4a.setVec(x,y,z,w);
vec4a.rotVec(mat);
ensure_equals("1:rotVec: Fail " ,vec4a, vec4);
F32 a = 2.32f, b = -23.2f, c = -34.1112f, d = 1.010112f;
LLQuaternion q(a,b,c,d);
LLVector4 vec4b(a,b,c,d),vec4c;
vec4b.rotVec(q);
vec4c.setVec(a, b, c, d);
vec4c.rotVec(q);
ensure_equals("2:rotVec: Fail " ,vec4b, vec4c);
}
template<> template<>
void v4math_object::test<9>()
{
F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f;
LLVector4 vec4(x,y,z,w),vec4a;;
std::ostringstream stream1, stream2;
stream1 << vec4;
vec4a.setVec(x,y,z,w);
stream2 << vec4a;
ensure("operator << failed",(stream1.str() == stream2.str()));
}
template<> template<>
void v4math_object::test<10>()
{
F32 x1 = 1.f, y1 = 2.f, z1 = -1.1f, w1 = .23f;
F32 x2 = 1.2f, y2 = 2.5f, z2 = 1.f, w2 = 1.3f;
LLVector4 vec4(x1,y1,z1,w1),vec4a(x2,y2,z2,w2),vec4b;
vec4b = vec4a + vec4;
ensure("1:operator+:Fail to initialize " ,(is_approx_equal(x1+x2,vec4b.mV[VX]) && is_approx_equal(y1+y2,vec4b.mV[VY]) && is_approx_equal(z1+z2,vec4b.mV[VZ])));
x1 = -2.45f, y1 = 2.1f, z1 = 3.0f;
vec4.clearVec();
vec4a.clearVec();
vec4.setVec(x1,y1,z1);
vec4a +=vec4;
ensure_equals("2:operator+=: Fail to initialize", vec4a,vec4);
vec4a += vec4;
ensure("3:operator+=:Fail to initialize " ,(is_approx_equal(2*x1,vec4a.mV[VX]) && is_approx_equal(2*y1,vec4a.mV[VY]) && is_approx_equal(2*z1,vec4a.mV[VZ])));
}
template<> template<>
void v4math_object::test<11>()
{
F32 x1 = 1.f, y1 = 2.f, z1 = -1.1f, w1 = .23f;
F32 x2 = 1.2f, y2 = 2.5f, z2 = 1.f, w2 = 1.3f;
LLVector4 vec4(x1,y1,z1,w1),vec4a(x2,y2,z2,w2),vec4b;
vec4b = vec4a - vec4;
ensure("1:operator-:Fail to initialize " ,(is_approx_equal(x2-x1,vec4b.mV[VX]) && is_approx_equal(y2-y1,vec4b.mV[VY]) && is_approx_equal(z2-z1,vec4b.mV[VZ])));
x1 = -2.45f, y1 = 2.1f, z1 = 3.0f;
vec4.clearVec();
vec4a.clearVec();
vec4.setVec(x1,y1,z1);
vec4a -=vec4;
ensure_equals("2:operator-=: Fail to initialize" , vec4a,-vec4);
vec4a -=vec4;
ensure("3:operator-=:Fail to initialize " ,(is_approx_equal(-2*x1,vec4a.mV[VX]) && is_approx_equal(-2*y1,vec4a.mV[VY]) && is_approx_equal(-2*z1,vec4a.mV[VZ])));
}
template<> template<>
void v4math_object::test<12>()
{
F32 x1 = 1.f, y1 = 2.f, z1 = -1.1f;
F32 x2 = 1.2f, y2 = 2.5f, z2 = 1.f;
LLVector4 vec4(x1,y1,z1),vec4a(x2,y2,z2);
F32 res = vec4 * vec4a;
ensure("1:operator* failed " ,is_approx_equal(res, x1*x2 + y1*y2 + z1*z2));
vec4a.clearVec();
F32 mulVal = 4.2f;
vec4a = vec4 * mulVal;
ensure("2:operator* failed " ,is_approx_equal(x1*mulVal,vec4a.mV[VX]) && is_approx_equal(y1*mulVal, vec4a.mV[VY])&& is_approx_equal(z1*mulVal, vec4a.mV[VZ]));
vec4a.clearVec();
vec4a = mulVal * vec4 ;
ensure("3:operator* failed " ,is_approx_equal(x1*mulVal, vec4a.mV[VX]) && is_approx_equal(y1*mulVal, vec4a.mV[VY])&& is_approx_equal(z1*mulVal, vec4a.mV[VZ]));
vec4 *= mulVal;
ensure("4:operator*= failed " ,is_approx_equal(x1*mulVal, vec4.mV[VX]) && is_approx_equal(y1*mulVal, vec4.mV[VY])&& is_approx_equal(z1*mulVal, vec4.mV[VZ]));
}
template<> template<>
void v4math_object::test<13>()
{
F32 x1 = 1.f, y1 = 2.f, z1 = -1.1f;
F32 x2 = 1.2f, y2 = 2.5f, z2 = 1.f;
LLVector4 vec4(x1,y1,z1),vec4a(x2,y2,z2),vec4b;
vec4b = vec4 % vec4a;
ensure("1:operator% failed " ,is_approx_equal(y1*z2 - y2*z1, vec4b.mV[VX]) && is_approx_equal(z1*x2 -z2*x1, vec4b.mV[VY]) && is_approx_equal(x1*y2-x2*y1, vec4b.mV[VZ]));
vec4 %= vec4a;
ensure_equals("operator%= failed " ,vec4,vec4b);
}
template<> template<>
void v4math_object::test<14>()
{
F32 x = 1.f, y = 2.f, z = -1.1f,div = 4.2f;
F32 t = 1.f / div;
LLVector4 vec4(x,y,z), vec4a;
vec4a = vec4/div;
ensure("1:operator/ failed " ,is_approx_equal(x*t, vec4a.mV[VX]) && is_approx_equal(y*t, vec4a.mV[VY])&& is_approx_equal(z*t, vec4a.mV[VZ]));
x = 1.23f, y = 4.f, z = -2.32f;
vec4.clearVec();
vec4a.clearVec();
vec4.setVec(x,y,z);
vec4a = vec4/div;
ensure("2:operator/ failed " ,is_approx_equal(x*t, vec4a.mV[VX]) && is_approx_equal(y*t, vec4a.mV[VY])&& is_approx_equal(z*t, vec4a.mV[VZ]));
vec4 /= div;
ensure("3:operator/ failed " ,is_approx_equal(x*t, vec4.mV[VX]) && is_approx_equal(y*t, vec4.mV[VY])&& is_approx_equal(z*t, vec4.mV[VZ]));
}
template<> template<>
void v4math_object::test<15>()
{
F32 x = 1.f, y = 2.f, z = -1.1f;
LLVector4 vec4(x,y,z), vec4a;
ensure("operator!= failed " ,(vec4 != vec4a));
vec4a = vec4;
ensure("operator== failed " ,(vec4 ==vec4a));
}
template<> template<>
void v4math_object::test<16>()
{
F32 x = 1.f, y = 2.f, z = -1.1f;
LLVector4 vec4(x,y,z), vec4a;
vec4a = - vec4;
ensure("operator- failed " , (vec4 == - vec4a));
}
template<> template<>
void v4math_object::test<17>()
{
F32 x = 1.f, y = 2.f, z = -1.1f,epsilon = .23425f;
LLVector4 vec4(x,y,z), vec4a(x,y,z);
ensure("1:are_parallel: Fail " ,(TRUE == are_parallel(vec4a,vec4,epsilon)));
x = 21.f, y = 12.f, z = -123.1f;
vec4a.clearVec();
vec4a.setVec(x,y,z);
ensure("2:are_parallel: Fail " ,(FALSE == are_parallel(vec4a,vec4,epsilon)));
}
template<> template<>
void v4math_object::test<18>()
{
F32 x = 1.f, y = 2.f, z = -1.1f;
F32 angle1, angle2;
LLVector4 vec4(x,y,z), vec4a(x,y,z);
angle1 = angle_between(vec4, vec4a);
vec4.normVec();
vec4a.normVec();
angle2 = acos(vec4 * vec4a);
ensure_approximately_equals("1:angle_between: Fail " ,angle1,angle2,8);
F32 x1 = 21.f, y1 = 2.23f, z1 = -1.1f;
LLVector4 vec4b(x,y,z), vec4c(x1,y1,z1);
angle1 = angle_between(vec4b, vec4c);
vec4b.normVec();
vec4c.normVec();
angle2 = acos(vec4b * vec4c);
ensure_approximately_equals("2:angle_between: Fail " ,angle1,angle2,8);
}
template<> template<>
void v4math_object::test<19>()
{
F32 x1 =-2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, y2 = 1.f, z2 = 1.f;
F32 val1,val2;
LLVector4 vec4(x1,y1,z1),vec4a(x2,y2,z2);
val1 = dist_vec(vec4,vec4a);
val2 = fsqrtf((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2));
ensure_equals("dist_vec: Fail ",val2, val1);
val1 = dist_vec_squared(vec4,vec4a);
val2 =((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2));
ensure_equals("dist_vec_squared: Fail ",val2, val1);
}
template<> template<>
void v4math_object::test<20>()
{
F32 x1 =-2.3f, y1 = 2.f,z1 = 1.2f, w1 = -.23f, x2 = 1.3f, y2 = 1.f, z2 = 1.f,w2 = .12f;
F32 val = 2.3f,val1,val2,val3,val4;
LLVector4 vec4(x1,y1,z1,w1),vec4a(x2,y2,z2,w2);
val1 = x1 + (x2 - x1)* val;
val2 = y1 + (y2 - y1)* val;
val3 = z1 + (z2 - z1)* val;
val4 = w1 + (w2 - w1)* val;
LLVector4 vec4b = lerp(vec4,vec4a,val);
ensure("lerp failed", ((val1 ==vec4b.mV[VX])&& (val2 ==vec4b.mV[VY]) && (val3 ==vec4b.mV[VZ])&& (val4 ==vec4b.mV[VW])));
}
template<> template<>
void v4math_object::test<21>()
{
F32 x = 1.f, y = 2.f, z = -1.1f;
LLVector4 vec4(x,y,z);
LLVector3 vec3 = vec4to3(vec4);
ensure("vec4to3 failed", ((x == vec3.mV[VX])&& (y == vec3.mV[VY]) && (z == vec3.mV[VZ])));
LLVector4 vec4a = vec3to4(vec3);
ensure_equals("vec3to4 failed",vec4a,vec4);
}
template<> template<>
void v4math_object::test<22>()
{
F32 x = 1.f, y = 2.f, z = -1.1f;
LLVector4 vec4(x,y,z);
LLSD llsd = vec4.getValue();
LLVector3 vec3(llsd);
LLVector4 vec4a = vec3to4(vec3);
ensure_equals("getValue failed",vec4a,vec4);
}
}

View File

@ -0,0 +1,251 @@
/**
* @file xform_tut.cpp
* @author Adroit
* @date March 2007
* @brief Test cases for LLXform
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "../test/lltut.h"
#include "../xform.h"
namespace tut
{
struct xform_test
{
};
typedef test_group<xform_test> xform_test_t;
typedef xform_test_t::object xform_test_object_t;
tut::xform_test_t tut_xform_test("xform_test");
//test case for init(), getParent(), getRotation(), getPositionW(), getWorldRotation() fns.
template<> template<>
void xform_test_object_t::test<1>()
{
LLXform xform_obj;
LLVector3 emptyVec(0.f,0.f,0.f);
LLVector3 initialScaleVec(1.f,1.f,1.f);
ensure("LLXform empty constructor failed: ", !xform_obj.getParent() && !xform_obj.isChanged() &&
xform_obj.getPosition() == emptyVec &&
(xform_obj.getRotation()).isIdentity() &&
xform_obj.getScale() == initialScaleVec &&
xform_obj.getPositionW() == emptyVec &&
(xform_obj.getWorldRotation()).isIdentity() &&
!xform_obj.getScaleChildOffset());
}
// test cases for
// setScale(const LLVector3& scale)
// setScale(const F32 x, const F32 y, const F32 z)
// setRotation(const F32 x, const F32 y, const F32 z)
// setPosition(const F32 x, const F32 y, const F32 z)
// getLocalMat4(LLMatrix4 &mat)
template<> template<>
void xform_test_object_t::test<2>()
{
LLMatrix4 llmat4;
LLXform xform_obj;
F32 x = 3.6f;
F32 y = 5.5f;
F32 z = 4.2f;
F32 w = 0.f;
F32 posz = z + 2.122f;
LLVector3 vec(x, y, z);
xform_obj.setScale(x, y, z);
xform_obj.setPosition(x, y, posz);
ensure("setScale failed: ", xform_obj.getScale() == vec);
vec.setVec(x, y, posz);
ensure("getPosition failed: ", xform_obj.getPosition() == vec);
x = x * 2.f;
y = y + 2.3f;
z = posz * 4.f;
vec.setVec(x, y, z);
xform_obj.setPositionX(x);
xform_obj.setPositionY(y);
xform_obj.setPositionZ(z);
ensure("setPositionX/Y/Z failed: ", xform_obj.getPosition() == vec);
xform_obj.setScaleChildOffset(TRUE);
ensure("setScaleChildOffset failed: ", xform_obj.getScaleChildOffset());
vec.setVec(x, y, z);
xform_obj.addPosition(vec);
vec += vec;
ensure("addPosition failed: ", xform_obj.getPosition() == vec);
xform_obj.setScale(vec);
ensure("setScale vector failed: ", xform_obj.getScale() == vec);
LLQuaternion quat(x, y, z, w);
xform_obj.setRotation(quat);
ensure("setRotation quat failed: ", xform_obj.getRotation() == quat);
xform_obj.setRotation(x, y, z, w);
ensure("getRotation 2 failed: ", xform_obj.getRotation() == quat);
xform_obj.setRotation(x, y, z);
quat.setQuat(x,y,z);
ensure("setRotation xyz failed: ", xform_obj.getRotation() == quat);
// LLXform::setRotation(const F32 x, const F32 y, const F32 z)
// Does normalization
// LLXform::setRotation(const F32 x, const F32 y, const F32 z, const F32 s)
// Simply copies the individual values - does not do any normalization.
// Is that the expected behavior?
}
// test cases for inline BOOL setParent(LLXform *parent) and getParent() fn.
template<> template<>
void xform_test_object_t::test<3>()
{
LLXform xform_obj;
LLXform par;
LLXform grandpar;
xform_obj.setParent(&par);
par.setParent(&grandpar);
ensure("setParent/getParent failed: ", &par == xform_obj.getParent());
ensure("getRoot failed: ", &grandpar == xform_obj.getRoot());
ensure("isRoot failed: ", grandpar.isRoot() && !par.isRoot() && !xform_obj.isRoot());
ensure("isRootEdit failed: ", grandpar.isRootEdit() && !par.isRootEdit() && !xform_obj.isRootEdit());
}
template<> template<>
void xform_test_object_t::test<4>()
{
LLXform xform_obj;
xform_obj.setChanged(LLXform::TRANSLATED | LLXform::ROTATED | LLXform::SCALED);
ensure("setChanged/isChanged failed: ", xform_obj.isChanged());
xform_obj.clearChanged(LLXform::TRANSLATED | LLXform::ROTATED | LLXform::SCALED);
ensure("clearChanged failed: ", !xform_obj.isChanged());
LLVector3 llvect3(12.4f, -5.6f, 0.34f);
xform_obj.setScale(llvect3);
ensure("setScale did not set SCALED flag: ", xform_obj.isChanged(LLXform::SCALED));
xform_obj.setPosition(1.2f, 2.3f, 3.4f);
ensure("setScale did not set TRANSLATED flag: ", xform_obj.isChanged(LLXform::TRANSLATED));
ensure("TRANSLATED reset SCALED flag: ", xform_obj.isChanged(LLXform::TRANSLATED | LLXform::SCALED));
xform_obj.clearChanged(LLXform::SCALED);
ensure("reset SCALED failed: ", !xform_obj.isChanged(LLXform::SCALED));
xform_obj.setRotation(1, 2, 3, 4);
ensure("ROTATION flag not set ", xform_obj.isChanged(LLXform::TRANSLATED | LLXform::ROTATED));
xform_obj.setScale(llvect3);
ensure("ROTATION flag not set ", xform_obj.isChanged(LLXform::MOVED));
}
//to test init() and getWorldMatrix() fns.
template<> template<>
void xform_test_object_t::test<5>()
{
LLXformMatrix formMatrix_obj;
formMatrix_obj.init();
LLMatrix4 mat4_obj;
ensure("1. The value is not NULL", 1.f == formMatrix_obj.getWorldMatrix().mMatrix[0][0]);
ensure("2. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[0][1]);
ensure("3. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[0][2]);
ensure("4. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[0][3]);
ensure("5. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[1][0]);
ensure("6. The value is not NULL", 1.f == formMatrix_obj.getWorldMatrix().mMatrix[1][1]);
ensure("7. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[1][2]);
ensure("8. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[1][3]);
ensure("9. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[2][0]);
ensure("10. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[2][1]);
ensure("11. The value is not NULL", 1.f == formMatrix_obj.getWorldMatrix().mMatrix[2][2]);
ensure("12. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[2][3]);
ensure("13. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[3][0]);
ensure("14. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[3][1]);
ensure("15. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[3][2]);
ensure("16. The value is not NULL", 1.f == formMatrix_obj.getWorldMatrix().mMatrix[3][3]);
}
//to test mMin.clearVec() and mMax.clearVec() fns
template<> template<>
void xform_test_object_t::test<6>()
{
LLXformMatrix formMatrix_obj;
formMatrix_obj.init();
LLVector3 llmin_vec3;
LLVector3 llmax_vec3;
formMatrix_obj.getMinMax(llmin_vec3, llmax_vec3);
ensure("1. The value is not NULL", 0.f == llmin_vec3.mV[0]);
ensure("2. The value is not NULL", 0.f == llmin_vec3.mV[1]);
ensure("3. The value is not NULL", 0.f == llmin_vec3.mV[2]);
ensure("4. The value is not NULL", 0.f == llmin_vec3.mV[0]);
ensure("5. The value is not NULL", 0.f == llmin_vec3.mV[1]);
ensure("6. The value is not NULL", 0.f == llmin_vec3.mV[2]);
}
//test case of update() fn.
template<> template<>
void xform_test_object_t::test<7>()
{
LLXformMatrix formMatrix_obj;
LLXformMatrix parent;
LLVector3 llvecpos(1.0, 2.0, 3.0);
LLVector3 llvecpospar(10.0, 20.0, 30.0);
formMatrix_obj.setPosition(llvecpos);
parent.setPosition(llvecpospar);
LLVector3 llvecparentscale(1.0, 2.0, 0);
parent.setScaleChildOffset(TRUE);
parent.setScale(llvecparentscale);
LLQuaternion quat(1, 2, 3, 4);
LLQuaternion quatparent(5, 6, 7, 8);
formMatrix_obj.setRotation(quat);
parent.setRotation(quatparent);
formMatrix_obj.setParent(&parent);
parent.update();
formMatrix_obj.update();
LLVector3 worldPos = llvecpos;
worldPos.scaleVec(llvecparentscale);
worldPos *= quatparent;
worldPos += llvecpospar;
LLQuaternion worldRot = quat * quatparent;
ensure("getWorldPosition failed: ", formMatrix_obj.getWorldPosition() == worldPos);
ensure("getWorldRotation failed: ", formMatrix_obj.getWorldRotation() == worldRot);
ensure("getWorldPosition for parent failed: ", parent.getWorldPosition() == llvecpospar);
ensure("getWorldRotation for parent failed: ", parent.getWorldRotation() == quatparent);
}
}

View File

@ -56,9 +56,7 @@ LLColor3::LLColor3(const LLVector4 &a)
LLColor3::LLColor3(const LLSD &sd)
{
mV[0] = (F32) sd[0].asReal();
mV[1] = (F32) sd[1].asReal();
mV[2] = (F32) sd[2].asReal();
setValue(sd);
}
const LLColor3& LLColor3::operator=(const LLColor4 &a)

View File

@ -185,14 +185,6 @@ void LLVector3::snap(S32 sig_digits)
mV[VZ] = snap_to_sig_figs(mV[VZ], sig_digits);
}
std::ostream& operator<<(std::ostream& s, const LLVector3 &a)
{
s << "{ " << a.mV[VX] << ", " << a.mV[VY] << ", " << a.mV[VZ] << " }";
return s;
}
const LLVector3& LLVector3::rotVec(const LLMatrix3 &mat)
{
*this = *this * mat;

View File

@ -556,4 +556,10 @@ inline BOOL are_parallel(const LLVector3 &a, const LLVector3 &b, F32 epsilon)
return FALSE;
}
inline std::ostream& operator<<(std::ostream& s, const LLVector3 &a)
{
s << "{ " << a.mV[VX] << ", " << a.mV[VY] << ", " << a.mV[VZ] << " }";
return s;
}
#endif

View File

@ -208,43 +208,43 @@ list(APPEND llmessage_SOURCE_FILES ${llmessage_HEADER_FILES})
add_library (llmessage ${llmessage_SOURCE_FILES})
target_link_libraries(
llmessage
${CURL_LIBRARIES}
${CARES_LIBRARIES}
${OPENSSL_LIBRARIES}
${CRYPTO_LIBRARIES}
${XMLRPCEPI_LIBRARIES}
)
llmessage
${CURL_LIBRARIES}
${CARES_LIBRARIES}
${OPENSSL_LIBRARIES}
${CRYPTO_LIBRARIES}
${XMLRPCEPI_LIBRARIES}
)
IF (NOT LINUX AND VIEWER)
# When building the viewer the tests links against the shared objects.
# These can not be found when we try to run the tests, so we had to disable them, for the viewer build.
# TODO: Can someone with viewer knowledge figure out how to make these find the correct so.
SET(llmessage_TEST_SOURCE_FILES
# llhttpclientadapter.cpp
lltrustedmessageservice.cpp
lltemplatemessagedispatcher.cpp
# tests
SET(llmessage_TEST_SOURCE_FILES
# llhttpclientadapter.cpp
llmime.cpp
llnamevalue.cpp
lltrustedmessageservice.cpp
lltemplatemessagedispatcher.cpp
llregionpresenceverifier.cpp
)
)
LL_ADD_PROJECT_UNIT_TESTS(llmessage "${llmessage_TEST_SOURCE_FILES}")
# set(TEST_DEBUG on)
set(test_libs
${LLMESSAGE_LIBRARIES}
${WINDOWS_LIBRARIES}
${LLVFS_LIBRARIES}
${LLMATH_LIBRARIES}
${LLCOMMON_LIBRARIES}
set(test_libs
${LLMESSAGE_LIBRARIES}
${WINDOWS_LIBRARIES}
${LLVFS_LIBRARIES}
${LLMATH_LIBRARIES}
${LLCOMMON_LIBRARIES}
${GOOGLEMOCK_LIBRARIES}
)
)
LL_ADD_INTEGRATION_TEST(
llsdmessage
"llsdmessage.cpp"
"${test_libs}"
${PYTHON_EXECUTABLE}
"${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llsdmessage_peer.py"
)
LL_ADD_INTEGRATION_TEST(
llsdmessage
"llsdmessage.cpp"
"${test_libs}"
${PYTHON_EXECUTABLE}
"${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llsdmessage_peer.py"
)
LL_ADD_PROJECT_UNIT_TESTS(llmessage "${llmessage_TEST_SOURCE_FILES}")
ENDIF (NOT LINUX AND VIEWER)
LL_ADD_INTEGRATION_TEST(llhost "" "${test_libs}")

View File

@ -728,9 +728,9 @@ static S32 buildBlock(U8* buffer, S32 buffer_size, const LLMessageBlock* templat
// out gracefully from this function. XXXTBD
llerrs << "buildBlock failed. "
<< "Attempted to pack "
<< result + mvci.getSize()
<< (result + mvci.getSize())
<< " bytes into a buffer with size "
<< buffer_size << "." << llendl
<< buffer_size << "." << llendl;
}
}
}

View File

@ -678,12 +678,7 @@ BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender
// default to 0s.
U32 size = mvci.getSize();
std::vector<U8> data(size);
if(size)
{
// Nonsense test to get past GCC 4.3.1 bug with -O3
memset(&(data[0]), 0, size);
}
std::vector<U8> data(size, 0);
cur_data_block->addData(mvci.getName(), &(data[0]),
size, mvci.getType());
}

View File

@ -0,0 +1,247 @@
/**
* @file llhost_tut.cpp
* @author Adroit
* @date 2007-02
* @brief llhost test cases.
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "../llhost.h"
#include "../test/lltut.h"
namespace tut
{
struct host_data
{
};
typedef test_group<host_data> host_test;
typedef host_test::object host_object;
tut::host_test host_testcase("llhost");
template<> template<>
void host_object::test<1>()
{
LLHost host;
ensure("IP address is not NULL", (0 == host.getAddress()) && (0 == host.getPort()) && !host.isOk());
}
template<> template<>
void host_object::test<2>()
{
U32 ip_addr = 0xc098017d;
U32 port = 8080;
LLHost host(ip_addr, port);
ensure("IP address is invalid", ip_addr == host.getAddress());
ensure("Port Number is invalid", port == host.getPort());
ensure("IP address and port number both should be ok", host.isOk());
}
template<> template<>
void host_object::test<3>()
{
const char* str = "192.168.1.1";
U32 port = 8080;
LLHost host(str, port);
ensure("IP address could not be processed", (host.getAddress() == ip_string_to_u32(str)));
ensure("Port Number is invalid", (port == host.getPort()));
}
template<> template<>
void host_object::test<4>()
{
U32 ip = ip_string_to_u32("192.168.1.1");
U32 port = 22;
U64 ip_port = (((U64) ip) << 32) | port;
LLHost host(ip_port);
ensure("IP address is invalid", ip == host.getAddress());
ensure("Port Number is invalid", port == host.getPort());
}
template<> template<>
void host_object::test<5>()
{
std::string ip_port_string = "192.168.1.1:8080";
U32 ip = ip_string_to_u32("192.168.1.1");
U32 port = 8080;
LLHost host(ip_port_string);
ensure("IP address from IP:port is invalid", ip == host.getAddress());
ensure("Port Number from from IP:port is invalid", port == host.getPort());
}
template<> template<>
void host_object::test<6>()
{
U32 ip = 0xc098017d, port = 8080;
LLHost host;
host.set(ip,port);
ensure("IP address is invalid", (ip == host.getAddress()));
ensure("Port Number is invalid", (port == host.getPort()));
}
template<> template<>
void host_object::test<7>()
{
const char* str = "192.168.1.1";
U32 port = 8080, ip;
LLHost host;
host.set(str,port);
ip = ip_string_to_u32(str);
ensure("IP address is invalid", (ip == host.getAddress()));
ensure("Port Number is invalid", (port == host.getPort()));
str = "64.233.187.99";
ip = ip_string_to_u32(str);
host.setAddress(str);
ensure("IP address is invalid", (ip == host.getAddress()));
ip = 0xc098017b;
host.setAddress(ip);
ensure("IP address is invalid", (ip == host.getAddress()));
// should still use the old port
ensure("Port Number is invalid", (port == host.getPort()));
port = 8084;
host.setPort(port);
ensure("Port Number is invalid", (port == host.getPort()));
// should still use the old address
ensure("IP address is invalid", (ip == host.getAddress()));
}
template<> template<>
void host_object::test<8>()
{
const std::string str("192.168.1.1");
U32 port = 8080;
LLHost host;
host.set(str,port);
std::string ip_string = host.getIPString();
ensure("Function Failed", (ip_string == str));
std::string ip_string_port = host.getIPandPort();
ensure("Function Failed", (ip_string_port == "192.168.1.1:8080"));
}
// getHostName() and setHostByName
template<> template<>
void host_object::test<9>()
{
std::string hostStr = "google.com";
LLHost host;
host.setHostByName(hostStr);
// reverse DNS will likely result in appending of some
// sub-domain to the main hostname. so look for
// the main domain name and not do the exact compare
std::string hostname = host.getHostName();
ensure("getHostName failed", hostname.find(hostStr) != std::string::npos);
}
// setHostByName for dotted IP
template<> template<>
void host_object::test<10>()
{
std::string hostStr = "64.233.167.99";
LLHost host;
host.setHostByName(hostStr);
ensure("SetHostByName for dotted IP Address failed", host.getAddress() == ip_string_to_u32(hostStr.c_str()));
}
template<> template<>
void host_object::test<11>()
{
LLHost host1(0xc098017d, 8080);
LLHost host2 = host1;
ensure("Both IP addresses are not same", (host1.getAddress() == host2.getAddress()));
ensure("Both port numbers are not same", (host1.getPort() == host2.getPort()));
}
template<> template<>
void host_object::test<12>()
{
LLHost host1("192.168.1.1", 8080);
std::string str1 = "192.168.1.1:8080";
std::ostringstream stream;
stream << host1;
ensure("Operator << failed", ( stream.str()== str1));
// There is no istream >> llhost operator.
//std::istringstream is(stream.str());
//LLHost host2;
//is >> host2;
//ensure("Operator >> failed. Not compatible with <<", host1 == host2);
}
// operators ==, !=, <
template<> template<>
void host_object::test<13>()
{
U32 ip_addr = 0xc098017d;
U32 port = 8080;
LLHost host1(ip_addr, port);
LLHost host2(ip_addr, port);
ensure("operator== failed", host1 == host2);
// change port
host2.setPort(7070);
ensure("operator!= failed", host1 != host2);
// set port back to 8080 and change IP address now
host2.setPort(8080);
host2.setAddress(ip_addr+10);
ensure("operator!= failed", host1 != host2);
ensure("operator< failed", host1 < host2);
// set IP address back to same value and change port
host2.setAddress(ip_addr);
host2.setPort(host1.getPort() + 10);
ensure("operator< failed", host1 < host2);
}
// invalid ip address string
template<> template<>
void host_object::test<14>()
{
LLHost host1("10.0.1.2", 6143);
ensure("10.0.1.2 should be a valid address", host1.isOk());
LLHost host2("booger-brains", 6143);
ensure("booger-brains should be an invalid ip addess", !host2.isOk());
LLHost host3("255.255.255.255", 6143);
ensure("255.255.255.255 should be valid broadcast address", host3.isOk());
}
}

View File

@ -0,0 +1,451 @@
/**
* @file llmime_tut.cpp
* @author Phoenix
* @date 2006-12-24
* @brief BRIEF_DESC of llmime_tut.cpp
*
* $LicenseInfo:firstyear=2006&license=viewergpl$
*
* Copyright (c) 2006-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llsdserialize.h"
#include "../llmime.h"
#include "../test/lltut.h"
namespace tut
{
struct mime_index
{
};
typedef test_group<mime_index> mime_index_t;
typedef mime_index_t::object mime_index_object_t;
tut::mime_index_t tut_mime_index("mime_index");
template<> template<>
void mime_index_object_t::test<1>()
{
LLMimeIndex mime;
ensure("no headers", mime.headers().isUndefined());
ensure_equals("invalid offset", mime.offset(), -1);
ensure_equals("invalid content length", mime.contentLength(), -1);
ensure("no content type", mime.contentType().empty());
ensure("not multipart", !mime.isMultipart());
ensure_equals("no attachments", mime.subPartCount(), 0);
}
template<> template<>
void mime_index_object_t::test<2>()
{
const S32 CONTENT_LENGTH = 6000;
const S32 CONTENT_OFFSET = 100;
const std::string CONTENT_TYPE = std::string("image/j2c");
LLSD headers;
headers["Content-Length"] = CONTENT_LENGTH;
headers["Content-Type"] = CONTENT_TYPE;
LLMimeIndex mime(headers, CONTENT_OFFSET);
ensure("headers are map", mime.headers().isMap());
ensure_equals("offset", mime.offset(), CONTENT_OFFSET);
ensure_equals("content length", mime.contentLength(), CONTENT_LENGTH);
ensure_equals("type is image/j2c", mime.contentType(), CONTENT_TYPE);
ensure("not multipart", !mime.isMultipart());
ensure_equals("no attachments", mime.subPartCount(), 0);
}
template<> template<>
void mime_index_object_t::test<3>()
{
const S32 MULTI_CONTENT_LENGTH = 8000;
const S32 MULTI_CONTENT_OFFSET = 100;
const std::string MULTI_CONTENT_TYPE = std::string("multipart/mixed");
LLSD headers;
headers["Content-Length"] = MULTI_CONTENT_LENGTH;
headers["Content-Type"] = MULTI_CONTENT_TYPE;
LLMimeIndex mime(headers, MULTI_CONTENT_OFFSET);
llinfos << "headers: " << LLSDOStreamer<LLSDNotationFormatter>(headers)
<< llendl;
const S32 META_CONTENT_LENGTH = 700;
const S32 META_CONTENT_OFFSET = 69;
const std::string META_CONTENT_TYPE = std::string(
"text/llsd+xml");
headers = LLSD::emptyMap();
headers["Content-Length"] = META_CONTENT_LENGTH;
headers["Content-Type"] = META_CONTENT_TYPE;
LLMimeIndex meta(headers, META_CONTENT_OFFSET);
mime.attachSubPart(meta);
const S32 IMAGE_CONTENT_LENGTH = 6000;
const S32 IMAGE_CONTENT_OFFSET = 200;
const std::string IMAGE_CONTENT_TYPE = std::string("image/j2c");
headers = LLSD::emptyMap();
headers["Content-Length"] = IMAGE_CONTENT_LENGTH;
headers["Content-Type"] = IMAGE_CONTENT_TYPE;
LLMimeIndex image(headers, IMAGE_CONTENT_OFFSET);
mime.attachSubPart(image);
// make sure we have a valid multi-part
ensure("is multipart", mime.isMultipart());
ensure_equals("multi offset", mime.offset(), MULTI_CONTENT_OFFSET);
ensure_equals(
"multi content length",
mime.contentLength(),
MULTI_CONTENT_LENGTH);
ensure_equals("two attachments", mime.subPartCount(), 2);
// make sure ranged gets do the right thing with out of bounds
// sub-parts.
LLMimeIndex invalid_child(mime.subPart(-1));
ensure("no headers", invalid_child.headers().isUndefined());
ensure_equals("invalid offset", invalid_child.offset(), -1);
ensure_equals(
"invalid content length", invalid_child.contentLength(), -1);
ensure("no content type", invalid_child.contentType().empty());
ensure("not multipart", !invalid_child.isMultipart());
ensure_equals("no attachments", invalid_child.subPartCount(), 0);
invalid_child = mime.subPart(2);
ensure("no headers", invalid_child.headers().isUndefined());
ensure_equals("invalid offset", invalid_child.offset(), -1);
ensure_equals(
"invalid content length", invalid_child.contentLength(), -1);
ensure("no content type", invalid_child.contentType().empty());
ensure("not multipart", !invalid_child.isMultipart());
ensure_equals("no attachments", invalid_child.subPartCount(), 0);
}
template<> template<>
void mime_index_object_t::test<4>()
{
const S32 MULTI_CONTENT_LENGTH = 8000;
const S32 MULTI_CONTENT_OFFSET = 100;
const std::string MULTI_CONTENT_TYPE = std::string("multipart/mixed");
LLSD headers;
headers["Content-Length"] = MULTI_CONTENT_LENGTH;
headers["Content-Type"] = MULTI_CONTENT_TYPE;
LLMimeIndex mime(headers, MULTI_CONTENT_OFFSET);
const S32 META_CONTENT_LENGTH = 700;
const S32 META_CONTENT_OFFSET = 69;
const std::string META_CONTENT_TYPE = std::string(
"application/llsd+xml");
headers = LLSD::emptyMap();
headers["Content-Length"] = META_CONTENT_LENGTH;
headers["Content-Type"] = META_CONTENT_TYPE;
LLMimeIndex meta(headers, META_CONTENT_OFFSET);
mime.attachSubPart(meta);
const S32 IMAGE_CONTENT_LENGTH = 6000;
const S32 IMAGE_CONTENT_OFFSET = 200;
const std::string IMAGE_CONTENT_TYPE = std::string("image/j2c");
headers = LLSD::emptyMap();
headers["Content-Length"] = IMAGE_CONTENT_LENGTH;
headers["Content-Type"] = IMAGE_CONTENT_TYPE;
LLMimeIndex image(headers, IMAGE_CONTENT_OFFSET);
mime.attachSubPart(image);
// check what we have
ensure("is multipart", mime.isMultipart());
ensure_equals("multi offset", mime.offset(), MULTI_CONTENT_OFFSET);
ensure_equals(
"multi content length",
mime.contentLength(),
MULTI_CONTENT_LENGTH);
ensure_equals("two attachments", mime.subPartCount(), 2);
LLMimeIndex actual_meta = mime.subPart(0);
ensure_equals(
"meta type", actual_meta.contentType(), META_CONTENT_TYPE);
ensure_equals(
"meta offset", actual_meta.offset(), META_CONTENT_OFFSET);
ensure_equals(
"meta content length",
actual_meta.contentLength(),
META_CONTENT_LENGTH);
LLMimeIndex actual_image = mime.subPart(1);
ensure_equals(
"image type", actual_image.contentType(), IMAGE_CONTENT_TYPE);
ensure_equals(
"image offset", actual_image.offset(), IMAGE_CONTENT_OFFSET);
ensure_equals(
"image content length",
actual_image.contentLength(),
IMAGE_CONTENT_LENGTH);
}
/*
template<> template<>
void mime_index_object_t::test<5>()
{
}
template<> template<>
void mime_index_object_t::test<6>()
{
}
template<> template<>
void mime_index_object_t::test<7>()
{
}
template<> template<>
void mime_index_object_t::test<8>()
{
}
template<> template<>
void mime_index_object_t::test<>()
{
}
*/
}
namespace tut
{
struct mime_parse
{
};
typedef test_group<mime_parse> mime_parse_t;
typedef mime_parse_t::object mime_parse_object_t;
tut::mime_parse_t tut_mime_parse("mime_parse");
template<> template<>
void mime_parse_object_t::test<1>()
{
// parse one mime object
const std::string SERIALIZED_MIME("Content-Length: 200\r\nContent-Type: text/plain\r\n\r\naaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccc\r\n");
std::stringstream istr;
istr.str(SERIALIZED_MIME);
LLMimeIndex mime;
LLMimeParser parser;
bool ok = parser.parseIndex(istr, mime);
ensure("Parse successful.", ok);
ensure_equals("content type", mime.contentType(), "text/plain");
ensure_equals("content length", mime.contentLength(), 200);
ensure_equals("offset", mime.offset(), 49);
}
template<> template<>
void mime_parse_object_t::test<2>()
{
// make sure we only parse one.
const std::string SERIALIZED_MIME("Content-Length: 200\r\nContent-Type: text/plain\r\n\r\naaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccc\r\n\r\nContent-Length: 200\r\nContent-Type: text/plain\r\n\r\naaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccc\r\n\r\n");
std::stringstream istr;
istr.str(SERIALIZED_MIME);
LLMimeIndex mime;
LLMimeParser parser;
bool ok = parser.parseIndex(istr, mime);
ensure("Parse successful.", ok);
ensure("not multipart.", !mime.isMultipart());
ensure_equals("content type", mime.contentType(), "text/plain");
ensure_equals("content length", mime.contentLength(), 200);
ensure_equals("offset", mime.offset(), 49);
}
template<> template<>
void mime_parse_object_t::test<3>()
{
// test multi-part and lack of content length for some of it.
/*
Content-Type: multipart/mixed; boundary="segment"rnContent-Length: 148rnrn--segmentrnContent-Type: text/plainrnrnsome datarnrn--segmentrnContent-Type: text/xml; charset=UTF-8rnContent-Length: 22rnrn<llsd><undef /></llsd>rnrn
*/
const std::string SERIALIZED_MIME("Content-Type: multipart/mixed; boundary=\"segment\"\r\nContent-Length: 150\r\n\r\n--segment\r\nContent-Type: text/plain\r\n\r\nsome data\r\n\r\n--segment\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n");
std::stringstream istr;
istr.str(SERIALIZED_MIME);
LLMimeIndex mime;
LLMimeParser parser;
bool ok = parser.parseIndex(istr, mime);
ensure("Parse successful.", ok);
ensure("is multipart.", mime.isMultipart());
ensure_equals("sub-part count", mime.subPartCount(), 2);
ensure_equals("content length", mime.contentLength(), 150);
ensure_equals("data offset for multipart", mime.offset(), 74);
LLMimeIndex mime_plain(mime.subPart(0));
ensure_equals(
"first part type",
mime_plain.contentType(),
"text/plain");
ensure_equals(
"first part content length not known.",
mime_plain.contentLength(),
-1);
ensure_equals("first part offset", mime_plain.offset(), 113);
LLMimeIndex mime_xml(mime.subPart(1));
ensure_equals(
"second part type",
mime_xml.contentType(),
"text/xml; charset=UTF-8");
ensure_equals(
"second part content length",
mime_xml.contentLength(),
22);
ensure_equals("second part offset", mime_xml.offset(), 198);
}
template<> template<>
void mime_parse_object_t::test<4>()
{
// test multi-part, unquoted separator, and premature eof conditions
/*
Content-Type: multipart/mixed; boundary=segmentrnContent-Length: 220rnrn--segmentrnContent-Type: text/plainrnContent-Length: 55rnrnhow are you today?rnI do not know. I guess I am:n'fine'rnrn--segmentrnContent-Type: text/xml; charset=UTF-8rnContent-Length: 22rnrn<llsd><undef /></llsd>rnrn */
const std::string SERIALIZED_MIME("Content-Type: multipart/mixed; boundary=segment\r\nContent-Length: 220\r\n\r\n--segment\r\nContent-Type: text/plain\r\nContent-Length: 55\r\n\r\nhow are you today?\r\nI do not know. I guess I am:\n'fine'\r\n\r\n--segment\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n");
std::stringstream istr;
istr.str(SERIALIZED_MIME);
LLMimeIndex mime;
LLMimeParser parser;
bool ok = parser.parseIndex(istr, mime);
ensure("Parse successful.", ok);
ensure("is multipart.", mime.isMultipart());
ensure_equals("sub-part count", mime.subPartCount(), 2);
ensure_equals("content length", mime.contentLength(), 220);
ensure_equals("data offset for multipart", mime.offset(), 72);
LLMimeIndex mime_plain(mime.subPart(0));
ensure_equals(
"first part type",
mime_plain.contentType(),
"text/plain");
ensure_equals(
"first part content length",
mime_plain.contentLength(),
55);
ensure_equals("first part offset", mime_plain.offset(), 131);
LLMimeIndex mime_xml(mime.subPart(1));
ensure_equals(
"second part type",
mime_xml.contentType(),
"text/xml; charset=UTF-8");
ensure_equals(
"second part content length",
mime_xml.contentLength(),
22);
ensure_equals("second part offset", mime_xml.offset(), 262);
}
template<> template<>
void mime_parse_object_t::test<5>()
{
// test multi-part with multiple params
const std::string SERIALIZED_MIME("Content-Type: multipart/mixed; boundary=segment; comment=\"testing multiple params.\"\r\nContent-Length: 220\r\n\r\n--segment\r\nContent-Type: text/plain\r\nContent-Length: 55\r\n\r\nhow are you today?\r\nI do not know. I guess I am:\n'fine'\r\n\r\n--segment\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n");
std::stringstream istr;
istr.str(SERIALIZED_MIME);
LLMimeIndex mime;
LLMimeParser parser;
bool ok = parser.parseIndex(istr, mime);
ensure("Parse successful.", ok);
ensure("is multipart.", mime.isMultipart());
ensure_equals("sub-part count", mime.subPartCount(), 2);
ensure_equals("content length", mime.contentLength(), 220);
LLMimeIndex mime_plain(mime.subPart(0));
ensure_equals(
"first part type",
mime_plain.contentType(),
"text/plain");
ensure_equals(
"first part content length",
mime_plain.contentLength(),
55);
LLMimeIndex mime_xml(mime.subPart(1));
ensure_equals(
"second part type",
mime_xml.contentType(),
"text/xml; charset=UTF-8");
ensure_equals(
"second part content length",
mime_xml.contentLength(),
22);
}
template<> template<>
void mime_parse_object_t::test<6>()
{
// test multi-part with no specified boundary and eof
/*
Content-Type: multipart/relatedrnContent-Length: 220rnrn--rnContent-Type: text/plainrnContent-Length: 55rnrnhow are you today?rnI do not know. I guess I am:n'fine'rnrn--rnContent-Type: text/xml; charset=UTF-8rnContent-Length: 22rnrn<llsd><undef /></llsd>rnrn
*/
const std::string SERIALIZED_MIME("Content-Type: multipart/related\r\nContent-Length: 500\r\n\r\n--\r\nContent-Type: text/plain\r\nContent-Length: 55\r\n\r\nhow are you today?\r\nI do not know. I guess I am:\n'fine'\r\n\r\n--\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n");
std::stringstream istr;
istr.str(SERIALIZED_MIME);
LLMimeIndex mime;
LLMimeParser parser;
bool ok = parser.parseIndex(istr, mime);
ensure("Parse successful.", ok);
ensure("is multipart.", mime.isMultipart());
ensure_equals("sub-part count", mime.subPartCount(), 2);
ensure_equals("content length", mime.contentLength(), 500);
ensure_equals("data offset for multipart", mime.offset(), 56);
LLMimeIndex mime_plain(mime.subPart(0));
ensure_equals(
"first part type",
mime_plain.contentType(),
"text/plain");
ensure_equals(
"first part content length",
mime_plain.contentLength(),
55);
ensure_equals("first part offset", mime_plain.offset(), 108);
LLMimeIndex mime_xml(mime.subPart(1));
ensure_equals(
"second part type",
mime_xml.contentType(),
"text/xml; charset=UTF-8");
ensure_equals(
"second part content length",
mime_xml.contentLength(),
22);
ensure_equals("second part offset", mime_xml.offset(), 232);
}
/*
template<> template<>
void mime_parse_object_t::test<>()
{
}
template<> template<>
void mime_parse_object_t::test<>()
{
}
template<> template<>
void mime_parse_object_t::test<>()
{
}
template<> template<>
void mime_parse_object_t::test<>()
{
}
*/
}

View File

@ -0,0 +1,412 @@
/**
* @file llnamevalue_tut.cpp
* @author Adroit
* @date 2007-02
* @brief LLNameValue unit test
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llsdserialize.h"
#include "../llnamevalue.h"
#include "../test/lltut.h"
#if LL_WINDOWS
// disable unreachable code warnings
#pragma warning(disable: 4702)
#endif
namespace tut
{
struct namevalue_test
{
namevalue_test()
{
}
};
typedef test_group<namevalue_test> namevalue_t;
typedef namevalue_t::object namevalue_object_t;
tut::namevalue_t tut_namevalue("namevalue_test");
template<> template<>
void namevalue_object_t::test<1>()
{
// LLNameValue()
LLNameValue nValue;
ensure("mName should have been NULL", nValue.mName == NULL);
ensure("getTypeEnum failed",nValue.getTypeEnum() == NVT_NULL);
ensure("getClassEnum failed",nValue.getClassEnum() == NVC_NULL);
ensure("getSendtoEnum failed",nValue.getSendtoEnum() == NVS_NULL);
LLNameValue nValue1(" SecondLife ASSET RW SIM 232324343");
}
// LLNameValue(const char* data);
// LLNameValue(const char* name, const char* data, const char* type, const char* nvclass, const char* nvsendto,
// TNameValueCallback nvcb = NULL, void** user_data = NULL);
template<> template<>
void namevalue_object_t::test<2>()
{
LLNameValue nValue(" SecondLife ASSET RW S 232324343");
ensure("mName not set correctly", (0 == strcmp(nValue.mName,"SecondLife")));
ensure("getTypeEnum failed", nValue.getTypeEnum() == NVT_ASSET);
ensure("getClassEnum failed", nValue.getClassEnum() == NVC_READ_WRITE);
ensure("getSendtoEnum failed", nValue.getSendtoEnum() == NVS_SIM);
ensure("getString failed", (0==strcmp(nValue.getAsset(),"232324343")));
ensure("sendToData or sendToViewer failed", !nValue.sendToData() && !nValue.sendToViewer());
LLNameValue nValue1("\n\r SecondLife_1 STRING READ_WRITE SIM 232324343");
ensure("1. mName not set correctly", (0 == strcmp(nValue1.mName,"SecondLife_1")));
ensure("1. getTypeEnum failed", nValue1.getTypeEnum() == NVT_STRING);
ensure("1. getClassEnum failed", nValue1.getClassEnum() == NVC_READ_WRITE);
ensure("1. getSendtoEnum failed", nValue1.getSendtoEnum() == NVS_SIM);
ensure("1. getString failed", (0==strcmp(nValue1.getString(),"232324343")));
ensure("1. sendToData or sendToViewer failed", !nValue1.sendToData() && !nValue1.sendToViewer());
LLNameValue nValue2("SecondLife", "23.5", "F32", "R", "DS");
ensure("2. getTypeEnum failed", nValue2.getTypeEnum() == NVT_F32);
ensure("2. getClassEnum failed", nValue2.getClassEnum() == NVC_READ_ONLY);
ensure("2. getSendtoEnum failed", nValue2.getSendtoEnum() == NVS_DATA_SIM);
ensure("2. getF32 failed", *nValue2.getF32() == 23.5f);
ensure("2. sendToData or sendToViewer failed", nValue2.sendToData() && !nValue2.sendToViewer());
LLNameValue nValue3("SecondLife", "-43456787", "S32", "READ_ONLY", "SIM_SPACE");
ensure("3. getTypeEnum failed", nValue3.getTypeEnum() == NVT_S32);
ensure("3. getClassEnum failed", nValue3.getClassEnum() == NVC_READ_ONLY);
ensure("3. getSendtoEnum failed", nValue3.getSendtoEnum() == NVS_DATA_SIM);
ensure("3. getS32 failed", *nValue3.getS32() == -43456787);
ensure("sendToData or sendToViewer failed", nValue3.sendToData() && !nValue3.sendToViewer());
LLNameValue nValue4("SecondLife", "<1.0, 2.0, 3.0>", "VEC3", "RW", "SV");
LLVector3 llvec4(1.0, 2.0, 3.0);
ensure("4. getTypeEnum failed", nValue4.getTypeEnum() == NVT_VEC3);
ensure("4. getClassEnum failed", nValue4.getClassEnum() == NVC_READ_WRITE);
ensure("4. getSendtoEnum failed", nValue4.getSendtoEnum() == NVS_SIM_VIEWER);
ensure("4. getVec3 failed", *nValue4.getVec3() == llvec4);
ensure("4. sendToData or sendToViewer failed", !nValue4.sendToData() && nValue4.sendToViewer());
LLNameValue nValue5("SecondLife", "-1.0, 2.4, 3", "VEC3", "RW", "SIM_VIEWER");
LLVector3 llvec5(-1.0f, 2.4f, 3);
ensure("5. getTypeEnum failed", nValue5.getTypeEnum() == NVT_VEC3);
ensure("5. getClassEnum failed", nValue5.getClassEnum() == NVC_READ_WRITE);
ensure("5. getSendtoEnum failed", nValue5.getSendtoEnum() == NVS_SIM_VIEWER);
ensure("5. getVec3 failed", *nValue5.getVec3() == llvec5);
ensure("5. sendToData or sendToViewer failed", !nValue5.sendToData() && nValue5.sendToViewer());
LLNameValue nValue6("SecondLife", "89764323", "U32", "RW", "DSV");
ensure("6. getTypeEnum failed", nValue6.getTypeEnum() == NVT_U32);
ensure("6. getClassEnum failed", nValue6.getClassEnum() == NVC_READ_WRITE);
ensure("6. getSendtoEnum failed", nValue6.getSendtoEnum() == NVS_DATA_SIM_VIEWER);
ensure("6. getU32 failed", *nValue6.getU32() == 89764323);
ensure("6. sendToData or sendToViewer failed", nValue6.sendToData() && nValue6.sendToViewer());
LLNameValue nValue7("SecondLife", "89764323323232", "U64", "RW", "SIM_SPACE_VIEWER");
U64 u64_7 = U64L(89764323323232);
ensure("7. getTypeEnum failed", nValue7.getTypeEnum() == NVT_U64);
ensure("7. getClassEnum failed", nValue7.getClassEnum() == NVC_READ_WRITE);
ensure("7. getSendtoEnum failed", nValue7.getSendtoEnum() == NVS_DATA_SIM_VIEWER);
ensure("7. getU32 failed", *nValue7.getU64() == u64_7);
ensure("7. sendToData or sendToViewer failed", nValue7.sendToData() && nValue7.sendToViewer());
}
// LLNameValue(const char* name, const char* data, const char* type, const char* nvclass,
// TNameValueCallback nvcb = NULL, void** user_data = NULL);
template<> template<>
void namevalue_object_t::test<3>()
{
LLNameValue nValue("SecondLife", "232324343", "ASSET", "READ_WRITE");
ensure("mName not set correctly", (0 == strcmp(nValue.mName,"SecondLife")));
ensure("getTypeEnum failed", nValue.getTypeEnum() == NVT_ASSET);
ensure("getClassEnum failed", nValue.getClassEnum() == NVC_READ_WRITE);
ensure("getSendtoEnum failed", nValue.getSendtoEnum() == NVS_SIM);
ensure("getString failed", (0==strcmp(nValue.getAsset(),"232324343")));
LLNameValue nValue1("SecondLife", "232324343", "STRING", "READ_WRITE");
ensure("1. mName not set correctly", (0 == strcmp(nValue1.mName,"SecondLife")));
ensure("1. getTypeEnum failed", nValue1.getTypeEnum() == NVT_STRING);
ensure("1. getClassEnum failed", nValue1.getClassEnum() == NVC_READ_WRITE);
ensure("1. getSendtoEnum failed", nValue1.getSendtoEnum() == NVS_SIM);
ensure("1. getString failed", (0==strcmp(nValue1.getString(),"232324343")));
LLNameValue nValue2("SecondLife", "23.5", "F32", "R");
ensure("2. getTypeEnum failed", nValue2.getTypeEnum() == NVT_F32);
ensure("2. getClassEnum failed", nValue2.getClassEnum() == NVC_READ_ONLY);
ensure("2. getSendtoEnum failed", nValue2.getSendtoEnum() == NVS_SIM);
ensure("2. getF32 failed", *nValue2.getF32() == 23.5f);
LLNameValue nValue3("SecondLife", "-43456787", "S32", "READ_ONLY");
ensure("3. getTypeEnum failed", nValue3.getTypeEnum() == NVT_S32);
ensure("3. getClassEnum failed", nValue3.getClassEnum() == NVC_READ_ONLY);
ensure("3. getSendtoEnum failed", nValue3.getSendtoEnum() == NVS_SIM);
ensure("3. getS32 failed", *nValue3.getS32() == -43456787);
LLNameValue nValue4("SecondLife", "<1.0, 2.0, 3.0>", "VEC3", "RW");
LLVector3 llvec4(1.0, 2.0, 3.0);
ensure("4. getTypeEnum failed", nValue4.getTypeEnum() == NVT_VEC3);
ensure("4. getClassEnum failed", nValue4.getClassEnum() == NVC_READ_WRITE);
ensure("4. getSendtoEnum failed", nValue4.getSendtoEnum() == NVS_SIM);
ensure("4. getVec3 failed", *nValue4.getVec3() == llvec4);
LLNameValue nValue5("SecondLife", "-1.0, 2.4, 3", "VEC3", "RW");
LLVector3 llvec5(-1.0f, 2.4f, 3);
ensure("5. getTypeEnum failed", nValue5.getTypeEnum() == NVT_VEC3);
ensure("5. getClassEnum failed", nValue5.getClassEnum() == NVC_READ_WRITE);
ensure("5. getSendtoEnum failed", nValue5.getSendtoEnum() == NVS_SIM);
ensure("5. getVec3 failed", *nValue5.getVec3() == llvec5);
LLNameValue nValue6("SecondLife", "89764323", "U32", "RW");
ensure("6. getTypeEnum failed", nValue6.getTypeEnum() == NVT_U32);
ensure("6. getClassEnum failed", nValue6.getClassEnum() == NVC_READ_WRITE);
ensure("6. getSendtoEnum failed", nValue6.getSendtoEnum() == NVS_SIM);
ensure("6. getU32 failed", *nValue6.getU32() == 89764323);
LLNameValue nValue7("SecondLife", "89764323323232", "U64", "RW");
U64 u64_7 = U64L(89764323323232);
ensure("7. getTypeEnum failed", nValue7.getTypeEnum() == NVT_U64);
ensure("7. getClassEnum failed", nValue7.getClassEnum() == NVC_READ_WRITE);
ensure("7. getSendtoEnum failed", nValue7.getSendtoEnum() == NVS_SIM);
ensure("7. getU32 failed", *nValue7.getU64() == u64_7);
}
// LLNameValue(const char* name, const char* type, const char* nvclass,
// TNameValueCallback nvcb = NULL, void** user_data = NULL);
template<> template<>
void namevalue_object_t::test<4>()
{
LLNameValue nValue("SecondLife", "STRING", "READ_WRITE");
ensure("mName not set correctly", (0 == strcmp(nValue.mName,"SecondLife")));
ensure("getTypeEnum failed", nValue.getTypeEnum() == NVT_STRING);
ensure("getClassEnum failed", nValue.getClassEnum() == NVC_READ_WRITE);
ensure("getSendtoEnum failed", nValue.getSendtoEnum() == NVS_SIM);
LLNameValue nValue1("SecondLife", "ASSET", "READ_WRITE");
ensure("1. mName not set correctly", (0 == strcmp(nValue1.mName,"SecondLife")));
ensure("1. getTypeEnum for RW failed", nValue1.getTypeEnum() == NVT_ASSET);
ensure("1. getClassEnum for RW failed", nValue1.getClassEnum() == NVC_READ_WRITE);
ensure("1. getSendtoEnum for RW failed", nValue1.getSendtoEnum() == NVS_SIM);
LLNameValue nValue2("SecondLife", "F32", "READ_ONLY");
ensure("2. getTypeEnum failed", nValue2.getTypeEnum() == NVT_F32);
ensure("2. getClassEnum failed", nValue2.getClassEnum() == NVC_READ_ONLY);
ensure("2. getSendtoEnum failed", nValue2.getSendtoEnum() == NVS_SIM);
LLNameValue nValue3("SecondLife", "S32", "READ_ONLY");
ensure("3. getTypeEnum failed", nValue3.getTypeEnum() == NVT_S32);
ensure("3. getClassEnum failed", nValue3.getClassEnum() == NVC_READ_ONLY);
ensure("3. getSendtoEnum failed", nValue3.getSendtoEnum() == NVS_SIM);
LLNameValue nValue4("SecondLife", "VEC3", "READ_WRITE");
ensure("4. getTypeEnum failed", nValue4.getTypeEnum() == NVT_VEC3);
ensure("4. getClassEnum failed", nValue4.getClassEnum() == NVC_READ_WRITE);
ensure("4. getSendtoEnum failed", nValue4.getSendtoEnum() == NVS_SIM);
LLNameValue nValue6("SecondLife", "U32", "READ_WRITE");
ensure("6. getTypeEnum failed", nValue6.getTypeEnum() == NVT_U32);
ensure("6. getClassEnum failed", nValue6.getClassEnum() == NVC_READ_WRITE);
ensure("6. getSendtoEnum failed", nValue6.getSendtoEnum() == NVS_SIM);
LLNameValue nValue7("SecondLife", "U64", "READ_WRITE");
ensure("7. getTypeEnum failed", nValue7.getTypeEnum() == NVT_U64);
ensure("7. getClassEnum failed", nValue7.getClassEnum() == NVC_READ_WRITE);
ensure("7. getSendtoEnum failed", nValue7.getSendtoEnum() == NVS_SIM);
}
template<> template<>
void namevalue_object_t::test<5>()
{
LLNameValue nValue("SecondLife", "This is a test", "STRING", "RW", "SIM");
ensure("getString failed", (0 == strcmp(nValue.getString(),"This is a test")));
}
template<> template<>
void namevalue_object_t::test<6>()
{
LLNameValue nValue("SecondLife", "This is a test", "ASSET", "RW", "S");
ensure("getAsset failed", (0 == strcmp(nValue.getAsset(),"This is a test")));
}
template<> template<>
void namevalue_object_t::test<7>()
{
LLNameValue nValue("SecondLife", "555555", "F32", "RW", "SIM");
ensure("getF32 failed",*nValue.getF32() == 555555.f);
}
template<> template<>
void namevalue_object_t::test<8>()
{
LLNameValue nValue("SecondLife", "-5555", "S32", "RW", "SIM");
ensure("getS32 failed", *nValue.getS32() == -5555);
S32 sVal = 0x7FFFFFFF;
nValue.setS32(sVal);
ensure("getS32 failed", *nValue.getS32() == sVal);
sVal = -0x7FFFFFFF;
nValue.setS32(sVal);
ensure("getS32 failed", *nValue.getS32() == sVal);
sVal = 0;
nValue.setS32(sVal);
ensure("getS32 failed", *nValue.getS32() == sVal);
}
template<> template<>
void namevalue_object_t::test<9>()
{
LLNameValue nValue("SecondLife", "<-3, 2, 1>", "VEC3", "RW", "SIM");
LLVector3 vecExpected(-3, 2, 1);
LLVector3 vec;
nValue.getVec3(vec);
ensure("getVec3 failed", vec == vecExpected);
}
template<> template<>
void namevalue_object_t::test<10>()
{
LLNameValue nValue("SecondLife", "12345678", "U32", "RW", "SIM");
ensure("getU32 failed",*nValue.getU32() == 12345678);
U32 val = 0xFFFFFFFF;
nValue.setU32(val);
ensure("U32 max", *nValue.getU32() == val);
val = 0;
nValue.setU32(val);
ensure("U32 min", *nValue.getU32() == val);
}
template<> template<>
void namevalue_object_t::test<11>()
{
//skip_fail("incomplete support for U64.");
LLNameValue nValue("SecondLife", "44444444444", "U64", "RW", "SIM");
ensure("getU64 failed",*nValue.getU64() == U64L(44444444444));
// there is no LLNameValue::setU64()
}
template<> template<>
void namevalue_object_t::test<12>()
{
//skip_fail("incomplete support for U64.");
LLNameValue nValue("SecondLife U64 RW DSV 44444444444");
std::string ret_str = nValue.printNameValue();
ensure_equals("1:printNameValue failed",ret_str,"SecondLife U64 RW DSV 44444444444");
LLNameValue nValue1(ret_str.c_str());
ensure_equals("Serialization of printNameValue failed", *nValue.getU64(), *nValue1.getU64());
}
template<> template<>
void namevalue_object_t::test<13>()
{
LLNameValue nValue("SecondLife STRING RW DSV 44444444444");
std::string ret_str = nValue.printData();
ensure_equals("1:printData failed",ret_str,"44444444444");
LLNameValue nValue1("SecondLife S32 RW DSV 44444");
ret_str = nValue1.printData();
ensure_equals("2:printData failed",ret_str,"44444");
}
template<> template<>
void namevalue_object_t::test<14>()
{
LLNameValue nValue("SecodLife STRING RW SIM 22222");
std::ostringstream stream1,stream2,stream3, stream4, stream5;
stream1 << nValue;
ensure_equals("STRING << failed",stream1.str(),"22222");
LLNameValue nValue1("SecodLife F32 RW SIM 22222");
stream2 << nValue1;
ensure_equals("F32 << failed",stream2.str(),"22222");
LLNameValue nValue2("SecodLife S32 RW SIM 22222");
stream3<< nValue2;
ensure_equals("S32 << failed",stream3.str(),"22222");
LLNameValue nValue3("SecodLife U32 RW SIM 122222");
stream4<< nValue3;
ensure_equals("U32 << failed",stream4.str(),"122222");
// I don't think we use U64 name value pairs. JC
//skip_fail("incomplete support for U64.");
//LLNameValue nValue4("SecodLife U64 RW SIM 22222");
//stream5<< nValue4;
//ensure("U64 << failed",0 == strcmp((stream5.str()).c_str(),"22222"));
}
template<> template<>
void namevalue_object_t::test<15>()
{
LLNameValue nValue("SecondLife", "This is a test", "ASSET", "R", "S");
ensure("getAsset failed", (0 == strcmp(nValue.getAsset(),"This is a test")));
// this should not have updated as it is read only.
nValue.setAsset("New Value should not be updated");
ensure("setAsset on ReadOnly failed", (0 == strcmp(nValue.getAsset(),"This is a test")));
LLNameValue nValue1("SecondLife", "1234", "U32", "R", "S");
// this should not have updated as it is read only.
nValue1.setU32(4567);
ensure("setU32 on ReadOnly failed", *nValue1.getU32() == 1234);
LLNameValue nValue2("SecondLife", "1234", "S32", "R", "S");
// this should not have updated as it is read only.
nValue2.setS32(4567);
ensure("setS32 on ReadOnly failed", *nValue2.getS32() == 1234);
LLNameValue nValue3("SecondLife", "1234", "F32", "R", "S");
// this should not have updated as it is read only.
nValue3.setF32(4567);
ensure("setF32 on ReadOnly failed", *nValue3.getF32() == 1234);
LLNameValue nValue4("SecondLife", "<1,2,3>", "VEC3", "R", "S");
// this should not have updated as it is read only.
LLVector3 vec(4,5,6);
nValue3.setVec3(vec);
LLVector3 vec1(1,2,3);
ensure("setVec3 on ReadOnly failed", *nValue4.getVec3() == vec1);
// cant test for U64 as no set64 exists nor any operators support U64 type
}
}

View File

@ -9,6 +9,7 @@ include(LLCommon)
include(LLImage)
include(LLMath)
include(LLRender)
include(LLVFS)
include(LLWindow)
include(LLXML)
include(LLVFS)
@ -19,6 +20,7 @@ include_directories(
${LLIMAGE_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS}
${LLRENDER_INCLUDE_DIRS}
${LLVFS_INCLUDE_DIRS}
${LLWINDOW_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS}
${LLVFS_INCLUDE_DIRS}

View File

@ -106,7 +106,7 @@ void LLCubeMap::initGL()
}
else
{
llwarns << "Using cube map without extension!" << llendl
llwarns << "Using cube map without extension!" << llendl;
}
}

View File

@ -98,9 +98,7 @@ LLFontGlyphInfo::LLFontGlyphInfo(U32 index)
mWidth(0), // In pixels
mHeight(0), // In pixels
mXAdvance(0.f), // In pixels
mYAdvance(0.f), // In pixels
mIsRendered(FALSE),
mMetricsValid(FALSE)
mYAdvance(0.f) // In pixels
{
}
@ -199,7 +197,7 @@ BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v
if (!mIsFallback)
{
// Add the default glyph
addGlyph(0, 0);
addGlyphFromFont(this, 0, 0);
}
mName = filename;
@ -251,59 +249,12 @@ F32 LLFontFreetype::getXAdvance(llwchar wch) const
if (mFTFace == NULL)
return 0.0;
//llassert(!mIsFallback);
U32 glyph_index;
// Return existing info only if it is current
LLFontGlyphInfo* gi = getGlyphInfo(wch);
if (gi && gi->mMetricsValid)
if (gi)
{
return gi->mXAdvance;
}
const LLFontFreetype* fontp = this;
// Initialize char to glyph map
glyph_index = FT_Get_Char_Index(mFTFace, wch);
if (glyph_index == 0)
{
font_vector_t::const_iterator iter;
for(iter = mFallbackFonts.begin(); (iter != mFallbackFonts.end()) && (glyph_index == 0); iter++)
{
glyph_index = FT_Get_Char_Index((*iter)->mFTFace, wch);
if(glyph_index)
{
fontp = *iter;
}
}
}
if (glyph_index)
{
// This font has this glyph
fontp->renderGlyph(glyph_index);
// Create the entry if it's not there
char_glyph_info_map_t::iterator iter2 = mCharGlyphInfoMap.find(wch);
if (iter2 == mCharGlyphInfoMap.end())
{
gi = new LLFontGlyphInfo(glyph_index);
insertGlyphInfo(wch, gi);
}
else
{
gi = iter2->second;
}
gi->mWidth = fontp->mFTFace->glyph->bitmap.width;
gi->mHeight = fontp->mFTFace->glyph->bitmap.rows;
// Convert these from 26.6 units to float pixels.
gi->mXAdvance = fontp->mFTFace->glyph->advance.x / 64.f;
gi->mYAdvance = fontp->mFTFace->glyph->advance.y / 64.f;
gi->mMetricsValid = TRUE;
return gi->mXAdvance;
}
else
{
gi = get_if_there(mCharGlyphInfoMap, (llwchar)0, (LLFontGlyphInfo*)NULL);
@ -323,10 +274,10 @@ F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const
return 0.0;
//llassert(!mIsFallback);
LLFontGlyphInfo* left_glyph_info = get_if_there(mCharGlyphInfoMap, char_left, (LLFontGlyphInfo*)NULL);
LLFontGlyphInfo* left_glyph_info = getGlyphInfo(char_left);;
U32 left_glyph = left_glyph_info ? left_glyph_info->mGlyphIndex : 0;
// Kern this puppy.
LLFontGlyphInfo* right_glyph_info = get_if_there(mCharGlyphInfoMap, char_right, (LLFontGlyphInfo*)NULL);
LLFontGlyphInfo* right_glyph_info = getGlyphInfo(char_right);
U32 right_glyph = right_glyph_info ? right_glyph_info->mGlyphIndex : 0;
FT_Vector delta;
@ -339,18 +290,10 @@ F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const
BOOL LLFontFreetype::hasGlyph(llwchar wch) const
{
llassert(!mIsFallback);
const LLFontGlyphInfo* gi = getGlyphInfo(wch);
if (gi && gi->mIsRendered)
{
return TRUE;
}
else
{
return FALSE;
}
return(mCharGlyphInfoMap.find(wch) != mCharGlyphInfoMap.end());
}
BOOL LLFontFreetype::addChar(llwchar wch) const
LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch) const
{
if (mFTFace == NULL)
return FALSE;
@ -364,37 +307,30 @@ BOOL LLFontFreetype::addChar(llwchar wch) const
glyph_index = FT_Get_Char_Index(mFTFace, wch);
if (glyph_index == 0)
{
//llinfos << "Trying to add glyph from fallback font!" << llendl
//llinfos << "Trying to add glyph from fallback font!" << llendl;
font_vector_t::const_iterator iter;
for(iter = mFallbackFonts.begin(); iter != mFallbackFonts.end(); iter++)
{
glyph_index = FT_Get_Char_Index((*iter)->mFTFace, wch);
if (glyph_index)
{
addGlyphFromFont(*iter, wch, glyph_index);
return TRUE;
return addGlyphFromFont(*iter, wch, glyph_index);
}
}
}
char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch);
if (iter == mCharGlyphInfoMap.end() || !(iter->second->mIsRendered))
if (iter == mCharGlyphInfoMap.end())
{
BOOL result = addGlyph(wch, glyph_index);
return result;
return addGlyphFromFont(this, wch, glyph_index);
}
return FALSE;
return NULL;
}
BOOL LLFontFreetype::addGlyph(llwchar wch, U32 glyph_index) const
{
return addGlyphFromFont(this, wch, glyph_index);
}
BOOL LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index) const
LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index) const
{
if (mFTFace == NULL)
return FALSE;
return NULL;
llassert(!mIsFallback);
fontp->renderGlyph(glyph_index);
@ -417,8 +353,6 @@ BOOL LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch,
// Convert these from 26.6 units to float pixels.
gi->mXAdvance = fontp->mFTFace->glyph->advance.x / 64.f;
gi->mYAdvance = fontp->mFTFace->glyph->advance.y / 64.f;
gi->mIsRendered = TRUE;
gi->mMetricsValid = TRUE;
insertGlyphInfo(wch, gi);
@ -489,7 +423,11 @@ BOOL LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch,
// omit it from the font-image.
}
return TRUE;
LLImageGL *image_gl = mFontBitmapCachep->getImageGL(bitmap_num);
LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_num);
image_gl->setSubImage(image_raw, 0, 0, image_gl->getWidth(), image_gl->getHeight());
return gi;
}
LLFontGlyphInfo* LLFontFreetype::getGlyphInfo(llwchar wch) const
@ -499,7 +437,11 @@ LLFontGlyphInfo* LLFontFreetype::getGlyphInfo(llwchar wch) const
{
return iter->second;
}
return NULL;
else
{
// this glyph doesn't yet exist, so render it and return the result
return addGlyph(wch);
}
}
void LLFontFreetype::insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const
@ -534,11 +476,10 @@ void LLFontFreetype::renderGlyph(U32 glyph_index) const
void LLFontFreetype::reset(F32 vert_dpi, F32 horz_dpi)
{
resetBitmapCache();
loadFace(mName, mPointSize, vert_dpi ,horz_dpi, mFontBitmapCachep->getNumComponents(), mIsFallback);
if (!mIsFallback)
{
// This is the head of the list - need to rebuild ourself and all fallbacks.
loadFace(mName, mPointSize, vert_dpi ,horz_dpi, mFontBitmapCachep->getNumComponents(), mIsFallback);
if (mFallbackFonts.empty())
{
llwarns << "LLFontGL::reset(), no fallback fonts present" << llendl;
@ -557,19 +498,12 @@ void LLFontFreetype::reset(F32 vert_dpi, F32 horz_dpi)
void LLFontFreetype::resetBitmapCache()
{
// Iterate through glyphs and clear the mIsRendered flag
for (char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.begin();
iter != mCharGlyphInfoMap.end(); ++iter)
{
iter->second->mIsRendered = FALSE;
//FIXME: this is only strictly necessary when resetting the entire font,
//not just flushing the bitmap
iter->second->mMetricsValid = FALSE;
}
for_each(mCharGlyphInfoMap.begin(), mCharGlyphInfoMap.end(), DeletePairedPointer());
mCharGlyphInfoMap.clear();
mFontBitmapCachep->reset();
// Add the empty glyph
addGlyph(0, 0);
addGlyphFromFont(this, 0, 0);
}
void LLFontFreetype::destroyGL()
@ -577,21 +511,11 @@ void LLFontFreetype::destroyGL()
mFontBitmapCachep->destroyGL();
}
BOOL LLFontFreetype::getIsFallback() const
{
return mIsFallback;
}
const std::string &LLFontFreetype::getName() const
{
return mName;
}
F32 LLFontFreetype::getPointSize() const
{
return mPointSize;
}
const LLPointer<LLFontBitmapCache> LLFontFreetype::getFontBitmapCache() const
{
return mFontBitmapCachep;

View File

@ -70,10 +70,8 @@ public:
S32 mHeight; // In pixels
F32 mXAdvance; // In pixels
F32 mYAdvance; // In pixels
BOOL mMetricsValid; // We have up-to-date metrics for this glyph
// Information for actually rendering
BOOL mIsRendered; // We actually have rendered this glyph
S32 mXBitmapOffset; // Offset to the origin in the bitmap
S32 mYBitmapOffset; // Offset to the origin in the bitmap
S32 mXBearing; // Distance from baseline to left in pixels
@ -133,34 +131,27 @@ public:
F32 getXAdvance(llwchar wc) const;
F32 getXKerning(llwchar char_left, llwchar char_right) const; // Get the kerning between the two characters
BOOL hasGlyph(llwchar wch) const; // Has a glyph for this character
BOOL addChar(llwchar wch) const; // Add a new character to the font if necessary
BOOL addGlyph(llwchar wch, U32 glyph_index) const; // Add a new glyph to the existing font
BOOL addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index) const; // Add a glyph from this font to the other (returns the glyph_index, 0 if not found)
LLFontGlyphInfo* getGlyphInfo(llwchar wch) const;
void insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const;
void renderGlyph(U32 glyph_index) const;
void reset(F32 vert_dpi, F32 horz_dpi);
void resetBitmapCache();
void destroyGL();
BOOL getIsFallback() const;
const std::string& getName() const;
F32 getPointSize() const;
const LLPointer<LLFontBitmapCache> getFontBitmapCache() const;
void setStyle(U8 style);
U8 getStyle() const;
private:
void resetBitmapCache();
void setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 width, U32 height, U8 *data, S32 stride = 0) const;
BOOL hasGlyph(llwchar wch) const; // Has a glyph for this character
LLFontGlyphInfo* addGlyph(llwchar wch) const; // Add a new character to the font if necessary
LLFontGlyphInfo* addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index) const; // Add a glyph from this font to the other (returns the glyph_index, 0 if not found)
void renderGlyph(U32 glyph_index) const;
void insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const;
std::string mName;

View File

@ -44,6 +44,7 @@
#include "llstl.h"
#include "v4color.h"
#include "lltexture.h"
#include "lldir.h"
// Third party library includes
#include <boost/tokenizer.hpp>
@ -251,11 +252,6 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
{
llwchar wch = wstr[i];
if (!mFontFreetype->hasGlyph(wch))
{
addChar(wch);
}
const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch);
if (!fgi)
{
@ -298,10 +294,6 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
if (next_char && (next_char < LAST_CHARACTER))
{
// Kern this puppy.
if (!mFontFreetype->hasGlyph(next_char))
{
addChar(next_char);
}
cur_x += mFontFreetype->getXKerning(wch, next_char);
}
@ -441,15 +433,22 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars
F32 cur_x = 0;
const S32 max_index = begin_offset + max_chars;
for (S32 i = begin_offset; i < max_index; i++)
F32 width_padding = 0.f;
for (S32 i = begin_offset; i < max_index && wchars[i] != 0; i++)
{
llwchar wch = wchars[i];
if (wch == 0)
{
break; // done
}
cur_x += mFontFreetype->getXAdvance(wch);
const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch);
F32 advance = mFontFreetype->getXAdvance(wch);
// for the last character we want to measure the greater of its width and xadvance values
// so keep track of the difference between these values for the each character we measure
// so we can fix things up at the end
width_padding = llmax(0.f, (F32)fgi->mWidth - advance);
cur_x += advance;
llwchar next_char = wchars[i+1];
if (((i + 1) < begin_offset + max_chars)
@ -463,6 +462,9 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars
cur_x = (F32)llfloor(cur_x + 0.5f);
}
// add in extra pixels for last character's width past its xadvance
cur_x += width_padding;
return cur_x / sScaleX;
}
@ -662,25 +664,6 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 t
return llmin(max_chars, pos - begin_offset);
}
BOOL LLFontGL::addChar(llwchar wch) const
{
if (!mFontFreetype->addChar(wch))
{
return FALSE;
}
stop_glerror();
LLFontGlyphInfo *glyph_info = mFontFreetype->getGlyphInfo(wch);
U32 bitmap_num = glyph_info->mBitmapNum;
const LLFontBitmapCache* font_bitmap_cache = mFontFreetype->getFontBitmapCache();
LLImageGL *image_gl = font_bitmap_cache->getImageGL(bitmap_num);
LLImageRaw *image_raw = font_bitmap_cache->getImageRaw(bitmap_num);
image_gl->setSubImage(image_raw, 0, 0, image_gl->getWidth(), image_gl->getHeight());
return TRUE;
}
const LLFontDescriptor& LLFontGL::getFontDesc() const
{
return mFontDescriptor;

View File

@ -131,8 +131,6 @@ public:
// Returns the index of the character closest to pixel position x (ignoring text to the right of max_pixels and max_chars)
S32 charFromPixelOffset(const llwchar* wchars, S32 char_offset, F32 x, F32 max_pixels=F32_MAX, S32 max_chars = S32_MAX, BOOL round = TRUE) const;
BOOL addChar(const llwchar wch) const;
const LLFontDescriptor& getFontDesc() const;

View File

@ -53,8 +53,6 @@
# include "GL/glxext.h"
//# define GLH_EXT_GET_PROC_ADDRESS(p) glXGetProcAddressARB((const GLubyte*)(p))
# define GLH_EXT_GET_PROC_ADDRESS(p) glXGetProcAddress((const GLubyte*)(p))
// the X headers define 'Status'. Undefine to avoid confusion.
#undef Status
// The __APPLE__ kludge is to make glh_extensions.h not symbol-clash horribly
// This header is distributed with SL. You'll find it in linden/libraries/include/GL/
@ -277,8 +275,6 @@ extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT;
// Use glXGetProcAddressARB instead of glXGetProcAddress - the ARB symbol
// is considered 'legacy' but works on more machines.
# define GLH_EXT_GET_PROC_ADDRESS(p) glXGetProcAddressARB((const GLubyte*)(p))
// Whee, the X headers define 'Status'. Undefine to avoid confusion.
#undef Status
#endif // LL_LINUX && !LL_MESA_HEADLESS
#if LL_LINUX && defined(WINGDIAPI)

View File

@ -428,7 +428,7 @@ void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents)
// Check if dimensions are a power of two!
if (!checkSize(width,height))
{
llerrs << llformat("Texture has non power of two dimention: %dx%d",width,height) << llendl;
llerrs << llformat("Texture has non power of two dimension: %dx%d",width,height) << llendl;
}
if (mTexName)

View File

@ -52,6 +52,7 @@
#include "llrender.h"
#include "lluictrlfactory.h"
#include "llhelp.h"
#include "lldockablefloater.h"
static LLDefaultChildRegistry::Register<LLButton> r("button");
@ -1056,6 +1057,20 @@ void LLButton::setFloaterToggle(LLUICtrl* ctrl, const LLSD& sdname)
button->setClickedCallback(boost::bind(&LLFloaterReg::toggleFloaterInstance, sdname));
}
// static
void LLButton::setDockableFloaterToggle(LLUICtrl* ctrl, const LLSD& sdname)
{
LLButton* button = dynamic_cast<LLButton*>(ctrl);
if (!button)
return;
// Get the visibility control name for the floater
std::string vis_control_name = LLFloaterReg::declareVisibilityControl(sdname.asString());
// Set the button control value (toggle state) to the floater visibility control (Sets the value as well)
button->setControlVariable(LLUI::sSettingGroups["floater"]->getControl(vis_control_name));
// Set the clicked callback to toggle the floater
button->setClickedCallback(boost::bind(&LLDockableFloater::toggleInstance, sdname));
}
// static
void LLButton::showHelp(LLUICtrl* ctrl, const LLSD& sdname)
{

View File

@ -232,6 +232,7 @@ public:
static void onHeldDown(void *userdata); // to be called by gIdleCallbacks
static void toggleFloaterAndSetToggleState(LLUICtrl* ctrl, const LLSD& sdname);
static void setFloaterToggle(LLUICtrl* ctrl, const LLSD& sdname);
static void setDockableFloaterToggle(LLUICtrl* ctrl, const LLSD& sdname);
static void showHelp(LLUICtrl* ctrl, const LLSD& sdname);
void setForcePressedState(BOOL b) { mForcePressedState = b; }

View File

@ -33,24 +33,36 @@
#include "linden_common.h"
#include "lldockablefloater.h"
#include "llfloaterreg.h"
//static
LLHandle<LLFloater> LLDockableFloater::sInstanceHandle;
//static
void LLDockableFloater::init(LLDockableFloater* thiz)
{
thiz->setDocked(thiz->mDockControl.get() != NULL
&& thiz->mDockControl.get()->isDockVisible());
thiz->resetInstance();
// all dockable floaters should have close, dock and minimize buttons
thiz->setCanClose(TRUE);
thiz->setCanDock(true);
thiz->setCanMinimize(TRUE);
}
LLDockableFloater::LLDockableFloater(LLDockControl* dockControl,
const LLSD& key, const Params& params) :
LLFloater(key, params), mDockControl(dockControl), mUniqueDocking(true)
{
setDocked(mDockControl.get() != NULL && mDockControl.get()->isDockVisible());
resetInstance();
init(this);
}
LLDockableFloater::LLDockableFloater(LLDockControl* dockControl, bool uniqueDocking,
const LLSD& key, const Params& params) :
LLFloater(key, params), mDockControl(dockControl), mUniqueDocking(uniqueDocking)
{
setDocked(mDockControl.get() != NULL && mDockControl.get()->isDockVisible());
resetInstance();
init(this);
}
LLDockableFloater::~LLDockableFloater()
@ -64,6 +76,33 @@ BOOL LLDockableFloater::postBuild()
return LLView::postBuild();
}
//static
void LLDockableFloater::toggleInstance(const LLSD& sdname)
{
LLSD key;
std::string name = sdname.asString();
LLDockableFloater* instance =
dynamic_cast<LLDockableFloater*> (LLFloaterReg::findInstance(name));
// if floater closed or docked
if (instance == NULL || instance != NULL && instance->isDocked())
{
LLFloaterReg::toggleInstance(name, key);
// restore button toggle state
if (instance != NULL)
{
instance->storeVisibilityControl();
}
}
// if floater undocked
else if (instance != NULL)
{
instance->setMinimized(FALSE);
instance->setVisible(TRUE);
instance->setFocus(TRUE);
}
}
void LLDockableFloater::resetInstance()
{
if (mUniqueDocking && sInstanceHandle.get() != this)
@ -91,6 +130,17 @@ void LLDockableFloater::setVisible(BOOL visible)
LLFloater::setVisible(visible);
}
void LLDockableFloater::setMinimized(BOOL minimize)
{
if(minimize && isDocked())
{
setVisible(FALSE);
}
setCanDock(!minimize);
LLFloater::setMinimized(minimize);
}
void LLDockableFloater::onDockHidden()
{
setCanDock(FALSE);

View File

@ -44,6 +44,8 @@
class LLDockableFloater : public LLFloater
{
static const U32 UNDOCK_LEAP_HEIGHT = 12;
static void init(LLDockableFloater* thiz);
public:
LOG_CLASS(LLDockableFloater);
LLDockableFloater(LLDockControl* dockControl, const LLSD& key,
@ -54,6 +56,8 @@ public:
static LLHandle<LLFloater> getInstanceHandle() { return sInstanceHandle; }
static void toggleInstance(const LLSD& sdname);
/**
* If descendant class overrides postBuild() in order to perform specific
* construction then it must still invoke its superclass' implementation.
@ -68,6 +72,12 @@ public:
*/
/*virtual*/ void setVisible(BOOL visible);
/**
* If descendant class overrides setMinimized() then it must still invoke its
* superclass' implementation.
*/
/*virtual*/ void setMinimized(BOOL minimize);
virtual void onDockHidden();
virtual void onDockShown();

View File

@ -916,6 +916,9 @@ void LLFloater::setMinimized(BOOL minimize)
if (minimize)
{
// minimized flag should be turned on before release focus
mMinimized = TRUE;
mExpandedRect = getRect();
// If the floater has been dragged while minimized in the
@ -977,8 +980,6 @@ void LLFloater::setMinimized(BOOL minimize)
}
}
mMinimized = TRUE;
// Reshape *after* setting mMinimized
reshape( minimized_width, floater_header_size, TRUE);
}
@ -1432,7 +1433,18 @@ void LLFloater::onClickHelp( LLFloater* self )
{
if (self && LLUI::sHelpImpl)
{
LLUI::sHelpImpl->showTopic(self->getHelpTopic());
// get the help topic for this floater
std::string help_topic = self->getHelpTopic();
// but use a more specific help topic for the currently
// displayed tab inside of this floater, if present
LLPanel *curtab = self->childGetVisibleTabWithHelp();
if (curtab)
{
help_topic = curtab->getHelpTopic();
}
LLUI::sHelpImpl->showTopic(help_topic);
}
}
@ -2554,10 +2566,10 @@ void LLFloater::initFromParams(const LLFloater::Params& p)
LLFastTimer::DeclareTimer POST_BUILD("Floater Post Build");
void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node)
bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node)
{
Params params(LLUICtrlFactory::getDefaultParams<LLFloater>());
LLXUIParser::instance().readXUI(node, params);
LLXUIParser::instance().readXUI(node, params); // *TODO: Error checking
if (output_node)
{
@ -2603,5 +2615,7 @@ void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o
gFloaterView->adjustToFitScreen(this, FALSE); // Floaters loaded from XML should all fit on screen
moveResizeHandlesToFront();
return true; // *TODO: Error checking
}

View File

@ -146,7 +146,7 @@ public:
static void setupParamsForExport(Params& p, LLView* parent);
void initFromParams(const LLFloater::Params& p);
void initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node = NULL);
bool initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node = NULL);
/*virtual*/ void handleReshape(const LLRect& new_rect, bool by_user = false);
/*virtual*/ BOOL canSnapTo(const LLView* other_view);

View File

@ -124,8 +124,13 @@ LLFloater* LLFloaterReg::getInstance(const std::string& name, const LLSD& key)
res = build_func(key);
LLUICtrlFactory::getInstance()->buildFloater(res, xui_file, NULL);
bool success = LLUICtrlFactory::getInstance()->buildFloater(res, xui_file, NULL);
if (!success)
{
llwarns << "Failed to buid floater type: '" << name << "'." << llendl;
return NULL;
}
// Note: key should eventually be a non optional LLFloater arg; for now, set mKey to be safe
res->mKey = key;
res->setInstanceName(name);

View File

@ -148,6 +148,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
mBgImage( p.background_image ),
mBgImageDisabled( p.background_image_disabled ),
mBgImageFocused( p.background_image_focused ),
mHaveHistory(FALSE),
mReplaceNewlinesWithSpaces( TRUE ),
mLabel(p.label),
mCursorColor(p.cursor_color()),
@ -164,13 +165,8 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
mTripleClickTimer.reset();
setText(p.default_text());
// line history support:
// - initialize line history list
mLineHistory.insert( mLineHistory.end(), "" );
// - disable line history by default
mHaveHistory = FALSE;
// - reset current history line pointer
mCurrentHistoryLine = 0;
// Initialize current history line iterator
mCurrentHistoryLine = mLineHistory.begin();
LLRect border_rect(getLocalRect());
// adjust for gl line drawing glitch
@ -278,16 +274,31 @@ void LLLineEditor::updateHistory()
// reset current history line number.
// Be sure only to remember lines that are not empty and that are
// different from the last on the list.
if( mHaveHistory && mText.length() && ( mLineHistory.empty() || getText() != mLineHistory.back() ) )
if( mHaveHistory && getLength() )
{
// discard possible empty line at the end of the history
// inserted by setText()
if( !mLineHistory.back().length() )
if( !mLineHistory.empty() )
{
mLineHistory.pop_back();
// When not empty, last line of history should always be blank.
if( mLineHistory.back().empty() )
{
// discard the empty line
mLineHistory.pop_back();
}
else
{
LL_WARNS("") << "Last line of history was not blank." << LL_ENDL;
}
}
mLineHistory.insert( mLineHistory.end(), getText() );
mCurrentHistoryLine = mLineHistory.size() - 1;
// Add text to history, ignoring duplicates
if( mLineHistory.empty() || getText() != mLineHistory.back() )
{
mLineHistory.push_back( getText() );
}
// Restore the blank line and set mCurrentHistoryLine to point at it
mLineHistory.push_back( "" );
mCurrentHistoryLine = mLineHistory.end() - 1;
}
}
@ -357,11 +368,8 @@ void LLLineEditor::setText(const LLStringExplicit &new_text)
}
setCursor(llmin((S32)mText.length(), getCursor()));
// Newly set text goes always in the last line of history.
// Possible empty strings (as with chat line) will be deleted later.
mLineHistory.insert( mLineHistory.end(), new_text );
// Set current history line to end of history.
mCurrentHistoryLine = mLineHistory.size() - 1;
mCurrentHistoryLine = mLineHistory.end() - 1;
mPrevText = mText;
}
@ -1254,9 +1262,9 @@ BOOL LLLineEditor::handleSpecialKey(KEY key, MASK mask)
case KEY_UP:
if( mHaveHistory && ( MASK_CONTROL == mask ) )
{
if( mCurrentHistoryLine > 0 )
if( mCurrentHistoryLine > mLineHistory.begin() )
{
mText.assign( mLineHistory[ --mCurrentHistoryLine ] );
mText.assign( *(--mCurrentHistoryLine) );
setCursor(llmin((S32)mText.length(), getCursor()));
}
else
@ -1271,9 +1279,9 @@ BOOL LLLineEditor::handleSpecialKey(KEY key, MASK mask)
case KEY_DOWN:
if( mHaveHistory && ( MASK_CONTROL == mask ) )
{
if( !mLineHistory.empty() && mCurrentHistoryLine < mLineHistory.size() - 1 )
if( !mLineHistory.empty() && mCurrentHistoryLine < mLineHistory.end() - 1 )
{
mText.assign( mLineHistory[ ++mCurrentHistoryLine ] );
mText.assign( *(++mCurrentHistoryLine) );
setCursor(llmin((S32)mText.length(), getCursor()));
}
else
@ -2291,14 +2299,20 @@ BOOL LLLineEditor::hasPreeditString() const
void LLLineEditor::resetPreedit()
{
if (hasPreeditString())
if (hasSelection())
{
if (hasSelection())
if (hasPreeditString())
{
llwarns << "Preedit and selection!" << llendl;
deselect();
}
else
{
deleteSelection();
}
}
if (hasPreeditString())
{
const S32 preedit_pos = mPreeditPositions.front();
mText.erase(preedit_pos, mPreeditPositions.back() - preedit_pos);
mText.insert(preedit_pos, mPreeditOverwrittenWString);
@ -2500,20 +2514,3 @@ LLWString LLLineEditor::getConvertedText() const
}
return text;
}
namespace LLInitParam
{
template<>
bool ParamCompare<LLLinePrevalidateFunc>::equals(const LLLinePrevalidateFunc &a, const LLLinePrevalidateFunc &b)
{
return false;
}
template<>
bool ParamCompare<boost::function<void (LLLineEditor *)> >::equals(
const boost::function<void (LLLineEditor *)> &a,
const boost::function<void (LLLineEditor *)> &b)
{
return false;
}
}

View File

@ -286,8 +286,9 @@ protected:
// line history support:
BOOL mHaveHistory; // flag for enabled line history
std::vector<std::string> mLineHistory; // line history storage
U32 mCurrentHistoryLine; // currently browsed history line
typedef std::vector<std::string> line_history_t;
line_history_t mLineHistory; // line history storage
line_history_t::iterator mCurrentHistoryLine; // currently browsed history line
LLViewBorder* mBorder;
const LLFontGL* mGLFont;
@ -390,15 +391,4 @@ private:
}; // end class LLLineEditor
namespace LLInitParam
{
template<>
bool ParamCompare<LLLinePrevalidateFunc>::equals(
const LLLinePrevalidateFunc &a, const LLLinePrevalidateFunc &b);
template<>
bool ParamCompare<boost::function<void (LLLineEditor *)> >::equals(
const boost::function<void (LLLineEditor *)> &a, const boost::function<void (LLLineEditor *)> &b);
}
#endif // LL_LINEEDITOR_

View File

@ -279,47 +279,7 @@ BOOL LLMenuItemGL::addToAcceleratorList(std::list <LLKeyBinding*> *listp)
// the current accelerator key and mask to the provided string.
void LLMenuItemGL::appendAcceleratorString( std::string& st ) const
{
// break early if this is a silly thing to do.
if( KEY_NONE == mAcceleratorKey )
{
return;
}
// Append any masks
#ifdef LL_DARWIN
// Standard Mac names for modifier keys in menu equivalents
// We could use the symbol characters, but they only exist in certain fonts.
if( mAcceleratorMask & MASK_CONTROL )
{
if ( mAcceleratorMask & MASK_MAC_CONTROL )
{
st.append( "Ctrl-" );
}
else
{
st.append( "Cmd-" ); // Symbol would be "\xE2\x8C\x98"
}
}
if( mAcceleratorMask & MASK_ALT )
st.append( "Opt-" ); // Symbol would be "\xE2\x8C\xA5"
if( mAcceleratorMask & MASK_SHIFT )
st.append( "Shift-" ); // Symbol would be "\xE2\x8C\xA7"
#else
if( mAcceleratorMask & MASK_CONTROL )
st.append( "Ctrl-" );
if( mAcceleratorMask & MASK_ALT )
st.append( "Alt-" );
if( mAcceleratorMask & MASK_SHIFT )
st.append( "Shift-" );
#endif
std::string keystr = LLKeyboard::stringFromKey( mAcceleratorKey );
if ((mAcceleratorMask & MASK_NORMALKEYS) &&
(keystr[0] == '-' || keystr[0] == '='))
{
st.append( " " );
}
st.append( keystr );
st = LLKeyboard::stringFromAccelerator( mAcceleratorMask, mAcceleratorKey );
LL_DEBUGS("HotKeys") << "appendAcceleratorString: " << st << LL_ENDL;
}

View File

@ -810,6 +810,47 @@ LLPanel *LLPanel::childGetVisibleTab(const std::string& id) const
return NULL;
}
static LLPanel *childGetVisibleTabWithHelp(LLView *parent)
{
LLView *child;
// look through immediate children first for an active tab with help
for (child = parent->getFirstChild(); child; child = parent->findNextSibling(child))
{
LLTabContainer *tab = dynamic_cast<LLTabContainer *>(child);
if (tab && tab->getVisible())
{
LLPanel *curTabPanel = tab->getCurrentPanel();
if (curTabPanel && !curTabPanel->getHelpTopic().empty())
{
return curTabPanel;
}
}
}
// then try a bit harder and recurse through all children
for (child = parent->getFirstChild(); child; child = parent->findNextSibling(child))
{
if (child->getVisible())
{
LLPanel* tab = ::childGetVisibleTabWithHelp(child);
if (tab)
{
return tab;
}
}
}
// couldn't find any active tabs with a help topic string
return NULL;
}
LLPanel *LLPanel::childGetVisibleTabWithHelp()
{
// find a visible tab with a help topic (to determine help context)
return ::childGetVisibleTabWithHelp(this);
}
void LLPanel::childSetPrevalidate(const std::string& id, BOOL (*func)(const LLWString &) )
{
LLLineEditor* child = findChild<LLLineEditor>(id);

View File

@ -208,6 +208,7 @@ public:
// LLTabContainer
void childShowTab(const std::string& id, const std::string& tabname, bool visible = true);
LLPanel *childGetVisibleTab(const std::string& id) const;
LLPanel *childGetVisibleTabWithHelp();
// LLTextBox/LLTextEditor/LLLineEditor
void childSetText(const std::string& id, const LLStringExplicit& text) { childSetValue(id, LLSD(text)); }

View File

@ -279,6 +279,14 @@ std::string LLResMgr::getMonetaryString( S32 input ) const
void LLResMgr::getIntegerString( std::string& output, S32 input ) const
{
// handle special case of input value being zero
if (input == 0)
{
output = "0";
return;
}
// *NOTE: this method does not handle negative input integers correctly
S32 fraction = 0;
std::string fraction_string;
S32 remaining_count = input;

View File

@ -640,15 +640,3 @@ void LLScrollbar::onLineDownBtnPressed( const LLSD& data )
{
changeLine( mStepSize, TRUE );
}
namespace LLInitParam
{
template<>
bool ParamCompare<boost::function<void (S32, LLScrollbar*)> >::equals(
const boost::function<void (S32, LLScrollbar*)> &a,
const boost::function<void (S32, LLScrollbar*)> &b)
{
return false;
}
}

View File

@ -167,11 +167,4 @@ private:
};
namespace LLInitParam
{
template<>
bool ParamCompare<boost::function<void (S32, LLScrollbar*)> >::equals(
const boost::function<void (S32, LLScrollbar*)> &a, const boost::function<void (S32, LLScrollbar*)> &b);
}
#endif // LL_SCROLLBAR_H

View File

@ -1411,6 +1411,7 @@ void LLScrollListCtrl::drawItems()
cur_y,
mItemListRect.getWidth(),
mLineHeight );
item->setRect(item_rect);
//llinfos << item_rect.getWidth() << llendl;
@ -1708,7 +1709,7 @@ BOOL LLScrollListCtrl::handleMouseDown(S32 x, S32 y, MASK mask)
}
BOOL LLScrollListCtrl::handleMouseUp(S32 x, S32 y, MASK mask)
{
{
if (hasMouseCapture())
{
// release mouse capture immediately so

View File

@ -97,6 +97,9 @@ public:
LLUUID getUUID() const { return mItemValue.asUUID(); }
LLSD getValue() const { return mItemValue; }
void setRect(LLRect rect) { mRectangle = rect; }
LLRect getRect() const { return mRectangle; }
void addColumn( const LLScrollListCell::Params& p );
@ -122,6 +125,7 @@ private:
void* mUserdata;
LLSD mItemValue;
std::vector<LLScrollListCell *> mColumns;
LLRect mRectangle;
};
#endif

View File

@ -37,9 +37,9 @@
#include "llsearcheditor.h"
LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p)
: LLUICtrl(p)
, mSearchButton(NULL)
, mClearButton(NULL)
: LLUICtrl(p),
mSearchButton(NULL),
mClearButton(NULL)
{
S32 srch_btn_top = p.search_button.top_pad + p.search_button.rect.height;
S32 srch_btn_right = p.search_button.rect.width + p.search_button.left_pad;

View File

@ -107,9 +107,10 @@ static LLDefaultChildRegistry::Register<LLTabContainer> r2("tab_container");
LLTabContainer::Params::Params()
: tab_width("tab_width"),
tab_position("tab_position"),
tab_min_width("tab_min_width"),
tab_max_width("tab_max_width"),
tab_height("tab_height"),
tab_position("tab_position"),
hide_tabs("hide_tabs", false),
tab_padding_right("tab_padding_right"),
tab_top_image_unselected("tab_top_image_unselected"),
@ -136,6 +137,7 @@ LLTabContainer::LLTabContainer(const LLTabContainer::Params& p)
mLockedTabCount(0),
mMinTabWidth(0),
mMaxTabWidth(p.tab_max_width),
mTabHeight(p.tab_height),
mPrevArrowBtn(NULL),
mNextArrowBtn(NULL),
mIsVertical( p.tab_position == LEFT ),
@ -802,7 +804,6 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
static LLUICachedControl<S32> tabcntrv_pad ("UITabCntrvPad", 0);
static LLUICachedControl<S32> tabcntr_button_panel_overlap ("UITabCntrButtonPanelOverlap", 0);
static LLUICachedControl<S32> tabcntr_tab_height ("UITabCntrTabHeight", 0);
static LLUICachedControl<S32> tab_padding ("UITabPadding", 0);
if (child->getParent() == this)
{
@ -830,14 +831,14 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
{
if( getTabPosition() == LLTabContainer::TOP )
{
S32 tab_height = mIsVertical ? BTN_HEIGHT : tabcntr_tab_height;
S32 tab_height = mIsVertical ? BTN_HEIGHT : mTabHeight;
tab_panel_top = getRect().getHeight() - getTopBorderHeight() - (tab_height - tabcntr_button_panel_overlap);
tab_panel_bottom = LLPANEL_BORDER_WIDTH;
}
else
{
tab_panel_top = getRect().getHeight() - getTopBorderHeight();
tab_panel_bottom = (tabcntr_tab_height - tabcntr_button_panel_overlap); // Run to the edge, covering up the border
tab_panel_bottom = (mTabHeight - tabcntr_button_panel_overlap); // Run to the edge, covering up the border
}
}
else
@ -886,13 +887,13 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
}
else if( getTabPosition() == LLTabContainer::TOP )
{
btn_rect.setLeftTopAndSize( 0, getRect().getHeight() - getTopBorderHeight() + tab_fudge, button_width, tabcntr_tab_height );
btn_rect.setLeftTopAndSize( 0, getRect().getHeight() - getTopBorderHeight() + tab_fudge, button_width, mTabHeight);
tab_img = mImageTopUnselected.get();
tab_selected_img = mImageTopSelected.get();
}
else
{
btn_rect.setOriginAndSize( 0, 0 + tab_fudge, button_width, tabcntr_tab_height );
btn_rect.setOriginAndSize( 0, 0 + tab_fudge, button_width, mTabHeight);
tab_img = mImageBottomUnselected.get();
tab_selected_img = mImageBottomSelected.get();
}

View File

@ -67,7 +67,9 @@ public:
Optional<TabPosition, TabPositions> tab_position;
Optional<S32> tab_width,
tab_min_width,
tab_max_width;
tab_max_width,
tab_height;
Optional<bool> hide_tabs;
Optional<S32> tab_padding_right;
@ -246,6 +248,7 @@ private:
S32 mMaxTabWidth;
S32 mTotalTabWidth;
S32 mTabHeight;
LLFrameTimer mDragAndDropDelayTimer;

View File

@ -122,17 +122,6 @@ struct LLTextBase::line_end_compare
};
//////////////////////////////////////////////////////////////////////////
//
// LLTextBase::DocumentPanel
//
LLTextBase::DocumentPanel::DocumentPanel(const Params& p)
: LLPanel(p)
{}
//////////////////////////////////////////////////////////////////////////
//
// LLTextBase
@ -157,8 +146,7 @@ LLTextBase::Params::Params()
bg_readonly_color("bg_readonly_color"),
bg_writeable_color("bg_writeable_color"),
bg_focus_color("bg_focus_color"),
hide_scrollbar("hide_scrollbar"),
clip_to_rect("clip_to_rect", true),
allow_scroll("allow_scroll", true),
track_end("track_end", false),
read_only("read_only", false),
v_pad("v_pad", 0),
@ -205,35 +193,42 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
mSelectionStart( 0 ),
mSelectionEnd( 0 ),
mIsSelecting( FALSE ),
mClip(p.clip_to_rect),
mWordWrap(p.wrap),
mUseEllipses( p.use_ellipses ),
mParseHTML(p.allow_html),
mParseHighlights(p.parse_highlights),
mHideScrollbar(p.hide_scrollbar)
mBGVisible(p.bg_visible),
mScroller(NULL)
{
LLScrollContainer::Params scroll_params;
scroll_params.name = "text scroller";
scroll_params.rect = getLocalRect();
scroll_params.follows.flags = FOLLOWS_ALL;
scroll_params.is_opaque = false;
scroll_params.mouse_opaque = false;
scroll_params.min_auto_scroll_rate = 200;
scroll_params.max_auto_scroll_rate = 800;
scroll_params.hide_scrollbar = p.hide_scrollbar;
scroll_params.border_visible = p.border_visible;
mScroller = LLUICtrlFactory::create<LLScrollContainer>(scroll_params);
addChild(mScroller);
if(p.allow_scroll)
{
LLScrollContainer::Params scroll_params;
scroll_params.name = "text scroller";
scroll_params.rect = getLocalRect();
scroll_params.follows.flags = FOLLOWS_ALL;
scroll_params.is_opaque = false;
scroll_params.mouse_opaque = false;
scroll_params.min_auto_scroll_rate = 200;
scroll_params.max_auto_scroll_rate = 800;
scroll_params.border_visible = p.border_visible;
mScroller = LLUICtrlFactory::create<LLScrollContainer>(scroll_params);
addChild(mScroller);
}
LLPanel::Params panel_params;
panel_params.name = "text_contents";
panel_params.rect = LLRect(0, 500, 500, 0);
panel_params.background_visible = p.bg_visible;
panel_params.background_opaque = true;
panel_params.mouse_opaque = false;
LLView::Params view_params;
view_params.name = "text_contents";
view_params.rect = LLRect(0, 500, 500, 0);
view_params.mouse_opaque = false;
mDocumentPanel = LLUICtrlFactory::create<DocumentPanel>(panel_params);
mScroller->addChild(mDocumentPanel);
mDocumentView = LLUICtrlFactory::create<LLView>(view_params);
if (mScroller)
{
mScroller->addChild(mDocumentView);
}
else
{
addChild(mDocumentView);
}
createDefaultSegment();
@ -314,7 +309,7 @@ void LLTextBase::drawSelectionBackground()
LLRect selection_rect = mTextRect;
// Skip through the lines we aren't drawing.
LLRect content_display_rect = mScroller->getVisibleContentRect();
LLRect content_display_rect = getVisibleDocumentRect();
// binary search for line that starts before top of visible buffer
line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mTop, compare_bottom());
@ -418,6 +413,9 @@ void LLTextBase::drawCursor()
return;
}
if (!mTextRect.contains(cursor_rect))
return;
// Draw the cursor
// (Flash the cursor every half second starting a fixed time after the last keystroke)
F32 elapsed = mCursorBlinkTimer.getElapsedTimeF32();
@ -496,8 +494,7 @@ void LLTextBase::drawText()
selection_right = llmax( mSelectionStart, mSelectionEnd );
}
LLRect scrolled_view_rect = mScroller->getVisibleContentRect();
LLRect content_rect = mScroller->getContentWindowRect();
LLRect scrolled_view_rect = getVisibleDocumentRect();
std::pair<S32, S32> line_range = getVisibleLines();
S32 first_line = line_range.first;
S32 last_line = line_range.second;
@ -540,7 +537,7 @@ void LLTextBase::drawText()
LLRect text_rect(line.mRect.mLeft + mTextRect.mLeft - scrolled_view_rect.mLeft,
line.mRect.mTop - scrolled_view_rect.mBottom + mTextRect.mBottom,
mDocumentPanel->getRect().getWidth() - scrolled_view_rect.mLeft,
mDocumentView->getRect().getWidth() - scrolled_view_rect.mLeft,
line.mRect.mBottom - scrolled_view_rect.mBottom + mTextRect.mBottom);
// draw a single line of text
@ -645,6 +642,7 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s
}
onValueChange(pos, pos + insert_len);
needsReflow();
return insert_len;
}
@ -704,6 +702,7 @@ S32 LLTextBase::removeStringNoUndo(S32 pos, S32 length)
createDefaultSegment();
onValueChange(pos, pos);
needsReflow();
return -length; // This will be wrong if someone calls removeStringNoUndo with an excessive length
}
@ -719,6 +718,7 @@ S32 LLTextBase::overwriteCharNoUndo(S32 pos, llwchar wc)
getViewModel()->setDisplay(text);
onValueChange(pos, pos + 1);
needsReflow();
return 1;
}
@ -949,29 +949,31 @@ void LLTextBase::draw()
// then update scroll position, as cursor may have moved
updateScrollFromCursor();
LLColor4 bg_color = mReadOnly
? mReadOnlyBgColor.get()
: hasFocus()
? mFocusBgColor.get()
: mWriteableBgColor.get();
mDocumentPanel->setBackgroundColor(bg_color);
LLUICtrl::draw();
if (mBGVisible)
{
LLLocalClipRect clip(mTextRect, mClip);
// clip background rect against extents, if we support scrolling
LLLocalClipRect clip(getLocalRect(), mScroller != NULL);
LLColor4 bg_color = mReadOnly
? mReadOnlyBgColor.get()
: hasFocus()
? mFocusBgColor.get()
: mWriteableBgColor.get();
gl_rect_2d(mDocumentView->getRect(), bg_color, TRUE);
}
// draw document view
LLUICtrl::draw();
{
// only clip if we support scrolling (mScroller != NULL)
LLLocalClipRect clip(mTextRect, mScroller != NULL);
drawSelectionBackground();
drawText();
drawCursor();
}
}
//virtual
void LLTextBase::clear()
{
getViewModel()->setDisplay(LLWStringUtil::null);
clearSegments();
}
//virtual
void LLTextBase::setColor( const LLColor4& c )
@ -1000,14 +1002,14 @@ void LLTextBase::updateScrollFromCursor()
// Update scroll position even in read-only mode (when there's no cursor displayed)
// because startOfDoc()/endOfDoc() modify cursor position. See EXT-736.
if (!mScrollNeeded)
if (!mScrollNeeded || !mScroller)
{
return;
}
mScrollNeeded = FALSE;
// scroll so that the cursor is at the top of the page
LLRect scroller_doc_window = mScroller->getVisibleContentRect();
LLRect scroller_doc_window = getVisibleDocumentRect();
LLRect cursor_rect_doc = getLocalRectFromDocIndex(mCursorPos);
cursor_rect_doc.translate(scroller_doc_window.mLeft, scroller_doc_window.mBottom);
mScroller->scrollToShowRect(cursor_rect_doc, LLRect(0, scroller_doc_window.getHeight() - 5, scroller_doc_window.getWidth(), 5));
@ -1042,7 +1044,7 @@ void LLTextBase::reflow(S32 start_index)
{
mReflowNeeded = FALSE;
bool scrolled_to_bottom = mScroller->isAtBottom();
bool scrolled_to_bottom = mScroller ? mScroller->isAtBottom() : false;
LLRect old_cursor_rect = getLocalRectFromDocIndex(mCursorPos);
bool follow_selection = mTextRect.overlaps(old_cursor_rect); // cursor is visible
@ -1104,12 +1106,17 @@ void LLTextBase::reflow(S32 start_index)
S32 segment_width = segment->getWidth(seg_offset, character_count);
remaining_pixels -= segment_width;
S32 text_left = getLeftOffset(text_width - remaining_pixels);
seg_offset += character_count;
S32 last_segment_char_on_line = segment->getStart() + seg_offset;
S32 text_left = getLeftOffset(text_width - remaining_pixels);
LLRect line_rect(text_left,
cur_top,
text_left + (text_width - remaining_pixels),
cur_top - line_height);
// if we didn't finish the current segment...
if (last_segment_char_on_line < segment->getEnd())
{
@ -1127,10 +1134,7 @@ void LLTextBase::reflow(S32 start_index)
mLineInfoList.push_back(line_info(
line_start_index,
last_segment_char_on_line,
LLRect(text_left,
cur_top,
text_left + (text_width - remaining_pixels),
cur_top - line_height),
line_rect,
line_count));
line_start_index = segment->getStart() + seg_offset;
@ -1145,15 +1149,12 @@ void LLTextBase::reflow(S32 start_index)
mLineInfoList.push_back(line_info(
line_start_index,
last_segment_char_on_line,
LLRect(text_left,
cur_top,
text_left + (text_width - remaining_pixels),
cur_top - line_height),
line_rect,
line_count));
cur_top -= llround((F32)line_height * mLineSpacingMult) + mLineSpacingPixels;
break;
}
// finished a segment and there are segments remaining on this line
// ...or finished a segment and there are segments remaining on this line
else
{
// subtract pixels used and increment segment
@ -1183,17 +1184,29 @@ void LLTextBase::reflow(S32 start_index)
mContentsRect.stretch(1);
}
// change mDocumentPanel document size to accomodate reflowed text
// change mDocumentView size to accomodate reflowed text
LLRect document_rect;
document_rect.setOriginAndSize(1, 1,
mScroller->getContentWindowRect().getWidth(),
llmax(mScroller->getContentWindowRect().getHeight(), mContentsRect.getHeight()));
mDocumentPanel->setShape(document_rect);
if (mScroller)
{
// document is size of scroller or size of text contents, whichever is larger
document_rect.setOriginAndSize(0, 0,
mScroller->getContentWindowRect().getWidth(),
llmax(mScroller->getContentWindowRect().getHeight(), mContentsRect.getHeight()));
}
else
{
// document size is just extents of reflowed text, reset to origin 0,0
document_rect.set(0,
getLocalRect().getHeight(),
getLocalRect().getWidth(),
llmin(0, getLocalRect().getHeight() - mContentsRect.getHeight()));
}
mDocumentView->setShape(document_rect);
// after making document big enough to hold all the text, move the text to fit in the document
if (!mLineInfoList.empty())
{
S32 delta_pos = mDocumentPanel->getRect().getHeight() - mLineInfoList.begin()->mRect.mTop - mVPad;
S32 delta_pos = mDocumentView->getRect().getHeight() - mLineInfoList.begin()->mRect.mTop - mVPad;
// move line segments to fit new document rect
for (line_list_t::iterator it = mLineInfoList.begin(); it != mLineInfoList.end(); ++it)
{
@ -1215,9 +1228,9 @@ void LLTextBase::reflow(S32 start_index)
}
// apply scroll constraints after reflowing text
if (!hasMouseCapture())
if (!hasMouseCapture() && mScroller)
{
LLRect visible_content_rect = mScroller->getVisibleContentRect();
LLRect visible_content_rect = getVisibleDocumentRect();
if (scrolled_to_bottom && mTrackEnd)
{
// keep bottom of text buffer visible
@ -1329,7 +1342,7 @@ S32 LLTextBase::getLineOffsetFromDocIndex( S32 startpos, bool include_wordwrap)
S32 LLTextBase::getFirstVisibleLine() const
{
LLRect visible_region = mScroller->getVisibleContentRect();
LLRect visible_region = getVisibleDocumentRect();
// binary search for line that starts before top of visible buffer
line_list_t::const_iterator iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mTop, compare_bottom());
@ -1339,7 +1352,7 @@ S32 LLTextBase::getFirstVisibleLine() const
std::pair<S32, S32> LLTextBase::getVisibleLines(bool fully_visible)
{
LLRect visible_region = mScroller->getVisibleContentRect();
LLRect visible_region = getVisibleDocumentRect();
line_list_t::const_iterator first_iter;
line_list_t::const_iterator last_iter;
@ -1370,12 +1383,12 @@ LLTextViewModel* LLTextBase::getViewModel() const
void LLTextBase::addDocumentChild(LLView* view)
{
mDocumentPanel->addChild(view);
mDocumentView->addChild(view);
}
void LLTextBase::removeDocumentChild(LLView* view)
{
mDocumentPanel->removeChild(view);
mDocumentView->removeChild(view);
}
@ -1481,11 +1494,10 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)
void LLTextBase::setText(const LLStringExplicit &utf8str)
{
// clear out the existing text and segments
clear();
getViewModel()->setDisplay(LLWStringUtil::null);
truncate();
createDefaultSegment();
clearSegments();
// createDefaultSegment();
startOfDoc();
deselect();
@ -1496,10 +1508,9 @@ void LLTextBase::setText(const LLStringExplicit &utf8str)
appendText(text, false);
needsReflow();
//resetDirty();
onValueChange(0, getLength());
needsReflow();
}
//virtual
@ -1767,7 +1778,7 @@ LLWString LLTextBase::getWText() const
S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const
{
// Figure out which line we're nearest to.
LLRect visible_region = mScroller->getVisibleContentRect();
LLRect visible_region = getVisibleDocumentRect();
// binary search for line that starts before local_y
line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), local_y - mTextRect.mBottom + visible_region.mBottom, compare_bottom());
@ -1838,7 +1849,7 @@ LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const
// find line that contains cursor
line_list_t::const_iterator line_iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), pos, line_end_compare());
LLRect scrolled_view_rect = mScroller->getVisibleContentRect();
LLRect scrolled_view_rect = getVisibleDocumentRect();
local_rect.mLeft = mTextRect.mLeft - scrolled_view_rect.mLeft + line_iter->mRect.mLeft;
local_rect.mBottom = mTextRect.mBottom + (line_iter->mRect.mBottom - scrolled_view_rect.mBottom);
local_rect.mTop = mTextRect.mBottom + (line_iter->mRect.mTop - scrolled_view_rect.mBottom);
@ -1917,7 +1928,7 @@ void LLTextBase::endOfDoc()
void LLTextBase::changePage( S32 delta )
{
const S32 PIXEL_OVERLAP_ON_PAGE_CHANGE = 10;
if (delta == 0) return;
if (delta == 0 || !mScroller) return;
LLRect cursor_rect = getLocalRectFromDocIndex(mCursorPos);
@ -1970,7 +1981,7 @@ void LLTextBase::changeLine( S32 delta )
new_line = line + 1;
}
LLRect visible_region = mScroller->getVisibleContentRect();
LLRect visible_region = getVisibleDocumentRect();
S32 new_cursor_pos = getDocIndexFromLocalCoord(mDesiredXPixel, mLineInfoList[new_line].mRect.mBottom + mTextRect.mBottom - visible_region.mBottom, TRUE);
setCursorPos(new_cursor_pos, true);
@ -2047,7 +2058,7 @@ S32 LLTextBase::getEditableIndex(S32 index, bool increasing_direction)
void LLTextBase::updateTextRect()
{
LLRect old_text_rect = mTextRect;
mTextRect = mScroller->getContentWindowRect();
mTextRect = mScroller ? mScroller->getContentWindowRect() : getLocalRect();
//FIXME: replace border with image?
if (mBorderVisible)
{
@ -2081,6 +2092,22 @@ void LLTextBase::endSelection()
}
}
// get portion of document that is visible in text editor
LLRect LLTextBase::getVisibleDocumentRect() const
{
if (mScroller)
{
return mScroller->getVisibleContentRect();
}
else
{
// entire document rect when not scrolling
LLRect doc_rect = mDocumentView->getLocalRect();
doc_rect.translate(-mDocumentView->getRect().mLeft, -mDocumentView->getRect().mBottom);
return doc_rect;
}
}
//
// LLTextSegment
//
@ -2150,6 +2177,7 @@ F32 LLNormalTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selec
{
if ( mStyle->isImage() && (start >= 0) && (end <= mEnd - mStart))
{
LLColor4 color = LLColor4::white % mEditor.getDrawContext().mAlpha;
LLUIImagePtr image = mStyle->getImage();
S32 style_image_height = image->getHeight();
S32 style_image_width = image->getWidth();
@ -2398,7 +2426,7 @@ S32 LLInlineViewSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin
void LLInlineViewSegment::updateLayout(const LLTextBase& editor)
{
LLRect start_rect = editor.getLocalRectFromDocIndex(mStart);
LLRect doc_rect = editor.getDocumentPanel()->getRect();
LLRect doc_rect = editor.getDocumentView()->getRect();
mView->setOrigin(doc_rect.mLeft + start_rect.mLeft, doc_rect.mBottom + start_rect.mBottom);
}

View File

@ -80,8 +80,7 @@ public:
border_visible,
track_end,
read_only,
hide_scrollbar,
clip_to_rect,
allow_scroll,
wrap,
use_ellipses,
allow_html,
@ -118,7 +117,6 @@ public:
// LLUICtrl interface
/*virtual*/ BOOL acceptsTextInput() const { return !mReadOnly; }
/*virtual*/ void clear();
/*virtual*/ void setColor( const LLColor4& c );
/*virtual*/ void setValue(const LLSD& value );
/*virtual*/ LLTextViewModel* getViewModel() const;
@ -149,16 +147,13 @@ public:
S32 getLength() const { return getWText().length(); }
S32 getLineCount() const { return mLineInfoList.size(); }
class DocumentPanel : public LLPanel
{
public:
DocumentPanel(const Params&);
};
void addDocumentChild(LLView* view);
void removeDocumentChild(LLView* view);
const DocumentPanel* getDocumentPanel() const { return mDocumentPanel; }
const LLView* getDocumentView() const { return mDocumentView; }
LLRect getTextRect() { return mTextRect; }
LLRect getContentsRect();
LLRect getVisibleDocumentRect() const;
S32 getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const;
LLRect getLocalRectFromDocIndex(S32 pos) const;
@ -344,13 +339,12 @@ protected:
bool mUseEllipses;
bool mTrackEnd; // if true, keeps scroll position at end of document during resize
bool mReadOnly;
bool mClip;
bool mHideScrollbar;
bool mBGVisible; // render background?
S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes
// support widgets
LLContextMenu* mPopupMenu;
DocumentPanel* mDocumentPanel;
LLView* mDocumentView;
class LLScrollContainer* mScroller;
// transient state

Some files were not shown because too many files have changed in this diff Show More