Apertura del repositorio

This commit is contained in:
2025-05-24 18:09:39 -03:00
parent 76e6359dad
commit d883ddd0d0
35253 changed files with 2891973 additions and 2 deletions
+179
View File
@@ -0,0 +1,179 @@
/**
* @file llcorehttp_test
* @brief Main test runner
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llcorehttp_test.h"
#include <iostream>
#include <sstream>
// These are not the right way in viewer for some reason:
// #include <tut/tut.hpp>
// #include <tut/tut_reporter.hpp>
// This works:
#include "../test/lltut.h"
// Pull in each of the test sets
#include "test_bufferarray.hpp"
#include "test_bufferstream.hpp"
#include "test_httpstatus.hpp"
#include "test_refcounted.hpp"
#include "test_httpoperation.hpp"
// As of 2019-06-28, test_httprequest.hpp consistently crashes on Mac Release
// builds for reasons not yet diagnosed.
#if ! (LL_DARWIN && LL_RELEASE)
#include "test_httprequest.hpp"
#endif
#include "test_httpheaders.hpp"
#include "test_httprequestqueue.hpp"
#include "_httpservice.h"
#include "llproxy.h"
#include "llcleanup.h"
void ssl_thread_id_callback(CRYPTO_THREADID*);
void ssl_locking_callback(int mode, int type, const char * file, int line);
#if 0 // lltut provides main and runner
namespace tut
{
test_runner_singleton runner;
}
int main()
{
curl_global_init(CURL_GLOBAL_ALL);
// *FIXME: Need threaded/SSL curl setup here.
tut::reporter reporter;
tut::runner.get().set_callback(&reporter);
tut::runner.get().run_tests();
return !reporter.all_ok();
curl_global_cleanup();
}
#endif // 0
int ssl_mutex_count(0);
LLCoreInt::HttpMutex ** ssl_mutex_list = NULL;
void init_curl()
{
curl_global_init(CURL_GLOBAL_ALL);
ssl_mutex_count = CRYPTO_num_locks();
if (ssl_mutex_count > 0)
{
ssl_mutex_list = new LLCoreInt::HttpMutex * [ssl_mutex_count];
for (int i(0); i < ssl_mutex_count; ++i)
{
ssl_mutex_list[i] = new LLCoreInt::HttpMutex;
}
CRYPTO_set_locking_callback(ssl_locking_callback);
CRYPTO_THREADID_set_callback(ssl_thread_id_callback);
}
LLProxy::getInstance();
}
void term_curl()
{
SUBSYSTEM_CLEANUP(LLProxy);
CRYPTO_set_locking_callback(NULL);
for (int i(0); i < ssl_mutex_count; ++i)
{
delete ssl_mutex_list[i];
}
delete [] ssl_mutex_list;
}
void ssl_thread_id_callback(CRYPTO_THREADID* pthreadid)
{
#if defined(WIN32)
CRYPTO_THREADID_set_pointer(pthreadid, GetCurrentThread());
#else
CRYPTO_THREADID_set_pointer(pthreadid, pthread_self());
#endif
}
void ssl_locking_callback(int mode, int type, const char * /* file */, int /* line */)
{
if (type >= 0 && type < ssl_mutex_count)
{
if (mode & CRYPTO_LOCK)
{
ssl_mutex_list[type]->lock();
}
else
{
ssl_mutex_list[type]->unlock();
}
}
}
std::string get_base_url()
{
const char * env(getenv("LL_TEST_PORT"));
if (! env)
{
std::cerr << "LL_TEST_PORT environment variable missing." << std::endl;
std::cerr << "Test expects to run in test_llcorehttp_peer.py script." << std::endl;
tut::ensure("LL_TEST_PORT set in environment", NULL != env);
}
int port(atoi(env));
std::ostringstream out;
out << "http://localhost:" << port << "/";
return out.str();
}
void stop_thread(LLCore::HttpRequest * req)
{
if (req)
{
req->requestStopThread(LLCore::HttpHandler::ptr_t());
int count = 0;
int limit = 10;
while (count++ < limit && ! HttpService::isStopped())
{
req->update(1000);
usleep(100000);
}
}
}
+64
View File
@@ -0,0 +1,64 @@
/**
* @file llcorehttp_test.h
* @brief Main test runner
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef _LLCOREHTTP_TEST_H_
#define _LLCOREHTTP_TEST_H_
#include "linden_common.h" // Modifies curl interfaces
#include <curl/curl.h>
#include <openssl/crypto.h>
#include <string>
#include "httprequest.h"
// Initialization and cleanup for libcurl. Mainly provides
// a mutex callback for SSL and a thread ID hash for libcurl.
// If you don't use these (or equivalent) and do use libcurl,
// you'll see stalls and other anomalies when performing curl
// operations.
extern void init_curl();
extern void term_curl();
extern std::string get_base_url();
extern void stop_thread(LLCore::HttpRequest * req);
class ScopedCurlInit
{
public:
ScopedCurlInit()
{
init_curl();
}
~ScopedCurlInit()
{
term_curl();
}
};
#endif // _LLCOREHTTP_TEST_H_
+174
View File
@@ -0,0 +1,174 @@
/**
* @file test_allocator.cpp
* @brief quick and dirty allocator for tracking memory allocations
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "test_allocator.h"
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050
#include <libkern/OSAtomic.h>
#elif defined(_MSC_VER)
#include <Windows.h>
#elif (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ ) > 40100
// atomic extensions are built into GCC on posix platforms
#endif
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <iostream>
#include <new>
#include <boost/thread.hpp>
struct BlockHeader
{
struct Block * next;
std::size_t size;
bool in_use;
};
struct Block
{
BlockHeader hdr;
unsigned char data[1];
};
#define TRACE_MSG(val) std::cout << __FUNCTION__ << "(" << val << ") [" << __FILE__ << ":" << __LINE__ << "]" << std::endl;
static unsigned char MemBuf[ 4096 * 1024 ];
Block * pNext = static_cast<Block *>(static_cast<void *>(MemBuf));
volatile std::size_t MemTotal = 0;
// cross-platform compare and swap operation
static bool CAS(void * volatile * ptr, void * expected, void * new_value)
{
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050
return OSAtomicCompareAndSwapPtr( expected, new_value, ptr );
#elif defined(_MSC_VER)
return expected == InterlockedCompareExchangePointer( ptr, new_value, expected );
#elif (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ ) > 40100
return __sync_bool_compare_and_swap( ptr, expected, new_value );
#endif
}
static void * GetMem(std::size_t size)
{
// TRACE_MSG(size);
volatile Block * pBlock = NULL;
volatile Block * pNewNext = NULL;
// do a lock-free update of the global next pointer
do
{
pBlock = pNext;
pNewNext = (volatile Block *)(pBlock->data + size);
} while(! CAS((void * volatile *) &pNext, (void *) pBlock, (void *) pNewNext));
// if we get here, we safely carved out a block of memory in the
// memory pool...
// initialize our block
pBlock->hdr.next = (Block *)(pBlock->data + size);
pBlock->hdr.size = size;
pBlock->hdr.in_use = true;
memset((void *) pBlock->data, 0, pBlock->hdr.size);
// do a lock-free update of the global memory total
volatile size_t total = 0;
volatile size_t new_total = 0;
do
{
total = MemTotal;
new_total = total + size;
} while (! CAS((void * volatile *) &MemTotal, (void *) total, (void *) new_total));
return (void *) pBlock->data;
}
static void FreeMem(void * p)
{
// get the pointer to the block record
Block * pBlock = (Block *)((unsigned char *) p - sizeof(BlockHeader));
// TRACE_MSG(pBlock->hdr.size);
bool * cur_in_use = &(pBlock->hdr.in_use);
volatile bool in_use = false;
bool new_in_use = false;
do
{
in_use = pBlock->hdr.in_use;
} while (! CAS((void * volatile *) cur_in_use, (void *) in_use, (void *) new_in_use));
// do a lock-free update of the global memory total
volatile size_t total = 0;
volatile size_t new_total = 0;
do
{
total = MemTotal;
new_total = total - pBlock->hdr.size;
} while (! CAS((void * volatile *)&MemTotal, (void *) total, (void *) new_total));
}
std::size_t GetMemTotal()
{
return MemTotal;
}
void * operator new(std::size_t size) //throw(std::bad_alloc)
{
return GetMem( size );
}
void * operator new[](std::size_t size) //throw(std::bad_alloc)
{
return GetMem( size );
}
void operator delete(void * p) throw()
{
if (p)
{
FreeMem( p );
}
}
void operator delete[](void * p) throw()
{
if (p)
{
FreeMem( p );
}
}
+42
View File
@@ -0,0 +1,42 @@
/**
* @file test_allocator.h
* @brief quick and dirty allocator for tracking memory allocations
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef TEST_ALLOCATOR_H
#define TEST_ALLOCATOR_H
#include <cstdlib>
#include <new>
#error 2019-06-27 Do not use test_allocator.h -- does not respect alignment.
size_t GetMemTotal();
void * operator new(std::size_t size); //throw (std::bad_alloc);
void * operator new[](std::size_t size); //throw (std::bad_alloc);
void operator delete(void * p) throw ();
void operator delete[](void * p) throw ();
#endif // TEST_ALLOCATOR_H
+380
View File
@@ -0,0 +1,380 @@
/**
* @file test_bufferarray.hpp
* @brief unit tests for the LLCore::BufferArray class
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef TEST_LLCORE_BUFFER_ARRAY_H_
#define TEST_LLCORE_BUFFER_ARRAY_H_
#include "bufferarray.h"
#include <iostream>
using namespace LLCore;
namespace tut
{
struct BufferArrayTestData
{
// the test objects inherit from this so the member functions and variables
// can be referenced directly inside of the test functions.
};
typedef test_group<BufferArrayTestData> BufferArrayTestGroupType;
typedef BufferArrayTestGroupType::object BufferArrayTestObjectType;
BufferArrayTestGroupType BufferArrayTestGroup("BufferArray Tests");
template <> template <>
void BufferArrayTestObjectType::test<1>()
{
set_test_name("BufferArray construction");
// create a new ref counted object with an implicit reference
BufferArray * ba = new BufferArray();
ensure("One ref on construction of BufferArray", ba->getRefCount() == 1);
ensure("Nothing in BA", 0 == ba->size());
// Try to read
char buffer[20];
size_t read_len(ba->read(0, buffer, sizeof(buffer)));
ensure("Read returns empty", 0 == read_len);
// release the implicit reference, causing the object to be released
ba->release();
}
template <> template <>
void BufferArrayTestObjectType::test<2>()
{
set_test_name("BufferArray single write");
// create a new ref counted object with an implicit reference
BufferArray * ba = new BufferArray();
// write some data to the buffer
char str1[] = "abcdefghij";
char buffer[256];
size_t len = ba->write(0, str1, strlen(str1));
ensure("Wrote length correct", strlen(str1) == len);
ensure("Recorded size correct", strlen(str1) == ba->size());
// read some data back
memset(buffer, 'X', sizeof(buffer));
len = ba->read(2, buffer, 2);
ensure("Read length correct", 2 == len);
ensure("Read content correct", 'c' == buffer[0] && 'd' == buffer[1]);
ensure("Read didn't overwrite", 'X' == buffer[2]);
// release the implicit reference, causing the object to be released
ba->release();
}
template <> template <>
void BufferArrayTestObjectType::test<3>()
{
set_test_name("BufferArray multiple writes");
// create a new ref counted object with an implicit reference
BufferArray * ba = new BufferArray();
// write some data to the buffer
char str1[] = "abcdefghij";
size_t str1_len(strlen(str1));
char buffer[256];
size_t len = ba->write(0, str1, str1_len);
ensure("Wrote length correct", str1_len == len);
ensure("Recorded size correct", str1_len == ba->size());
// again...
len = ba->write(str1_len, str1, strlen(str1));
ensure("Wrote length correct", str1_len == len);
ensure("Recorded size correct", (2 * str1_len) == ba->size());
// read some data back
memset(buffer, 'X', sizeof(buffer));
len = ba->read(8, buffer, 4);
ensure("Read length correct", 4 == len);
ensure("Read content correct", 'i' == buffer[0] && 'j' == buffer[1]);
ensure("Read content correct", 'a' == buffer[2] && 'b' == buffer[3]);
ensure("Read didn't overwrite", 'X' == buffer[4]);
// Read whole thing
memset(buffer, 'X', sizeof(buffer));
len = ba->read(0, buffer, sizeof(buffer));
ensure("Read length correct", (2 * str1_len) == len);
ensure("Read content correct (3)", 0 == strncmp(buffer, str1, str1_len));
ensure("Read content correct (4)", 0 == strncmp(&buffer[str1_len], str1, str1_len));
ensure("Read didn't overwrite (5)", 'X' == buffer[2 * str1_len]);
// release the implicit reference, causing the object to be released
ba->release();
}
template <> template <>
void BufferArrayTestObjectType::test<4>()
{
set_test_name("BufferArray overwriting");
// create a new ref counted object with an implicit reference
BufferArray * ba = new BufferArray();
// write some data to the buffer
char str1[] = "abcdefghij";
size_t str1_len(strlen(str1));
char str2[] = "ABCDEFGHIJ";
char buffer[256];
size_t len = ba->write(0, str1, str1_len);
ensure("Wrote length correct", str1_len == len);
ensure("Recorded size correct", str1_len == ba->size());
// again...
len = ba->write(str1_len, str1, strlen(str1));
ensure("Wrote length correct", str1_len == len);
ensure("Recorded size correct", (2 * str1_len) == ba->size());
// reposition and overwrite
len = ba->write(8, str2, 4);
ensure("Overwrite length correct", 4 == len);
// Leave position and read verifying content (stale really from seek() days)
memset(buffer, 'X', sizeof(buffer));
len = ba->read(12, buffer, 4);
ensure("Read length correct", 4 == len);
ensure("Read content correct", 'c' == buffer[0] && 'd' == buffer[1]);
ensure("Read content correct.2", 'e' == buffer[2] && 'f' == buffer[3]);
ensure("Read didn't overwrite", 'X' == buffer[4]);
// reposition and check
len = ba->read(6, buffer, 8);
ensure("Read length correct.2", 8 == len);
ensure("Read content correct.3", 'g' == buffer[0] && 'h' == buffer[1]);
ensure("Read content correct.4", 'A' == buffer[2] && 'B' == buffer[3]);
ensure("Read content correct.5", 'C' == buffer[4] && 'D' == buffer[5]);
ensure("Read content correct.6", 'c' == buffer[6] && 'd' == buffer[7]);
ensure("Read didn't overwrite.7", 'X' == buffer[8]);
// release the implicit reference, causing the object to be released
ba->release();
}
template <> template <>
void BufferArrayTestObjectType::test<5>()
{
set_test_name("BufferArray multiple writes - sequential reads");
// create a new ref counted object with an implicit reference
BufferArray * ba = new BufferArray();
// write some data to the buffer
char str1[] = "abcdefghij";
size_t str1_len(strlen(str1));
char buffer[256];
size_t len = ba->write(0, str1, str1_len);
ensure("Wrote length correct", str1_len == len);
ensure("Recorded size correct", str1_len == ba->size());
// again...
len = ba->write(str1_len, str1, str1_len);
ensure("Wrote length correct", str1_len == len);
ensure("Recorded size correct", (2 * str1_len) == ba->size());
// read some data back
memset(buffer, 'X', sizeof(buffer));
len = ba->read(8, buffer, 4);
ensure("Read length correct", 4 == len);
ensure("Read content correct", 'i' == buffer[0] && 'j' == buffer[1]);
ensure("Read content correct.2", 'a' == buffer[2] && 'b' == buffer[3]);
ensure("Read didn't overwrite", 'X' == buffer[4]);
// Read some more without repositioning
memset(buffer, 'X', sizeof(buffer));
len = ba->read(12, buffer, sizeof(buffer));
ensure("Read length correct", (str1_len - 2) == len);
ensure("Read content correct.3", 0 == strncmp(buffer, str1+2, str1_len-2));
ensure("Read didn't overwrite.2", 'X' == buffer[str1_len-1]);
// release the implicit reference, causing the object to be released
ba->release();
}
template <> template <>
void BufferArrayTestObjectType::test<6>()
{
set_test_name("BufferArray overwrite spanning blocks and appending");
// create a new ref counted object with an implicit reference
BufferArray * ba = new BufferArray();
// write some data to the buffer
char str1[] = "abcdefghij";
size_t str1_len(strlen(str1));
char str2[] = "ABCDEFGHIJKLMNOPQRST";
size_t str2_len(strlen(str2));
char buffer[256];
size_t len = ba->write(0, str1, str1_len);
ensure("Wrote length correct", str1_len == len);
ensure("Recorded size correct", str1_len == ba->size());
// again...
len = ba->write(str1_len, str1, strlen(str1));
ensure("Wrote length correct", str1_len == len);
ensure("Recorded size correct", (2 * str1_len) == ba->size());
// reposition and overwrite
len = ba->write(8, str2, str2_len);
ensure("Overwrite length correct", str2_len == len);
// Leave position and read verifying content
memset(buffer, 'X', sizeof(buffer));
len = ba->read(8 + str2_len, buffer, 0);
ensure("Read length correct", 0 == len);
ensure("Read didn't overwrite", 'X' == buffer[0]);
// reposition and check
len = ba->read(0, buffer, sizeof(buffer));
ensure("Read length correct.2", (str1_len + str2_len - 2) == len);
ensure("Read content correct", 0 == strncmp(buffer, str1, str1_len-2));
ensure("Read content correct.2", 0 == strncmp(buffer+str1_len-2, str2, str2_len));
ensure("Read didn't overwrite.2", 'X' == buffer[str1_len + str2_len - 2]);
// release the implicit reference, causing the object to be released
ba->release();
}
template <> template <>
void BufferArrayTestObjectType::test<7>()
{
set_test_name("BufferArray overwrite spanning blocks and sequential writes");
// create a new ref counted object with an implicit reference
BufferArray * ba = new BufferArray();
// write some data to the buffer
char str1[] = "abcdefghij";
size_t str1_len(strlen(str1));
char str2[] = "ABCDEFGHIJKLMNOPQRST";
size_t str2_len(strlen(str2));
char buffer[256];
// 2x str1
size_t len = ba->write(0, str1, str1_len);
len = ba->write(str1_len, str1, str1_len);
// reposition and overwrite
len = ba->write(6, str2, 2);
ensure("Overwrite length correct", 2 == len);
len = ba->write(8, str2, 2);
ensure("Overwrite length correct.2", 2 == len);
len = ba->write(10, str2, 2);
ensure("Overwrite length correct.3", 2 == len);
// append some data
len = ba->append(str2, str2_len);
ensure("Append length correct", str2_len == len);
// append some more
void * out_buf(ba->appendBufferAlloc(str1_len));
memcpy(out_buf, str1, str1_len);
// And some final writes
len = ba->write(3 * str1_len + str2_len, str2, 2);
ensure("Write length correct.2", 2 == len);
// Check contents
memset(buffer, 'X', sizeof(buffer));
len = ba->read(0, buffer, sizeof(buffer));
ensure("Final buffer length correct", (3 * str1_len + str2_len + 2) == len);
ensure("Read content correct", 0 == strncmp(buffer, str1, 6));
ensure("Read content correct.2", 0 == strncmp(buffer + 6, str2, 2));
ensure("Read content correct.3", 0 == strncmp(buffer + 8, str2, 2));
ensure("Read content correct.4", 0 == strncmp(buffer + 10, str2, 2));
ensure("Read content correct.5", 0 == strncmp(buffer + str1_len + 2, str1 + 2, str1_len - 2));
ensure("Read content correct.6", 0 == strncmp(buffer + str1_len + str1_len, str2, str2_len));
ensure("Read content correct.7", 0 == strncmp(buffer + str1_len + str1_len + str2_len, str1, str1_len));
ensure("Read content correct.8", 0 == strncmp(buffer + str1_len + str1_len + str2_len + str1_len, str2, 2));
ensure("Read didn't overwrite", 'X' == buffer[str1_len + str1_len + str2_len + str1_len + 2]);
// release the implicit reference, causing the object to be released
ba->release();
}
template <> template <>
void BufferArrayTestObjectType::test<8>()
{
set_test_name("BufferArray zero-length appendBufferAlloc");
// create a new ref counted object with an implicit reference
BufferArray * ba = new BufferArray();
// write some data to the buffer
char str1[] = "abcdefghij";
size_t str1_len(strlen(str1));
char str2[] = "ABCDEFGHIJKLMNOPQRST";
size_t str2_len(strlen(str2));
char buffer[256];
// 2x str1
size_t len = ba->write(0, str1, str1_len);
len = ba->write(str1_len, str1, str1_len);
// zero-length allocate (we allow this with a valid pointer returned)
void * out_buf(ba->appendBufferAlloc(0));
ensure("Buffer from zero-length appendBufferAlloc non-NULL", NULL != out_buf);
// Do it again
void * out_buf2(ba->appendBufferAlloc(0));
ensure("Buffer from zero-length appendBufferAlloc non-NULL.2", NULL != out_buf2);
ensure("Two zero-length appendBufferAlloc buffers distinct", out_buf != out_buf2);
// And some final writes
len = ba->write(2 * str1_len, str2, str2_len);
// Check contents
memset(buffer, 'X', sizeof(buffer));
len = ba->read(0, buffer, sizeof(buffer));
ensure("Final buffer length correct", (2 * str1_len + str2_len) == len);
ensure("Read content correct.1", 0 == strncmp(buffer, str1, str1_len));
ensure("Read content correct.2", 0 == strncmp(buffer + str1_len, str1, str1_len));
ensure("Read content correct.3", 0 == strncmp(buffer + str1_len + str1_len, str2, str2_len));
ensure("Read didn't overwrite", 'X' == buffer[str1_len + str1_len + str2_len]);
// release the implicit reference, causing the object to be released
ba->release();
}
} // end namespace tut
#endif // TEST_LLCORE_BUFFER_ARRAY_H_
@@ -0,0 +1,252 @@
/**
* @file test_bufferstream.hpp
* @brief unit tests for the LLCore::BufferArrayStreamBuf/BufferArrayStream classes
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef TEST_LLCORE_BUFFER_STREAM_H_
#define TEST_LLCORE_BUFFER_STREAM_H_
#include "bufferstream.h"
#include <iostream>
#include "llsd.h"
#include "llsdserialize.h"
using namespace LLCore;
namespace tut
{
struct BufferStreamTestData
{
// the test objects inherit from this so the member functions and variables
// can be referenced directly inside of the test functions.
};
typedef test_group<BufferStreamTestData> BufferStreamTestGroupType;
typedef BufferStreamTestGroupType::object BufferStreamTestObjectType;
BufferStreamTestGroupType BufferStreamTestGroup("BufferStream Tests");
typedef BufferArrayStreamBuf::traits_type tst_traits_t;
template <> template <>
void BufferStreamTestObjectType::test<1>()
{
set_test_name("BufferArrayStreamBuf construction with NULL BufferArray");
// create a new ref counted object with an implicit reference
BufferArrayStreamBuf * bsb = new BufferArrayStreamBuf(NULL);
// Not much will work with a NULL
ensure("underflow() on NULL fails", tst_traits_t::eof() == bsb->underflow());
ensure("uflow() on NULL fails", tst_traits_t::eof() == bsb->uflow());
ensure("pbackfail() on NULL fails", tst_traits_t::eof() == bsb->pbackfail('c'));
ensure("showmanyc() on NULL fails", bsb->showmanyc() == -1);
ensure("overflow() on NULL fails", tst_traits_t::eof() == bsb->overflow('c'));
ensure("xsputn() on NULL fails", bsb->xsputn("blah", 4) == 0);
ensure("seekoff() on NULL fails", bsb->seekoff(0, std::ios_base::beg, std::ios_base::in) == std::streampos(-1));
// release the implicit reference, causing the object to be released
delete bsb;
bsb = NULL;
}
template <> template <>
void BufferStreamTestObjectType::test<2>()
{
set_test_name("BufferArrayStream construction with NULL BufferArray");
// create a new ref counted object with an implicit reference
BufferArrayStream * bas = new BufferArrayStream(NULL);
// Not much will work with a NULL here
ensure("eof() is false on NULL", ! bas->eof());
ensure("fail() is false on NULL", ! bas->fail());
ensure("good() on NULL", bas->good());
// release the implicit reference, causing the object to be released
delete bas;
bas = NULL;
}
template <> template <>
void BufferStreamTestObjectType::test<3>()
{
set_test_name("BufferArrayStreamBuf construction with empty BufferArray");
// create a new ref counted BufferArray with implicit reference
BufferArray * ba = new BufferArray;
BufferArrayStreamBuf * bsb = new BufferArrayStreamBuf(ba);
// I can release my ref on the BA
ba->release();
ba = NULL;
// release the implicit reference, causing the object to be released
delete bsb;
bsb = NULL;
}
template <> template <>
void BufferStreamTestObjectType::test<4>()
{
set_test_name("BufferArrayStream construction with empty BufferArray");
// create a new ref counted BufferArray with implicit reference
BufferArray * ba = new BufferArray;
{
// create a new ref counted object with an implicit reference
BufferArrayStream bas(ba);
}
// release the implicit reference, causing the object to be released
ba->release();
ba = NULL;
}
template <> template <>
void BufferStreamTestObjectType::test<5>()
{
set_test_name("BufferArrayStreamBuf construction with real BufferArray");
// create a new ref counted BufferArray with implicit reference
BufferArray * ba = new BufferArray;
const char * content("This is a string. A fragment.");
const size_t c_len(strlen(content));
ba->append(content, c_len);
// Creat an adapter for the BufferArray
BufferArrayStreamBuf * bsb = new BufferArrayStreamBuf(ba);
// I can release my ref on the BA
ba->release();
ba = NULL;
// Various static state
ensure("underflow() returns 'T'", bsb->underflow() == 'T');
ensure("underflow() returns 'T' again", bsb->underflow() == 'T');
ensure("uflow() returns 'T'", bsb->uflow() == 'T');
ensure("uflow() returns 'h'", bsb->uflow() == 'h');
ensure("pbackfail('i') fails", tst_traits_t::eof() == bsb->pbackfail('i'));
ensure("pbackfail('T') fails", tst_traits_t::eof() == bsb->pbackfail('T'));
ensure("pbackfail('h') succeeds", bsb->pbackfail('h') == 'h');
ensure("showmanyc() is everything but the 'T'", bsb->showmanyc() == (c_len - 1));
ensure("overflow() appends", bsb->overflow('c') == 'c');
ensure("showmanyc() reflects append", bsb->showmanyc() == (c_len - 1 + 1));
ensure("xsputn() appends some more", bsb->xsputn("bla!", 4) == 4);
ensure("showmanyc() reflects 2nd append", bsb->showmanyc() == (c_len - 1 + 5));
ensure("seekoff() succeeds", bsb->seekoff(0, std::ios_base::beg, std::ios_base::in) == std::streampos(0));
ensure("seekoff() succeeds 2", bsb->seekoff(4, std::ios_base::cur, std::ios_base::in) == std::streampos(4));
ensure("showmanyc() picks up seekoff", bsb->showmanyc() == (c_len + 5 - 4));
ensure("seekoff() succeeds 3", bsb->seekoff(0, std::ios_base::end, std::ios_base::in) == std::streampos(c_len + 4));
ensure("pbackfail('!') succeeds", tst_traits_t::eof() == bsb->pbackfail('!'));
// release the implicit reference, causing the object to be released
delete bsb;
bsb = NULL;
}
template <> template <>
void BufferStreamTestObjectType::test<6>()
{
set_test_name("BufferArrayStream construction with real BufferArray");
// create a new ref counted BufferArray with implicit reference
BufferArray * ba = new BufferArray;
//const char * content("This is a string. A fragment.");
//const size_t c_len(strlen(content));
//ba->append(content, strlen(content));
{
// Creat an adapter for the BufferArray
BufferArrayStream bas(ba);
// Basic operations
bas << "Hello" << 27 << ".";
ensure("BA length 8", ba->size() == 8);
std::string str;
bas >> str;
ensure("reads correctly", str == "Hello27.");
}
// release the implicit reference, causing the object to be released
ba->release();
ba = NULL;
}
template <> template <>
void BufferStreamTestObjectType::test<7>()
{
set_test_name("BufferArrayStream with LLSD serialization");
// create a new ref counted BufferArray with implicit reference
BufferArray * ba = new BufferArray;
{
// Creat an adapter for the BufferArray
BufferArrayStream bas(ba);
// LLSD
LLSD llsd = LLSD::emptyMap();
llsd["int"] = LLSD::Integer(3);
llsd["float"] = LLSD::Real(923289.28992);
llsd["string"] = LLSD::String("aksjdl;ajsdgfjgfal;sdgjakl;sdfjkl;ajsdfkl;ajsdfkl;jaskl;dfj");
LLSD llsd_map = LLSD::emptyMap();
llsd_map["int"] = LLSD::Integer(-2889);
llsd_map["float"] = LLSD::Real(2.37829e32);
llsd_map["string"] = LLSD::String("OHIGODHSPDGHOSDHGOPSHDGP");
llsd["map"] = llsd_map;
// Serialize it
LLSDSerialize::toXML(llsd, bas);
std::string str;
bas >> str;
// std::cout << "SERIALIZED LLSD: " << str << std::endl;
ensure("Extracted string has reasonable length", str.size() > 60);
}
// release the implicit reference, causing the object to be released
ba->release();
ba = NULL;
}
} // end namespace tut
#endif // TEST_LLCORE_BUFFER_STREAM_H_
+392
View File
@@ -0,0 +1,392 @@
/**
* @file test_httpheaders.hpp
* @brief unit tests for the LLCore::HttpHeaders class
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012-2013, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef TEST_LLCORE_HTTP_HEADERS_H_
#define TEST_LLCORE_HTTP_HEADERS_H_
#include "httpheaders.h"
#include <iostream>
using namespace LLCoreInt;
namespace tut
{
struct HttpHeadersTestData
{
// the test objects inherit from this so the member functions and variables
// can be referenced directly inside of the test functions.
};
typedef test_group<HttpHeadersTestData> HttpHeadersTestGroupType;
typedef HttpHeadersTestGroupType::object HttpHeadersTestObjectType;
HttpHeadersTestGroupType HttpHeadersTestGroup("HttpHeaders Tests");
template <> template <>
void HttpHeadersTestObjectType::test<1>()
{
set_test_name("HttpHeaders construction");
// create a new ref counted object with an implicit reference
HttpHeaders::ptr_t headers = HttpHeaders::ptr_t(new HttpHeaders());
ensure("Nothing in headers", 0 == headers->size());
// release the implicit reference, causing the object to be released
headers.reset();
}
template <> template <>
void HttpHeadersTestObjectType::test<2>()
{
set_test_name("HttpHeaders construction");
// create a new ref counted object with an implicit reference
HttpHeaders::ptr_t headers = HttpHeaders::ptr_t(new HttpHeaders());
{
// Append a few strings
std::string str1n("Pragma");
std::string str1v("");
headers->append(str1n, str1v);
std::string str2n("Accept");
std::string str2v("application/json");
headers->append(str2n, str2v);
ensure("Headers retained", 2 == headers->size());
HttpHeaders::container_t & c(headers->getContainerTESTONLY());
ensure("First name is first name", c[0].first == str1n);
ensure("First value is first value", c[0].second == str1v);
ensure("Second name is second name", c[1].first == str2n);
ensure("Second value is second value", c[1].second == str2v);
}
// release the implicit reference, causing the object to be released
headers.reset();
}
template <> template <>
void HttpHeadersTestObjectType::test<3>()
{
set_test_name("HttpHeaders basic find");
// create a new ref counted object with an implicit reference
HttpHeaders::ptr_t headers = HttpHeaders::ptr_t(new HttpHeaders());
{
// Append a few strings
std::string str1n("Uno");
std::string str1v("1");
headers->append(str1n, str1v);
std::string str2n("doS");
std::string str2v("2-2-2-2");
headers->append(str2n, str2v);
std::string str3n("TRES");
std::string str3v("trois gymnopedie");
headers->append(str3n, str3v);
ensure("Headers retained", 3 == headers->size());
const std::string * result(NULL);
// Find a header
result = headers->find("TRES");
ensure("Found the last item", result != NULL);
ensure("Last item is a nice", result != NULL && str3v == *result);
// appends above are raw and find is case sensitive
result = headers->find("TReS");
ensure("Last item not found due to case", result == NULL);
result = headers->find("TRE");
ensure("Last item not found due to prefixing (1)", result == NULL);
result = headers->find("TRESS");
ensure("Last item not found due to prefixing (2)", result == NULL);
}
// release the implicit reference, causing the object to be released
headers.reset();
}
template <> template <>
void HttpHeadersTestObjectType::test<4>()
{
set_test_name("HttpHeaders normalized header entry");
// create a new ref counted object with an implicit reference
HttpHeaders::ptr_t headers = HttpHeaders::ptr_t(new HttpHeaders());
{
static char line1[] = " AcCePT : image/yourfacehere";
static char line1v[] = "image/yourfacehere";
headers->appendNormal(line1, sizeof(line1) - 1);
ensure("First append worked in some fashion", 1 == headers->size());
const std::string * result(NULL);
// Find a header
result = headers->find("accept");
ensure("Found 'accept'", result != NULL);
ensure("accept value has face", result != NULL && *result == line1v);
// Left-clean on value
static char line2[] = " next : \t\tlinejunk \t";
headers->appendNormal(line2, sizeof(line2) - 1);
ensure("Second append worked", 2 == headers->size());
result = headers->find("next");
ensure("Found 'next'", result != NULL);
ensure("next value is left-clean", result != NULL &&
*result == "linejunk \t");
// First value unmolested
result = headers->find("accept");
ensure("Found 'accept' again", result != NULL);
ensure("accept value has face", result != NULL && *result == line1v);
// Colons in value are okay
static char line3[] = "FancY-PANTs::plop:-neuf-=vleem=";
static char line3v[] = ":plop:-neuf-=vleem=";
headers->appendNormal(line3, sizeof(line3) - 1);
ensure("Third append worked", 3 == headers->size());
result = headers->find("fancy-pants");
ensure("Found 'fancy-pants'", result != NULL);
ensure("fancy-pants value has colons", result != NULL && *result == line3v);
// Zero-length value
static char line4[] = "all-talk-no-walk:";
headers->appendNormal(line4, sizeof(line4) - 1);
ensure("Fourth append worked", 4 == headers->size());
result = headers->find("all-talk-no-walk");
ensure("Found 'all-talk'", result != NULL);
ensure("al-talk value is zero-length", result != NULL && result->size() == 0);
// Zero-length name
static char line5[] = ":all-talk-no-walk";
static char line5v[] = "all-talk-no-walk";
headers->appendNormal(line5, sizeof(line5) - 1);
ensure("Fifth append worked", 5 == headers->size());
result = headers->find("");
ensure("Found no-name", result != NULL);
ensure("no-name value is something", result != NULL && *result == line5v);
// Lone colon is still something
headers->clear();
static char line6[] = " :";
headers->appendNormal(line6, sizeof(line6) - 1);
ensure("Sixth append worked", 1 == headers->size());
result = headers->find("");
ensure("Found 2nd no-name", result != NULL);
ensure("2nd no-name value is nothing", result != NULL && result->size() == 0);
// Line without colons is taken as-is and unstripped in name
static char line7[] = " \toskdgioasdghaosdghoowg28342908tg8902hg0hwedfhqew890v7qh0wdebv78q0wdevbhq>?M>BNM<ZV>?NZ? \t";
headers->appendNormal(line7, sizeof(line7) - 1);
ensure("Seventh append worked", 2 == headers->size());
result = headers->find(line7);
ensure("Found whatsit line", result != NULL);
ensure("Whatsit line has no value", result != NULL && result->size() == 0);
// Normaling interface heeds the byte count, doesn't look for NUL-terminator
static char line8[] = "binary:ignorestuffontheendofthis";
headers->appendNormal(line8, 13);
ensure("Eighth append worked", 3 == headers->size());
result = headers->find("binary");
ensure("Found 'binary'", result != NULL);
ensure("binary value was limited to 'ignore'", result != NULL &&
*result == "ignore");
}
// release the implicit reference, causing the object to be released
headers.reset();
}
// Verify forward iterator finds everything as expected
template <> template <>
void HttpHeadersTestObjectType::test<5>()
{
set_test_name("HttpHeaders iterator tests");
// create a new ref counted object with an implicit reference
HttpHeaders::ptr_t headers = HttpHeaders::ptr_t(new HttpHeaders());
HttpHeaders::iterator end(headers->end()), begin(headers->begin());
ensure("Empty container has equal begin/end const iterators", end == begin);
HttpHeaders::const_iterator cend(headers->end()), cbegin(headers->begin());
ensure("Empty container has equal rbegin/rend const iterators", cend == cbegin);
ensure("Empty container has equal begin/end iterators", headers->end() == headers->begin());
{
static char line1[] = " AcCePT : image/yourfacehere";
static char line1v[] = "image/yourfacehere";
headers->appendNormal(line1, sizeof(line1) - 1);
static char line2[] = " next : \t\tlinejunk \t";
static char line2v[] = "linejunk \t";
headers->appendNormal(line2, sizeof(line2) - 1);
static char line3[] = "FancY-PANTs::plop:-neuf-=vleem=";
static char line3v[] = ":plop:-neuf-=vleem=";
headers->appendNormal(line3, sizeof(line3) - 1);
static char line4[] = "all-talk-no-walk:";
static char line4v[] = "";
headers->appendNormal(line4, sizeof(line4) - 1);
static char line5[] = ":all-talk-no-walk";
static char line5v[] = "all-talk-no-walk";
headers->appendNormal(line5, sizeof(line5) - 1);
static char line6[] = " :";
static char line6v[] = "";
headers->appendNormal(line6, sizeof(line6) - 1);
ensure("All entries accounted for", 6 == headers->size());
static char * values[] = {
line1v,
line2v,
line3v,
line4v,
line5v,
line6v
};
int i(0);
HttpHeaders::const_iterator cend(headers->end());
for (HttpHeaders::const_iterator it(headers->begin());
cend != it;
++it, ++i)
{
std::ostringstream str;
str << "Const Iterator value # " << i << " was " << values[i];
ensure(str.str(), (*it).second == values[i]);
}
// Rewind, do non-consts
i = 0;
HttpHeaders::iterator end(headers->end());
for (HttpHeaders::iterator it(headers->begin());
end != it;
++it, ++i)
{
std::ostringstream str;
str << "Const Iterator value # " << i << " was " << values[i];
ensure(str.str(), (*it).second == values[i]);
}
}
// release the implicit reference, causing the object to be released
headers.reset();
}
// Reverse iterators find everything as expected
template <> template <>
void HttpHeadersTestObjectType::test<6>()
{
set_test_name("HttpHeaders reverse iterator tests");
// create a new ref counted object with an implicit reference
HttpHeaders::ptr_t headers = HttpHeaders::ptr_t(new HttpHeaders());
HttpHeaders::reverse_iterator rend(headers->rend()), rbegin(headers->rbegin());
ensure("Empty container has equal rbegin/rend const iterators", rend == rbegin);
HttpHeaders::const_reverse_iterator crend(headers->rend()), crbegin(headers->rbegin());
ensure("Empty container has equal rbegin/rend const iterators", crend == crbegin);
{
static char line1[] = " AcCePT : image/yourfacehere";
static char line1v[] = "image/yourfacehere";
headers->appendNormal(line1, sizeof(line1) - 1);
static char line2[] = " next : \t\tlinejunk \t";
static char line2v[] = "linejunk \t";
headers->appendNormal(line2, sizeof(line2) - 1);
static char line3[] = "FancY-PANTs::plop:-neuf-=vleem=";
static char line3v[] = ":plop:-neuf-=vleem=";
headers->appendNormal(line3, sizeof(line3) - 1);
static char line4[] = "all-talk-no-walk:";
static char line4v[] = "";
headers->appendNormal(line4, sizeof(line4) - 1);
static char line5[] = ":all-talk-no-walk";
static char line5v[] = "all-talk-no-walk";
headers->appendNormal(line5, sizeof(line5) - 1);
static char line6[] = " :";
static char line6v[] = "";
headers->appendNormal(line6, sizeof(line6) - 1);
ensure("All entries accounted for", 6 == headers->size());
static char * values[] = {
line6v,
line5v,
line4v,
line3v,
line2v,
line1v
};
int i(0);
HttpHeaders::const_reverse_iterator cend(headers->rend());
for (HttpHeaders::const_reverse_iterator it(headers->rbegin());
cend != it;
++it, ++i)
{
std::ostringstream str;
str << "Const Iterator value # " << i << " was " << values[i];
ensure(str.str(), (*it).second == values[i]);
}
// Rewind, do non-consts
i = 0;
HttpHeaders::reverse_iterator end(headers->rend());
for (HttpHeaders::reverse_iterator it(headers->rbegin());
end != it;
++it, ++i)
{
std::ostringstream str;
str << "Iterator value # " << i << " was " << values[i];
ensure(str.str(), (*it).second == values[i]);
}
}
// release the implicit reference, causing the object to be released
headers.reset();
}
} // end namespace tut
#endif // TEST_LLCORE_HTTP_HEADERS_H_
@@ -0,0 +1,107 @@
/**
* @file test_httpoperation.hpp
* @brief unit tests for the LLCore::HttpOperation-derived classes
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef TEST_LLCORE_HTTP_OPERATION_H_
#define TEST_LLCORE_HTTP_OPERATION_H_
#include "_httpoperation.h"
#include "httphandler.h"
#include <iostream>
using namespace LLCoreInt;
namespace
{
class TestHandler : public LLCore::HttpHandler
{
public:
virtual void onCompleted(HttpHandle, HttpResponse *)
{
std::cout << "TestHandler::onCompleted() invoked" << std::endl;
}
};
} // end namespace anonymous
namespace tut
{
struct HttpOperationTestData
{
// the test objects inherit from this so the member functions and variables
// can be referenced directly inside of the test functions.
};
typedef test_group<HttpOperationTestData> HttpOperationTestGroupType;
typedef HttpOperationTestGroupType::object HttpOperationTestObjectType;
HttpOperationTestGroupType HttpOperationTestGroup("HttpOperation Tests");
template <> template <>
void HttpOperationTestObjectType::test<1>()
{
set_test_name("HttpOpNull construction");
// create a new ref counted object with an implicit reference
HttpOperation::ptr_t op (new HttpOpNull());
ensure(op.use_count() == 1);
// release the implicit reference, causing the object to be released
op.reset();
}
template <> template <>
void HttpOperationTestObjectType::test<2>()
{
set_test_name("HttpOpNull construction with handlers");
// Get some handlers
LLCore::HttpHandler::ptr_t h1 (new TestHandler());
// create a new ref counted object with an implicit reference
HttpOperation::ptr_t op (new HttpOpNull());
// Add the handlers
op->setReplyPath(LLCore::HttpOperation::HttpReplyQueuePtr_t(), h1);
// Check ref count
ensure(op.use_count() == 1);
// release the reference, releasing the operation but
// not the handlers.
op.reset();
// release the handlers
h1.reset();
}
}
#endif // TEST_LLCORE_HTTP_OPERATION_H_
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,157 @@
/**
* @file test_httprequestqueue.hpp
* @brief unit tests for the LLCore::HttpRequestQueue class
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef TEST_LLCORE_HTTP_REQUESTQUEUE_H_
#define TEST_LLCORE_HTTP_REQUESTQUEUE_H_
#include "_httprequestqueue.h"
#include <iostream>
#include "_httpoperation.h"
using namespace LLCoreInt;
namespace tut
{
struct HttpRequestqueueTestData
{
// the test objects inherit from this so the member functions and variables
// can be referenced directly inside of the test functions.
};
typedef test_group<HttpRequestqueueTestData> HttpRequestqueueTestGroupType;
typedef HttpRequestqueueTestGroupType::object HttpRequestqueueTestObjectType;
HttpRequestqueueTestGroupType HttpRequestqueueTestGroup("HttpRequestqueue Tests");
template <> template <>
void HttpRequestqueueTestObjectType::test<1>()
{
set_test_name("HttpRequestQueue construction");
// create a new ref counted object with an implicit reference
HttpRequestQueue::init();
ensure("One ref on construction of HttpRequestQueue", HttpRequestQueue::instanceOf()->getRefCount() == 1);
// release the implicit reference, causing the object to be released
HttpRequestQueue::term();
}
template <> template <>
void HttpRequestqueueTestObjectType::test<2>()
{
set_test_name("HttpRequestQueue refcount works");
// create a new ref counted object with an implicit reference
HttpRequestQueue::init();
HttpRequestQueue * rq = HttpRequestQueue::instanceOf();
rq->addRef();
// release the singleton, hold on to the object
HttpRequestQueue::term();
ensure("One ref after term() called", rq->getRefCount() == 1);
// Drop ref
rq->release();
}
template <> template <>
void HttpRequestqueueTestObjectType::test<3>()
{
set_test_name("HttpRequestQueue addOp/fetchOp work");
// create a new ref counted object with an implicit reference
HttpRequestQueue::init();
HttpRequestQueue * rq = HttpRequestQueue::instanceOf();
HttpOperation::ptr_t op(new HttpOpNull());
rq->addOp(op); // transfer my refcount
op = rq->fetchOp(true); // Potentially hangs the test on failure
ensure("One goes in, one comes out", static_cast<bool>(op));
op.reset();
op = rq->fetchOp(false);
ensure("Better not be two of them", !op);
// release the singleton, hold on to the object
HttpRequestQueue::term();
}
template <> template <>
void HttpRequestqueueTestObjectType::test<4>()
{
set_test_name("HttpRequestQueue addOp/fetchAll work");
// create a new ref counted object with an implicit reference
HttpRequestQueue::init();
HttpRequestQueue * rq = HttpRequestQueue::instanceOf();
HttpOperation::ptr_t op (new HttpOpNull());
rq->addOp(op); // transfer my refcount
op.reset(new HttpOpNull());
rq->addOp(op); // transfer my refcount
op.reset(new HttpOpNull());
rq->addOp(op); // transfer my refcount
{
HttpRequestQueue::OpContainer ops;
rq->fetchAll(true, ops); // Potentially hangs the test on failure
ensure("Three go in, three come out", 3 == ops.size());
op = rq->fetchOp(false);
ensure("Better not be any more of them", !op);
op.reset();
// release the singleton, hold on to the object
HttpRequestQueue::term();
// Release them
ops.clear();
// while (! ops.empty())
// {
// HttpOperation * op = ops.front();
// ops.erase(ops.begin());
// op->release();
// }
}
}
} // end namespace tut
#endif // TEST_LLCORE_HTTP_REQUESTQUEUE_H_
+300
View File
@@ -0,0 +1,300 @@
/**
* @file test_llrefcounted
* @brief unit tests for HttpStatus struct
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012-2013, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef TEST_HTTP_STATUS_H_
#define TEST_HTTP_STATUS_H_
#include "httpcommon.h"
#include <curl/curl.h>
#include <curl/multi.h>
using namespace LLCore;
namespace tut
{
struct HttpStatusTestData
{
HttpStatusTestData()
{}
};
typedef test_group<HttpStatusTestData> HttpStatusTestGroupType;
typedef HttpStatusTestGroupType::object HttpStatusTestObjectType;
HttpStatusTestGroupType HttpStatusTestGroup("HttpStatus Tests");
template <> template <>
void HttpStatusTestObjectType::test<1>()
{
set_test_name("HttpStatus construction");
// auto allocation fine for this
HttpStatus status;
status = HttpStatus(HttpStatus::EXT_CURL_EASY, 0);
ensure(bool(status));
ensure(false == !(status));
status = HttpStatus(HttpStatus::EXT_CURL_MULTI, 0);
ensure(bool(status));
ensure(false == !(status));
status = HttpStatus(HttpStatus::LLCORE, HE_SUCCESS);
ensure(bool(status));
ensure(false == !(status));
status = HttpStatus(HttpStatus::EXT_CURL_MULTI, -1);
ensure(false == bool(status));
ensure(!(status));
status = HttpStatus(HttpStatus::EXT_CURL_EASY, CURLE_BAD_DOWNLOAD_RESUME);
ensure(false == bool(status));
ensure(!(status));
}
// template <> template <>
// void HttpStatusTestObjectType::test<2>()
// {
// set_test_name("HttpStatus memory structure");
//
// // Require that an HttpStatus object can be trivially
// // returned as a function return value in registers.
// // One should fit in an int on all platforms.
//
// //ensure(sizeof(HttpStatus) <= sizeof(int));
// }
template <> template <>
void HttpStatusTestObjectType::test<2>()
{
set_test_name("HttpStatus valid status string conversion");
HttpStatus status = HttpStatus(HttpStatus::EXT_CURL_EASY, 0);
std::string msg = status.toString();
// std::cout << "Result: " << msg << std::endl;
ensure(msg.empty());
status = HttpStatus(HttpStatus::EXT_CURL_EASY, CURLE_BAD_FUNCTION_ARGUMENT);
msg = status.toString();
// std::cout << "Result: " << msg << std::endl;
ensure(! msg.empty());
status = HttpStatus(HttpStatus::EXT_CURL_MULTI, CURLM_OUT_OF_MEMORY);
msg = status.toString();
// std::cout << "Result: " << msg << std::endl;
ensure(! msg.empty());
status = HttpStatus(HttpStatus::LLCORE, HE_SHUTTING_DOWN);
msg = status.toString();
// std::cout << "Result: " << msg << std::endl;
ensure(! msg.empty());
}
template <> template <>
void HttpStatusTestObjectType::test<3>()
{
set_test_name("HttpStatus invalid status string conversion");
HttpStatus status = HttpStatus(HttpStatus::EXT_CURL_EASY, 32726);
std::string msg = status.toString();
// std::cout << "Result: " << msg << std::endl;
ensure(! msg.empty());
status = HttpStatus(HttpStatus::EXT_CURL_MULTI, -470);
msg = status.toString();
// std::cout << "Result: " << msg << std::endl;
ensure(! msg.empty());
status = HttpStatus(HttpStatus::LLCORE, 923);
msg = status.toString();
// std::cout << "Result: " << msg << std::endl;
ensure(! msg.empty());
}
template <> template <>
void HttpStatusTestObjectType::test<4>()
{
set_test_name("HttpStatus equality/inequality testing");
// Make certain equality/inequality tests do not pass
// through the bool conversion. Distinct successful
// and error statuses should compare unequal.
HttpStatus status1(HttpStatus::LLCORE, HE_SUCCESS);
HttpStatus status2(HttpStatus::EXT_CURL_EASY, HE_SUCCESS);
ensure(status1 != status2);
status1 = HttpStatus(HttpStatus::LLCORE, HE_REPLY_ERROR);
status1 = HttpStatus(HttpStatus::LLCORE, HE_SHUTTING_DOWN);
ensure(status1 != status2);
}
template <> template <>
void HttpStatusTestObjectType::test<5>()
{
set_test_name("HttpStatus basic HTTP status encoding");
HttpStatus status;
status = HttpStatus(200, HE_SUCCESS);
std::string msg = status.toString();
ensure(msg.empty());
ensure(bool(status));
// Normally a success but application says error
status = HttpStatus(200, HE_REPLY_ERROR);
msg = status.toString();
ensure(! msg.empty());
ensure(! bool(status));
ensure(status.toULong() > 1UL); // Biggish number, not a bool-to-ulong
// Same statuses with distinct success/fail are distinct
status = HttpStatus(200, HE_SUCCESS);
HttpStatus status2(200, HE_REPLY_ERROR);
ensure(status != status2);
// Normally an error but application says okay
status = HttpStatus(406, HE_SUCCESS);
msg = status.toString();
ensure(msg.empty());
ensure(bool(status));
// Different statuses but both successful are distinct
status = HttpStatus(200, HE_SUCCESS);
status2 = HttpStatus(201, HE_SUCCESS);
ensure(status != status2);
// Different statuses but both failed are distinct
status = HttpStatus(200, HE_REPLY_ERROR);
status2 = HttpStatus(201, HE_REPLY_ERROR);
ensure(status != status2);
}
template <> template <>
void HttpStatusTestObjectType::test<6>()
{
set_test_name("HttpStatus HTTP status text strings");
HttpStatus status(100, HE_REPLY_ERROR);
std::string msg(status.toString());
ensure(! msg.empty()); // Should be something
ensure(msg == "Continue");
status = HttpStatus(200, HE_SUCCESS);
msg = status.toString();
ensure(msg.empty()); // Success is empty
status = HttpStatus(199, HE_REPLY_ERROR);
msg = status.toString();
ensure(msg == "Unknown error");
status = HttpStatus(505, HE_REPLY_ERROR);
msg = status.toString();
ensure(msg == "HTTP Version not supported");
status = HttpStatus(506, HE_REPLY_ERROR);
msg = status.toString();
ensure(msg == "Unknown error");
status = HttpStatus(999, HE_REPLY_ERROR);
msg = status.toString();
ensure(msg == "Unknown error");
}
template <> template <>
void HttpStatusTestObjectType::test<7>()
{
set_test_name("HttpStatus toHex() nominal function");
HttpStatus status(404);
std::string msg = status.toHex();
// std::cout << "Result: " << msg << std::endl;
ensure_equals(msg, "01940001");
}
template <> template <>
void HttpStatusTestObjectType::test<8>()
{
set_test_name("HttpStatus toTerseString() nominal function");
HttpStatus status(404);
std::string msg = status.toTerseString();
// std::cout << "Result: " << msg << std::endl;
ensure("Normal HTTP 404", msg == "Http_404");
status = HttpStatus(200);
msg = status.toTerseString();
// std::cout << "Result: " << msg << std::endl;
ensure("Normal HTTP 200", msg == "Http_200");
status = HttpStatus(200, HE_REPLY_ERROR);
msg = status.toTerseString();
// std::cout << "Result: " << msg << std::endl;
ensure("Unsuccessful HTTP 200", msg == "Http_200"); // No distinction for error
status = HttpStatus(HttpStatus::EXT_CURL_EASY, CURLE_COULDNT_CONNECT);
msg = status.toTerseString();
// std::cout << "Result: " << msg << std::endl;
ensure("Easy couldn't connect error", msg == "Easy_7");
status = HttpStatus(HttpStatus::EXT_CURL_MULTI, CURLM_OUT_OF_MEMORY);
msg = status.toTerseString();
// std::cout << "Result: " << msg << std::endl;
ensure("Multi out-of-memory error", msg == "Multi_3");
status = HttpStatus(HttpStatus::LLCORE, HE_OPT_NOT_SET);
msg = status.toTerseString();
// std::cout << "Result: " << msg << std::endl;
ensure("Core option not set error", msg == "Core_7");
status = HttpStatus(22000, 1);
msg = status.toTerseString();
// std::cout << "Result: " << msg << std::endl;
ensure("Undecodable error", msg == "Unknown_1");
status = HttpStatus(22000, -1);
msg = status.toTerseString();
// std::cout << "Result: " << msg << std::endl;
ensure("Undecodable error 65535", msg == "Unknown_65535");
}
} // end namespace tut
#endif // TEST_HTTP_STATUS_H
+318
View File
@@ -0,0 +1,318 @@
#!/usr/bin/env python3
"""\
@file test_llsdmessage_peer.py
@author Nat Goodspeed
@date 2008-10-09
@brief This script asynchronously runs the executable (with args) specified on
the command line, returning its result code. While that executable is
running, we provide dummy local services for use by C++ tests.
$LicenseInfo:firstyear=2008&license=viewerlgpl$
Second Life Viewer Source Code
Copyright (C) 2012-2013, Linden Research, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation;
version 2.1 of the License only.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
$/LicenseInfo$
"""
import os
import sys
import time
import select
import getopt
from io import StringIO
from http.server import HTTPServer, BaseHTTPRequestHandler
import llsd
# we're in llcorehttp/tests ; testrunner.py is found in llmessage/tests
sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir,
"llmessage", "tests"))
from testrunner import freeport, run, debug, VERBOSE
class TestHTTPRequestHandler(BaseHTTPRequestHandler):
"""This subclass of BaseHTTPRequestHandler is to receive and echo
LLSD-flavored messages sent by the C++ LLHTTPClient.
Target URLs are fairly free-form and are assembled by
concatinating fragments. Currently defined fragments
are:
- '/reflect/' Request headers are bounced back to caller
after prefixing with 'X-Reflect-'
- '/fail/' Body of request can contain LLSD with
'reason' string and 'status' integer
which will become response header.
- '/bug2295/' 206 response, no data in body:
-- '/bug2295/0/' "Content-Range: bytes 0-75/2983"
-- '/bug2295/1/' "Content-Range: bytes 0-75/*"
-- '/bug2295/2/' "Content-Range: bytes 0-75/2983",
"Content-Length: 0"
-- '/bug2295/00000018/0/' Generates PARTIAL_FILE (18) error in libcurl.
"Content-Range: bytes 0-75/2983",
"Content-Length: 76"
-- '/bug2295/inv_cont_range/0/' Generates HE_INVALID_CONTENT_RANGE error in llcorehttp.
- '/503/' Generate 503 responses with various kinds
of 'retry-after' headers
-- '/503/0/' "Retry-After: 2"
-- '/503/1/' "Retry-After: Thu, 31 Dec 2043 23:59:59 GMT"
-- '/503/2/' "Retry-After: Fri, 31 Dec 1999 23:59:59 GMT"
-- '/503/3/' "Retry-After: "
-- '/503/4/' "Retry-After: (*#*(@*(@(")"
-- '/503/5/' "Retry-After: aklsjflajfaklsfaklfasfklasdfklasdgahsdhgasdiogaioshdgo"
-- '/503/6/' "Retry-After: 1 2 3 4 5 6 7 8 9 10"
Some combinations make no sense, there's no effort to protect
you from that.
"""
ignore_exceptions = (Exception,)
def read(self):
# The following logic is adapted from the library module
# SimpleXMLRPCServer.py.
# Get arguments by reading body of request.
# We read this in chunks to avoid straining
# socket.read(); around the 10 or 15Mb mark, some platforms
# begin to have problems (bug #792570).
try:
size_remaining = int(self.headers["content-length"])
except (KeyError, ValueError):
return ""
max_chunk_size = 10*1024*1024
L = bytes()
while size_remaining:
chunk_size = min(size_remaining, max_chunk_size)
chunk = self.rfile.read(chunk_size)
L += chunk
size_remaining -= len(chunk)
return L.decode("utf-8")
# end of swiped read() logic
def read_xml(self):
# This approach reads the entire POST data into memory first
return llsd.parse(self.read())
## # This approach attempts to stream in the LLSD XML from self.rfile,
## # assuming that the underlying XML parser reads its input file
## # incrementally. Unfortunately I haven't been able to make it work.
## tree = xml_parse(self.rfile)
## debug("Finished raw parse")
## debug("parsed XML tree %s", tree)
## debug("parsed root node %s", tree.getroot())
## debug("root node tag %s", tree.getroot().tag)
## return llsd.to_python(tree.getroot())
def do_HEAD(self):
self.do_GET(withdata=False)
def do_GET(self, withdata=True):
# Of course, don't attempt to read data.
try:
self.answer(dict(reply="success", status=200,
reason="Your GET operation worked"))
except self.ignore_exceptions as e:
print("Exception during GET (ignoring): %s" % str(e), file=sys.stderr)
def do_POST(self):
# Read the provided POST data.
# self.answer(self.read())
try:
self.answer(dict(reply="success", status=200,
reason=self.read()))
except self.ignore_exceptions as e:
print("Exception during POST (ignoring): %s" % str(e), file=sys.stderr)
def do_PUT(self):
# Read the provided PUT data.
# self.answer(self.read())
try:
self.answer(dict(reply="success", status=200,
reason=self.read()))
except self.ignore_exceptions as e:
print("Exception during PUT (ignoring): %s" % str(e), file=sys.stderr)
def answer(self, data, withdata=True):
debug("%s.answer(%s): self.path = %r", self.__class__.__name__, data, self.path)
if "/sleep/" in self.path:
time.sleep(30)
if "/503/" in self.path:
# Tests for various kinds of 'Retry-After' header parsing
body = None
if "/503/0/" in self.path:
self.send_response(503)
self.send_header("retry-after", "2")
elif "/503/1/" in self.path:
self.send_response(503)
self.send_header("retry-after", "Thu, 31 Dec 2043 23:59:59 GMT")
elif "/503/2/" in self.path:
self.send_response(503)
self.send_header("retry-after", "Fri, 31 Dec 1999 23:59:59 GMT")
elif "/503/3/" in self.path:
self.send_response(503)
self.send_header("retry-after", "")
elif "/503/4/" in self.path:
self.send_response(503)
self.send_header("retry-after", "(*#*(@*(@(")
elif "/503/5/" in self.path:
self.send_response(503)
self.send_header("retry-after", "aklsjflajfaklsfaklfasfklasdfklasdgahsdhgasdiogaioshdgo")
elif "/503/6/" in self.path:
self.send_response(503)
self.send_header("retry-after", "1 2 3 4 5 6 7 8 9 10")
else:
# Unknown request
self.send_response(400)
body = "Unknown /503/ path in server"
if "/reflect/" in self.path:
self.reflect_headers()
self.send_header("Content-type", "text/plain")
self.end_headers()
if body:
self.wfile.write(body)
elif "/bug2295/" in self.path:
# Test for https://jira.secondlife.com/browse/BUG-2295
#
# Client can receive a header indicating data should
# appear in the body without actually getting the body.
# Library needs to defend against this case.
#
body = None
if "/bug2295/0/" in self.path:
self.send_response(206)
self.send_header("Content-Range", "bytes 0-75/2983")
elif "/bug2295/1/" in self.path:
self.send_response(206)
self.send_header("Content-Range", "bytes 0-75/*")
elif "/bug2295/2/" in self.path:
self.send_response(206)
self.send_header("Content-Range", "bytes 0-75/2983")
self.send_header("Content-Length", "0")
elif "/bug2295/00000012/0/" in self.path:
self.send_response(206)
self.send_header("Content-Range", "bytes 0-75/2983")
self.send_header("Content-Length", "76")
elif "/bug2295/inv_cont_range/0/" in self.path:
self.send_response(206)
self.send_header("Content-Range", "bytes 0-75/2983")
body = "Some text, but not enough."
else:
# Unknown request
self.send_response(400)
if "/reflect/" in self.path:
self.reflect_headers()
self.send_header("Content-type", "text/plain")
self.end_headers()
if body:
self.wfile.write(body.encode("utf-8"))
elif "fail" not in self.path:
data = data.copy() # we're going to modify
# Ensure there's a "reply" key in data, even if there wasn't before
data["reply"] = data.get("reply", llsd.LLSD("success"))
response = llsd.format_xml(data)
debug("success: %s", response)
self.send_response(200)
if "/reflect/" in self.path:
self.reflect_headers()
self.send_header("Content-type", "application/llsd+xml")
self.send_header("Content-Length", str(len(response)))
self.send_header("X-LL-Special", "Mememememe");
self.end_headers()
if withdata:
self.wfile.write(response)
else: # fail requested
status = data.get("status", 500)
# self.responses maps an int status to a (short, long) pair of
# strings. We want the longer string. That's why we pass a string
# pair to get(): the [1] will select the second string, whether it
# came from self.responses or from our default pair.
reason = data.get("reason",
self.responses.get(status,
("fail requested",
"Your request specified failure status %s "
"without providing a reason" % status))[1])
debug("fail requested: %s: %r", status, reason)
self.send_error(status, reason)
if "/reflect/" in self.path:
self.reflect_headers()
self.end_headers()
def reflect_headers(self):
for (name, val) in self.headers.items():
# print("Header: %s %s" % (name, val), file=sys.stderr)
self.send_header("X-Reflect-" + name, val)
if not VERBOSE:
# When VERBOSE is set, skip both these overrides because they exist to
# suppress output.
def log_request(self, code, size=None):
# For present purposes, we don't want the request splattered onto
# stderr, as it would upset devs watching the test run
pass
def log_error(self, format, *args):
# Suppress error output as well
pass
class Server(HTTPServer):
# This pernicious flag is on by default in HTTPServer. But proper
# operation of freeport() absolutely depends on it being off.
allow_reuse_address = False
# Override of BaseServer.handle_error(). Not too interested
# in errors and the default handler emits a scary traceback
# to stderr which annoys some. Disable this override to get
# default behavior which *shouldn't* cause the program to return
# a failure status.
def handle_error(self, request, client_address):
print('-'*40)
print('Ignoring exception during processing of request from %' % (client_address))
print('-'*40)
if __name__ == "__main__":
do_valgrind = False
path_search = False
options, args = getopt.getopt(sys.argv[1:], "V", ["valgrind"])
for option, value in options:
if option == "-V" or option == "--valgrind":
do_valgrind = True
# function to make a server with specified port
make_server = lambda port: Server(('127.0.0.1', port), TestHTTPRequestHandler)
if not sys.platform.startswith("win"):
# Instantiate a Server(TestHTTPRequestHandler) on a port chosen by the
# runtime.
httpd = make_server(0)
else:
# "Then there's Windows"
# Instantiate a Server(TestHTTPRequestHandler) on the first free port
# in the specified port range.
httpd, port = freeport(range(8000, 8020), make_server)
# Pass the selected port number to the subject test program via the
# environment. We don't want to impose requirements on the test program's
# command-line parsing -- and anyway, for C++ integration tests, that's
# performed in TUT code rather than our own.
os.environ["LL_TEST_PORT"] = str(httpd.server_port)
debug("$LL_TEST_PORT = %s", httpd.server_port)
if do_valgrind:
args = ["valgrind", "--log-file=./valgrind.log"] + args
path_search = True
sys.exit(run(server_inst=httpd, use_path=path_search, *args))
+126
View File
@@ -0,0 +1,126 @@
/**
* @file test_refcounted.hpp
* @brief unit tests for the LLCoreInt::RefCounted class
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef TEST_LLCOREINT_REF_COUNTED_H_
#define TEST_LLCOREINT_REF_COUNTED_H_
#include "_refcounted.h"
// disable all of this because it's hanging win64 builds?
#if ! (LL_WINDOWS && ADDRESS_SIZE == 64)
using namespace LLCoreInt;
namespace tut
{
struct RefCountedTestData
{
// the test objects inherit from this so the member functions and variables
// can be referenced directly inside of the test functions.
};
typedef test_group<RefCountedTestData> RefCountedTestGroupType;
typedef RefCountedTestGroupType::object RefCountedTestObjectType;
RefCountedTestGroupType RefCountedTestGroup("RefCounted Tests");
template <> template <>
void RefCountedTestObjectType::test<1>()
{
set_test_name("RefCounted construction with implicit count");
// create a new ref counted object with an implicit reference
RefCounted * rc = new RefCounted(true);
ensure(rc->getRefCount() == 1);
// release the implicit reference, causing the object to be released
rc->release();
}
template <> template <>
void RefCountedTestObjectType::test<2>()
{
set_test_name("RefCounted construction without implicit count");
// create a new ref counted object with an implicit reference
RefCounted * rc = new RefCounted(false);
ensure(rc->getRefCount() == 0);
// add a reference
rc->addRef();
ensure(rc->getRefCount() == 1);
// release the implicit reference, causing the object to be released
rc->release();
}
template <> template <>
void RefCountedTestObjectType::test<3>()
{
set_test_name("RefCounted addRef and release");
RefCounted * rc = new RefCounted(false);
for (int i = 0; i < 1024; ++i)
{
rc->addRef();
}
ensure(rc->getRefCount() == 1024);
for (int i = 0; i < 1024; ++i)
{
rc->release();
}
}
template <> template <>
void RefCountedTestObjectType::test<4>()
{
set_test_name("RefCounted isLastRef check");
RefCounted * rc = new RefCounted(true);
// with only one reference, isLastRef should be true
ensure(rc->isLastRef());
// release it to clean up memory
rc->release();
}
template <> template <>
void RefCountedTestObjectType::test<5>()
{
set_test_name("RefCounted noRef check");
RefCounted * rc = new RefCounted(false);
// set the noRef
rc->noRef();
// with only one reference, isLastRef should be true
ensure(rc->getRefCount() == RefCounted::NOT_REF_COUNTED);
}
}
#endif // disabling on Win64
#endif // TEST_LLCOREINT_REF_COUNTED_H_