Automated merge with ssh://bitbucket.org/andreykproductengine/drtvwr-493
commit
a5f58663c0
|
|
@ -491,9 +491,6 @@ typename LLSingleton<T>::SingletonData LLSingleton<T>::sData;
|
|||
* * However, distinct initParamSingleton() calls can be used to engage
|
||||
* different constructors, as long as only one such call is executed at
|
||||
* runtime.
|
||||
* * Circularity is not permitted. No LLSingleton referenced by an
|
||||
* LLParamSingleton's constructor or initSingleton() method may call this
|
||||
* LLParamSingleton's instance() or getInstance() methods.
|
||||
* * Unlike LLSingleton, an LLParamSingleton cannot be "revived" by an
|
||||
* instance() or getInstance() call after deleteSingleton().
|
||||
*
|
||||
|
|
@ -508,7 +505,6 @@ private:
|
|||
|
||||
public:
|
||||
using super::deleteSingleton;
|
||||
using super::instance;
|
||||
using super::instanceExists;
|
||||
using super::wasDeleted;
|
||||
|
||||
|
|
@ -519,7 +515,7 @@ public:
|
|||
// In case racing threads both call initParamSingleton() at the same
|
||||
// time, serialize them. One should initialize; the other should see
|
||||
// mInitState already set.
|
||||
std::unique_lock<std::mutex> lk(mMutex);
|
||||
std::unique_lock<decltype(mMutex)> lk(mMutex);
|
||||
// For organizational purposes this function shouldn't be called twice
|
||||
if (super::sData.mInitState != super::UNINITIALIZED)
|
||||
{
|
||||
|
|
@ -539,7 +535,7 @@ public:
|
|||
{
|
||||
// In case racing threads call getInstance() at the same moment as
|
||||
// initParamSingleton(), serialize the calls.
|
||||
std::unique_lock<std::mutex> lk(mMutex);
|
||||
std::unique_lock<decltype(mMutex)> lk(mMutex);
|
||||
|
||||
switch (super::sData.mInitState)
|
||||
{
|
||||
|
|
@ -551,15 +547,10 @@ public:
|
|||
case super::CONSTRUCTING:
|
||||
super::logerrs("Tried to access param singleton ",
|
||||
super::demangle(typeid(DERIVED_TYPE).name()).c_str(),
|
||||
" from singleton constructor!");
|
||||
" from singleton constructor!");
|
||||
break;
|
||||
|
||||
case super::INITIALIZING:
|
||||
super::logerrs("Tried to access param singleton ",
|
||||
super::demangle(typeid(DERIVED_TYPE).name()).c_str(),
|
||||
" from initSingleton() method!");
|
||||
break;
|
||||
|
||||
case super::INITIALIZED:
|
||||
return super::sData.mInstance;
|
||||
|
||||
|
|
@ -574,12 +565,23 @@ public:
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// instance() is replicated here so it calls
|
||||
// LLParamSingleton::getInstance() rather than LLSingleton::getInstance()
|
||||
// -- avoid making getInstance() virtual
|
||||
static DERIVED_TYPE& instance()
|
||||
{
|
||||
return *getInstance();
|
||||
}
|
||||
|
||||
private:
|
||||
static std::mutex mMutex;
|
||||
// Use a recursive_mutex in case of constructor circularity. With a
|
||||
// non-recursive mutex, that would result in deadlock rather than the
|
||||
// logerrs() call coded above.
|
||||
static std::recursive_mutex mMutex;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
typename std::mutex LLParamSingleton<T>::mMutex;
|
||||
typename std::recursive_mutex LLParamSingleton<T>::mMutex;
|
||||
|
||||
/**
|
||||
* Initialization locked singleton, only derived class can decide when to initialize.
|
||||
|
|
|
|||
|
|
@ -506,16 +506,10 @@ namespace tut
|
|||
replyName = waiter.getName0();
|
||||
errorName = waiter.getName1();
|
||||
WrapLLErrs capture;
|
||||
try
|
||||
{
|
||||
result = waiter.suspendWithLog();
|
||||
debug("no exception");
|
||||
}
|
||||
catch (const WrapLLErrs::FatalException& e)
|
||||
{
|
||||
debug(STRINGIZE("exception " << e.what()));
|
||||
threw = e.what();
|
||||
}
|
||||
threw = capture.catch_llerrs([&waiter, &debug](){
|
||||
result = waiter.suspendWithLog();
|
||||
debug("no exception");
|
||||
});
|
||||
}
|
||||
END
|
||||
}
|
||||
|
|
@ -762,18 +756,13 @@ namespace tut
|
|||
{
|
||||
LLCoroEventPumps waiter;
|
||||
WrapLLErrs capture;
|
||||
try
|
||||
{
|
||||
result = waiter.postAndSuspendWithLog(
|
||||
LLSDMap("value", 31)("fail", LLSD()),
|
||||
immediateAPI.getPump(), "reply", "error");
|
||||
debug("no exception");
|
||||
}
|
||||
catch (const WrapLLErrs::FatalException& e)
|
||||
{
|
||||
debug(STRINGIZE("exception " << e.what()));
|
||||
threw = e.what();
|
||||
}
|
||||
threw = capture.catch_llerrs(
|
||||
[&waiter, &debug](){
|
||||
result = waiter.postAndSuspendWithLog(
|
||||
LLSDMap("value", 31)("fail", LLSD()),
|
||||
immediateAPI.getPump(), "reply", "error");
|
||||
debug("no exception");
|
||||
});
|
||||
}
|
||||
END
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include "llsdutil.h"
|
||||
#include "stringize.h"
|
||||
#include "tests/wrapllerrs.h"
|
||||
#include "../test/catch_and_store_what_in.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
|
@ -630,16 +631,9 @@ namespace tut
|
|||
|
||||
void call_exc(const std::string& func, const LLSD& args, const std::string& exc_frag)
|
||||
{
|
||||
std::string threw;
|
||||
try
|
||||
{
|
||||
work(func, args);
|
||||
}
|
||||
catch (const std::runtime_error& e)
|
||||
{
|
||||
cout << "*** " << e.what() << '\n';
|
||||
threw = e.what();
|
||||
}
|
||||
std::string threw = catch_what<std::runtime_error>([this, &func, &args](){
|
||||
work(func, args);
|
||||
});
|
||||
ensure_has(threw, exc_frag);
|
||||
}
|
||||
|
||||
|
|
@ -717,15 +711,9 @@ namespace tut
|
|||
LLSD attempts(LLSDArray(17)(LLSDMap("pi", 3.14)("two", 2)));
|
||||
foreach(LLSD ae, inArray(attempts))
|
||||
{
|
||||
std::string threw;
|
||||
try
|
||||
{
|
||||
work.add("freena_err", "freena", freena, ae);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
threw = e.what();
|
||||
}
|
||||
std::string threw = catch_what<std::exception>([this, &ae](){
|
||||
work.add("freena_err", "freena", freena, ae);
|
||||
});
|
||||
ensure_has(threw, "must be an array");
|
||||
}
|
||||
}
|
||||
|
|
@ -734,15 +722,9 @@ namespace tut
|
|||
void object::test<2>()
|
||||
{
|
||||
set_test_name("map-style registration with badly-formed defaults");
|
||||
std::string threw;
|
||||
try
|
||||
{
|
||||
work.add("freena_err", "freena", freena, LLSDArray("a")("b"), 17);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
threw = e.what();
|
||||
}
|
||||
std::string threw = catch_what<std::exception>([this](){
|
||||
work.add("freena_err", "freena", freena, LLSDArray("a")("b"), 17);
|
||||
});
|
||||
ensure_has(threw, "must be a map or an array");
|
||||
}
|
||||
|
||||
|
|
@ -750,17 +732,11 @@ namespace tut
|
|||
void object::test<3>()
|
||||
{
|
||||
set_test_name("map-style registration with too many array defaults");
|
||||
std::string threw;
|
||||
try
|
||||
{
|
||||
work.add("freena_err", "freena", freena,
|
||||
LLSDArray("a")("b"),
|
||||
LLSDArray(17)(0.9)("gack"));
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
threw = e.what();
|
||||
}
|
||||
std::string threw = catch_what<std::exception>([this](){
|
||||
work.add("freena_err", "freena", freena,
|
||||
LLSDArray("a")("b"),
|
||||
LLSDArray(17)(0.9)("gack"));
|
||||
});
|
||||
ensure_has(threw, "shorter than");
|
||||
}
|
||||
|
||||
|
|
@ -768,17 +744,11 @@ namespace tut
|
|||
void object::test<4>()
|
||||
{
|
||||
set_test_name("map-style registration with too many map defaults");
|
||||
std::string threw;
|
||||
try
|
||||
{
|
||||
work.add("freena_err", "freena", freena,
|
||||
LLSDArray("a")("b"),
|
||||
LLSDMap("b", 17)("foo", 3.14)("bar", "sinister"));
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
threw = e.what();
|
||||
}
|
||||
std::string threw = catch_what<std::exception>([this](){
|
||||
work.add("freena_err", "freena", freena,
|
||||
LLSDArray("a")("b"),
|
||||
LLSDMap("b", 17)("foo", 3.14)("bar", "sinister"));
|
||||
});
|
||||
ensure_has(threw, "nonexistent params");
|
||||
ensure_has(threw, "foo");
|
||||
ensure_has(threw, "bar");
|
||||
|
|
@ -1039,16 +1009,9 @@ namespace tut
|
|||
// We don't have a comparable helper function for the one-arg
|
||||
// operator() method, and it's not worth building one just for this
|
||||
// case. Write it out.
|
||||
std::string threw;
|
||||
try
|
||||
{
|
||||
work(LLSDMap("op", "freek"));
|
||||
}
|
||||
catch (const std::runtime_error& e)
|
||||
{
|
||||
cout << "*** " << e.what() << "\n";
|
||||
threw = e.what();
|
||||
}
|
||||
std::string threw = catch_what<std::runtime_error>([this](){
|
||||
work(LLSDMap("op", "freek"));
|
||||
});
|
||||
ensure_has(threw, "bad");
|
||||
ensure_has(threw, "op");
|
||||
ensure_has(threw, "freek");
|
||||
|
|
|
|||
|
|
@ -350,15 +350,9 @@ namespace tut
|
|||
// Now let the timer expire.
|
||||
filter.forceTimeout();
|
||||
// Notice the timeout.
|
||||
std::string threw;
|
||||
try
|
||||
{
|
||||
mainloop.post(17);
|
||||
}
|
||||
catch (const WrapLLErrs::FatalException& e)
|
||||
{
|
||||
threw = e.what();
|
||||
}
|
||||
std::string threw = capture.catch_llerrs([this](){
|
||||
mainloop.post(17);
|
||||
});
|
||||
ensure_contains("errorAfter() timeout exception", threw, "timeout");
|
||||
// Timing out cancels the timer. Verify that.
|
||||
listener0.reset(0);
|
||||
|
|
|
|||
|
|
@ -198,14 +198,9 @@ namespace tut
|
|||
{
|
||||
WrapLLErrs wrapper;
|
||||
Keyed::instance_iter i(Keyed::beginInstances());
|
||||
try
|
||||
{
|
||||
delete keyed;
|
||||
}
|
||||
catch (const WrapLLErrs::FatalException& e)
|
||||
{
|
||||
what = e.what();
|
||||
}
|
||||
what = wrapper.catch_llerrs([&keyed](){
|
||||
delete keyed;
|
||||
});
|
||||
}
|
||||
ensure(! what.empty());
|
||||
}
|
||||
|
|
@ -219,14 +214,9 @@ namespace tut
|
|||
{
|
||||
WrapLLErrs wrapper;
|
||||
Keyed::key_iter i(Keyed::beginKeys());
|
||||
try
|
||||
{
|
||||
delete keyed;
|
||||
}
|
||||
catch (const WrapLLErrs::FatalException& e)
|
||||
{
|
||||
what = e.what();
|
||||
}
|
||||
what = wrapper.catch_llerrs([&keyed](){
|
||||
delete keyed;
|
||||
});
|
||||
}
|
||||
ensure(! what.empty());
|
||||
}
|
||||
|
|
@ -240,14 +230,9 @@ namespace tut
|
|||
{
|
||||
WrapLLErrs wrapper;
|
||||
Unkeyed::instance_iter i(Unkeyed::beginInstances());
|
||||
try
|
||||
{
|
||||
delete unkeyed;
|
||||
}
|
||||
catch (const WrapLLErrs::FatalException& e)
|
||||
{
|
||||
what = e.what();
|
||||
}
|
||||
what = wrapper.catch_llerrs([&unkeyed](){
|
||||
delete unkeyed;
|
||||
});
|
||||
}
|
||||
ensure(! what.empty());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include <boost/lambda/bind.hpp>
|
||||
// other Linden headers
|
||||
#include "../test/lltut.h"
|
||||
#include "../test/catch_and_store_what_in.h"
|
||||
|
||||
namespace bll = boost::lambda;
|
||||
|
||||
|
|
@ -200,15 +201,9 @@ namespace tut
|
|||
void lllazy_object::test<2>()
|
||||
{
|
||||
TestNeedsTesting tnt;
|
||||
std::string threw;
|
||||
try
|
||||
{
|
||||
tnt.toolate();
|
||||
}
|
||||
catch (const LLLazyCommon::InstanceChange& e)
|
||||
{
|
||||
threw = e.what();
|
||||
}
|
||||
std::string threw = catch_what<LLLazyCommon::InstanceChange>([&tnt](){
|
||||
tnt.toolate();
|
||||
});
|
||||
ensure_contains("InstanceChange exception", threw, "replace LLLazy instance");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
#include "../test/lltut.h"
|
||||
#include "../test/namedtempfile.h"
|
||||
#include "../test/catch_and_store_what_in.h"
|
||||
#include "wrapllerrs.h"
|
||||
#include "wrapllerrs.h" // CaptureLog
|
||||
#include "llevents.h"
|
||||
#include "llprocess.h"
|
||||
#include "llstring.h"
|
||||
|
|
@ -290,12 +290,9 @@ namespace tut
|
|||
void object::test<6>()
|
||||
{
|
||||
set_test_name("empty plugin vector");
|
||||
std::string threw;
|
||||
try
|
||||
{
|
||||
LLLeap::create("empty", StringVec());
|
||||
}
|
||||
CATCH_AND_STORE_WHAT_IN(threw, LLLeap::Error)
|
||||
std::string threw = catch_what<LLLeap::Error>([](){
|
||||
LLLeap::create("empty", StringVec());
|
||||
});
|
||||
ensure_contains("LLLeap::Error", threw, "no plugin");
|
||||
// try the suppress-exception variant
|
||||
ensure("bad launch returned non-NULL", ! LLLeap::create("empty", StringVec(), false));
|
||||
|
|
@ -308,12 +305,9 @@ namespace tut
|
|||
// Synthesize bogus executable name
|
||||
std::string BADPYTHON(PYTHON.substr(0, PYTHON.length()-1) + "x");
|
||||
CaptureLog log;
|
||||
std::string threw;
|
||||
try
|
||||
{
|
||||
LLLeap::create("bad exe", BADPYTHON);
|
||||
}
|
||||
CATCH_AND_STORE_WHAT_IN(threw, LLLeap::Error)
|
||||
std::string threw = catch_what<LLLeap::Error>([&BADPYTHON](){
|
||||
LLLeap::create("bad exe", BADPYTHON);
|
||||
});
|
||||
ensure_contains("LLLeap::create() didn't throw", threw, "failed");
|
||||
log.messageWith("failed");
|
||||
log.messageWith(BADPYTHON);
|
||||
|
|
|
|||
|
|
@ -25,8 +25,6 @@
|
|||
#include <boost/function.hpp>
|
||||
#include <boost/algorithm/string/find_iterator.hpp>
|
||||
#include <boost/algorithm/string/finder.hpp>
|
||||
//#include <boost/lambda/lambda.hpp>
|
||||
//#include <boost/lambda/bind.hpp>
|
||||
// other Linden headers
|
||||
#include "../test/lltut.h"
|
||||
#include "../test/namedtempfile.h"
|
||||
|
|
@ -35,7 +33,7 @@
|
|||
#include "llsdutil.h"
|
||||
#include "llevents.h"
|
||||
#include "llstring.h"
|
||||
#include "wrapllerrs.h"
|
||||
#include "wrapllerrs.h" // CaptureLog
|
||||
|
||||
#if defined(LL_WINDOWS)
|
||||
#define sleep(secs) _sleep((secs) * 1000)
|
||||
|
|
@ -45,8 +43,7 @@
|
|||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
//namespace lambda = boost::lambda;
|
||||
std::string apr_strerror_helper(apr_status_t rv)
|
||||
std::string apr_strerror_helper(apr_status_t rv)
|
||||
{
|
||||
char errbuf[256];
|
||||
apr_strerror(rv, errbuf, sizeof(errbuf));
|
||||
|
|
@ -960,12 +957,9 @@ namespace tut
|
|||
#define CATCH_IN(THREW, EXCEPTION, CODE) \
|
||||
do \
|
||||
{ \
|
||||
(THREW).clear(); \
|
||||
try \
|
||||
{ \
|
||||
CODE; \
|
||||
} \
|
||||
CATCH_AND_STORE_WHAT_IN(THREW, EXCEPTION) \
|
||||
(THREW) = catch_what<EXCEPTION>([&](){ \
|
||||
CODE; \
|
||||
}); \
|
||||
ensure("failed to throw " #EXCEPTION ": " #CODE, ! (THREW).empty()); \
|
||||
} while (0)
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@
|
|||
|
||||
#include "llsingleton.h"
|
||||
#include "../test/lltut.h"
|
||||
|
||||
#include "wrapllerrs.h"
|
||||
#include "llsd.h"
|
||||
|
||||
// Capture execution sequence by appending to log string.
|
||||
std::string sLog;
|
||||
|
|
@ -198,4 +199,130 @@ namespace tut
|
|||
|
||||
TESTS(A, B, 4, 5, 6, 7)
|
||||
TESTS(B, A, 8, 9, 10, 11)
|
||||
|
||||
#define PARAMSINGLETON(cls) \
|
||||
class cls: public LLParamSingleton<cls> \
|
||||
{ \
|
||||
LLSINGLETON(cls, const LLSD::String& str): mDesc(str) {} \
|
||||
cls(LLSD::Integer i): mDesc(i) {} \
|
||||
\
|
||||
public: \
|
||||
std::string desc() const { return mDesc.asString(); } \
|
||||
\
|
||||
private: \
|
||||
LLSD mDesc; \
|
||||
}
|
||||
|
||||
// Declare two otherwise-identical LLParamSingleton classes so we can
|
||||
// validly initialize each using two different constructors. If we tried
|
||||
// to test that with a single LLParamSingleton class within the same test
|
||||
// program, we'd get 'trying to use deleted LLParamSingleton' errors.
|
||||
PARAMSINGLETON(PSing1);
|
||||
PARAMSINGLETON(PSing2);
|
||||
|
||||
template<> template<>
|
||||
void singleton_object_t::test<12>()
|
||||
{
|
||||
set_test_name("LLParamSingleton");
|
||||
|
||||
WrapLLErrs catcherr;
|
||||
// query methods
|
||||
ensure("false positive on instanceExists()", ! PSing1::instanceExists());
|
||||
ensure("false positive on wasDeleted()", ! PSing1::wasDeleted());
|
||||
// try to reference before initializing
|
||||
std::string threw = catcherr.catch_llerrs([](){
|
||||
(void)PSing1::instance();
|
||||
});
|
||||
ensure_contains("too-early instance() didn't throw", threw, "Uninitialized");
|
||||
// getInstance() behaves the same as instance()
|
||||
threw = catcherr.catch_llerrs([](){
|
||||
(void)PSing1::getInstance();
|
||||
});
|
||||
ensure_contains("too-early getInstance() didn't throw", threw, "Uninitialized");
|
||||
// initialize using LLSD::String constructor
|
||||
PSing1::initParamSingleton("string");
|
||||
ensure_equals(PSing1::instance().desc(), "string");
|
||||
ensure("false negative on instanceExists()", PSing1::instanceExists());
|
||||
// try to initialize again
|
||||
threw = catcherr.catch_llerrs([](){
|
||||
PSing1::initParamSingleton("again");
|
||||
});
|
||||
ensure_contains("second ctor(string) didn't throw", threw, "twice");
|
||||
// try to initialize using the other constructor -- should be
|
||||
// well-formed, but illegal at runtime
|
||||
threw = catcherr.catch_llerrs([](){
|
||||
PSing1::initParamSingleton(17);
|
||||
});
|
||||
ensure_contains("other ctor(int) didn't throw", threw, "twice");
|
||||
PSing1::deleteSingleton();
|
||||
ensure("false negative on wasDeleted()", PSing1::wasDeleted());
|
||||
threw = catcherr.catch_llerrs([](){
|
||||
(void)PSing1::instance();
|
||||
});
|
||||
ensure_contains("accessed deleted LLParamSingleton", threw, "deleted");
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void singleton_object_t::test<13>()
|
||||
{
|
||||
set_test_name("LLParamSingleton alternate ctor");
|
||||
|
||||
WrapLLErrs catcherr;
|
||||
// We don't have to restate all the tests for PSing1. Only test validly
|
||||
// using the other constructor.
|
||||
PSing2::initParamSingleton(17);
|
||||
ensure_equals(PSing2::instance().desc(), "17");
|
||||
// can't do it twice
|
||||
std::string threw = catcherr.catch_llerrs([](){
|
||||
PSing2::initParamSingleton(34);
|
||||
});
|
||||
ensure_contains("second ctor(int) didn't throw", threw, "twice");
|
||||
// can't use the other constructor either
|
||||
threw = catcherr.catch_llerrs([](){
|
||||
PSing2::initParamSingleton("string");
|
||||
});
|
||||
ensure_contains("other ctor(string) didn't throw", threw, "twice");
|
||||
}
|
||||
|
||||
class CircularPCtor: public LLParamSingleton<CircularPCtor>
|
||||
{
|
||||
LLSINGLETON(CircularPCtor)
|
||||
{
|
||||
// never mind indirection, just go straight for the circularity
|
||||
(void)instance();
|
||||
}
|
||||
};
|
||||
|
||||
template<> template<>
|
||||
void singleton_object_t::test<14>()
|
||||
{
|
||||
set_test_name("Circular LLParamSingleton constructor");
|
||||
WrapLLErrs catcherr;
|
||||
std::string threw = catcherr.catch_llerrs([](){
|
||||
CircularPCtor::initParamSingleton();
|
||||
});
|
||||
ensure_contains("constructor circularity didn't throw", threw, "constructor");
|
||||
}
|
||||
|
||||
class CircularPInit: public LLParamSingleton<CircularPInit>
|
||||
{
|
||||
LLSINGLETON_EMPTY_CTOR(CircularPInit);
|
||||
public:
|
||||
virtual void initSingleton()
|
||||
{
|
||||
// never mind indirection, just go straight for the circularity
|
||||
(void)instance();
|
||||
}
|
||||
};
|
||||
|
||||
template<> template<>
|
||||
void singleton_object_t::test<15>()
|
||||
{
|
||||
set_test_name("Circular LLParamSingleton initSingleton()");
|
||||
WrapLLErrs catcherr;
|
||||
std::string threw = catcherr.catch_llerrs([](){
|
||||
CircularPInit::initParamSingleton();
|
||||
});
|
||||
ensure("initSingleton() circularity threw", threw.empty());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include "llerrorcontrol.h"
|
||||
#include "llexception.h"
|
||||
#include "stringize.h"
|
||||
#include "../test/catch_and_store_what_in.h"
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
|
@ -81,6 +82,31 @@ struct WrapLLErrs
|
|||
LLTHROW(FatalException(message));
|
||||
}
|
||||
|
||||
/// Convenience wrapper for catch_what<FatalException>()
|
||||
//
|
||||
// The implementation makes it clear that this function need not be a
|
||||
// member; it could easily be a free function. It is a member because it
|
||||
// makes no sense to attempt to catch FatalException unless there is a
|
||||
// WrapLLErrs instance in scope. Without a live WrapLLErrs instance, any
|
||||
// LL_ERRS() reached by code within 'func' would terminate the test
|
||||
// program instead of throwing FatalException.
|
||||
//
|
||||
// We were tempted to introduce a free function, likewise accepting
|
||||
// arbitrary 'func', that would instantiate WrapLLErrs and then call
|
||||
// catch_llerrs() on that instance. We decided against it, for this
|
||||
// reason: on extending a test function containing a single call to that
|
||||
// free function, a maintainer would most likely make additional calls to
|
||||
// that free function, instead of switching to an explicit WrapLLErrs
|
||||
// declaration with several calls to its catch_llerrs() member function.
|
||||
// Even a construct such as WrapLLErrs().catch_llerrs(...) would make the
|
||||
// object declaration more visible; it's not unreasonable to expect a
|
||||
// maintainer to extend that by naming and reusing the WrapLLErrs instance.
|
||||
template <typename FUNC>
|
||||
std::string catch_llerrs(FUNC func)
|
||||
{
|
||||
return catch_what<FatalException>(func);
|
||||
}
|
||||
|
||||
std::string error;
|
||||
LLError::SettingsStoragePtr mPriorErrorSettings;
|
||||
LLError::FatalFunction mPriorFatal;
|
||||
|
|
|
|||
|
|
@ -138,15 +138,9 @@ namespace tut
|
|||
WrapLLErrs capture;
|
||||
LLSD request;
|
||||
request["op"] = "foo";
|
||||
std::string threw;
|
||||
try
|
||||
{
|
||||
LLEventPumps::instance().obtain("LLAres").post(request);
|
||||
}
|
||||
catch (const WrapLLErrs::FatalException& e)
|
||||
{
|
||||
threw = e.what();
|
||||
}
|
||||
std::string threw = capture.catch_llerrs([&request](){
|
||||
LLEventPumps::instance().obtain("LLAres").post(request);
|
||||
});
|
||||
ensure_contains("LLAresListener bad op", threw, "bad");
|
||||
}
|
||||
|
||||
|
|
@ -157,15 +151,9 @@ namespace tut
|
|||
WrapLLErrs capture;
|
||||
LLSD request;
|
||||
request["op"] = "rewriteURI";
|
||||
std::string threw;
|
||||
try
|
||||
{
|
||||
LLEventPumps::instance().obtain("LLAres").post(request);
|
||||
}
|
||||
catch (const WrapLLErrs::FatalException& e)
|
||||
{
|
||||
threw = e.what();
|
||||
}
|
||||
std::string threw = capture.catch_llerrs([&request](){
|
||||
LLEventPumps::instance().obtain("LLAres").post(request);
|
||||
});
|
||||
ensure_contains("LLAresListener bad req", threw, "missing");
|
||||
ensure_contains("LLAresListener bad req", threw, "reply");
|
||||
ensure_contains("LLAresListener bad req", threw, "uri");
|
||||
|
|
@ -179,15 +167,9 @@ namespace tut
|
|||
LLSD request;
|
||||
request["op"] = "rewriteURI";
|
||||
request["reply"] = "nonexistent";
|
||||
std::string threw;
|
||||
try
|
||||
{
|
||||
LLEventPumps::instance().obtain("LLAres").post(request);
|
||||
}
|
||||
catch (const WrapLLErrs::FatalException& e)
|
||||
{
|
||||
threw = e.what();
|
||||
}
|
||||
std::string threw = capture.catch_llerrs([&request](){
|
||||
LLEventPumps::instance().obtain("LLAres").post(request);
|
||||
});
|
||||
ensure_contains("LLAresListener bad req", threw, "missing");
|
||||
ensure_contains("LLAresListener bad req", threw, "uri");
|
||||
ensure_does_not_contain("LLAresListener bad req", threw, "reply");
|
||||
|
|
@ -201,15 +183,9 @@ namespace tut
|
|||
LLSD request;
|
||||
request["op"] = "rewriteURI";
|
||||
request["uri"] = "foo.bar.com";
|
||||
std::string threw;
|
||||
try
|
||||
{
|
||||
LLEventPumps::instance().obtain("LLAres").post(request);
|
||||
}
|
||||
catch (const WrapLLErrs::FatalException& e)
|
||||
{
|
||||
threw = e.what();
|
||||
}
|
||||
std::string threw = capture.catch_llerrs([&request](){
|
||||
LLEventPumps::instance().obtain("LLAres").post(request);
|
||||
});
|
||||
ensure_contains("LLAresListener bad req", threw, "missing");
|
||||
ensure_contains("LLAresListener bad req", threw, "reply");
|
||||
ensure_does_not_contain("LLAresListener bad req", threw, "uri");
|
||||
|
|
|
|||
|
|
@ -88,15 +88,9 @@ namespace tut
|
|||
WrapLLErrs capture;
|
||||
LLSD request;
|
||||
request["uri"] = uri;
|
||||
std::string threw;
|
||||
try
|
||||
{
|
||||
pumps.obtain("LLXMLRPCTransaction").post(request);
|
||||
}
|
||||
catch (const WrapLLErrs::FatalException& e)
|
||||
{
|
||||
threw = e.what();
|
||||
}
|
||||
std::string threw = capture.catch_llerrs([&pumps, &request](){
|
||||
pumps.obtain("LLXMLRPCTransaction").post(request);
|
||||
});
|
||||
ensure_contains("threw exception", threw, "missing params");
|
||||
ensure_contains("identified missing", threw, "method");
|
||||
ensure_contains("identified missing", threw, "reply");
|
||||
|
|
@ -113,15 +107,9 @@ namespace tut
|
|||
request["reply"] = "reply";
|
||||
LLSD& params(request["params"]);
|
||||
params["who"]["specifically"] = "world"; // LLXMLRPCListener only handles scalar params
|
||||
std::string threw;
|
||||
try
|
||||
{
|
||||
pumps.obtain("LLXMLRPCTransaction").post(request);
|
||||
}
|
||||
catch (const WrapLLErrs::FatalException& e)
|
||||
{
|
||||
threw = e.what();
|
||||
}
|
||||
std::string threw = capture.catch_llerrs([&pumps, &request](){
|
||||
pumps.obtain("LLXMLRPCTransaction").post(request);
|
||||
});
|
||||
ensure_contains("threw exception", threw, "unknown type");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* @file catch_and_store_what_in.h
|
||||
* @author Nat Goodspeed
|
||||
* @date 2012-02-15
|
||||
* @brief CATCH_AND_STORE_WHAT_IN() macro
|
||||
* @brief catch_what() template function, CATCH_AND_STORE_WHAT_IN() macro
|
||||
*
|
||||
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
|
||||
* Copyright (c) 2012, Linden Research, Inc.
|
||||
|
|
@ -12,6 +12,30 @@
|
|||
#if ! defined(LL_CATCH_AND_STORE_WHAT_IN_H)
|
||||
#define LL_CATCH_AND_STORE_WHAT_IN_H
|
||||
|
||||
/**
|
||||
* In the brave new world of lambdas, we can use a nicer C++ idiom for testing
|
||||
* exceptions than CATCH_AND_STORE_WHAT_IN() below, e.g.:
|
||||
*
|
||||
* @code
|
||||
* std::string threw = catch_what<std::runtime_error>(
|
||||
* [](){ throw std::runtime_error("badness"); });
|
||||
* ensure_equals(threw, "badness");
|
||||
* @endcode
|
||||
*/
|
||||
template <typename EXCEPTION, typename FUNC>
|
||||
std::string catch_what(FUNC func)
|
||||
{
|
||||
try
|
||||
{
|
||||
func();
|
||||
return {};
|
||||
}
|
||||
catch (const EXCEPTION& err)
|
||||
{
|
||||
return err.what();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Idiom useful for test programs: catch an expected exception, store its
|
||||
* what() string in a specified std::string variable. From there the caller
|
||||
|
|
|
|||
|
|
@ -134,17 +134,15 @@ void events_object::test<1>()
|
|||
per_frame.post(4);
|
||||
check_listener("re-blocked", listener0, 3);
|
||||
} // unblock
|
||||
std::string threw;
|
||||
try
|
||||
{
|
||||
// NOTE: boost::bind() saves its arguments by VALUE! If you pass
|
||||
// an object instance rather than a pointer, you'll end up binding
|
||||
// to an internal copy of that instance! Use boost::ref() to
|
||||
// capture a reference instead.
|
||||
per_frame.listen(listener0.getName(), // note bug, dup name
|
||||
boost::bind(&Listener::call, boost::ref(listener1), _1));
|
||||
}
|
||||
CATCH_AND_STORE_WHAT_IN(threw, LLEventPump::DupListenerName)
|
||||
std::string threw = catch_what<LLEventPump::DupListenerName>(
|
||||
[&per_frame, this](){
|
||||
// NOTE: boost::bind() saves its arguments by VALUE! If you pass
|
||||
// an object instance rather than a pointer, you'll end up binding
|
||||
// to an internal copy of that instance! Use boost::ref() to
|
||||
// capture a reference instead.
|
||||
per_frame.listen(listener0.getName(), // note bug, dup name
|
||||
boost::bind(&Listener::call, boost::ref(listener1), _1));
|
||||
});
|
||||
ensure_equals(threw,
|
||||
std::string("DupListenerName: "
|
||||
"Attempt to register duplicate listener name '") +
|
||||
|
|
@ -341,15 +339,13 @@ void events_object::test<7>()
|
|||
ensure_equals(collector.result, make<StringVec>(list_of("Mary")("spot")("checked")));
|
||||
collector.clear();
|
||||
button.stopListening("spot");
|
||||
std::string threw;
|
||||
try
|
||||
{
|
||||
button.listen("spot",
|
||||
boost::bind(&Collect::add, boost::ref(collector), "spot", _1),
|
||||
// after "Mary" and "checked" -- whoops!
|
||||
make<NameList>(list_of("Mary")("checked")));
|
||||
}
|
||||
CATCH_AND_STORE_WHAT_IN(threw, LLEventPump::Cycle)
|
||||
std::string threw = catch_what<LLEventPump::Cycle>(
|
||||
[&button, &collector](){
|
||||
button.listen("spot",
|
||||
boost::bind(&Collect::add, boost::ref(collector), "spot", _1),
|
||||
// after "Mary" and "checked" -- whoops!
|
||||
make<NameList>(list_of("Mary")("checked")));
|
||||
});
|
||||
// Obviously the specific wording of the exception text can
|
||||
// change; go ahead and change the test to match.
|
||||
// Establish that it contains:
|
||||
|
|
@ -374,15 +370,13 @@ void events_object::test<7>()
|
|||
button.post(3);
|
||||
ensure_equals(collector.result, make<StringVec>(list_of("Mary")("checked")("yellow")("shoelaces")));
|
||||
collector.clear();
|
||||
threw.clear();
|
||||
try
|
||||
{
|
||||
button.listen("of",
|
||||
boost::bind(&Collect::add, boost::ref(collector), "of", _1),
|
||||
make<NameList>(list_of("shoelaces")),
|
||||
make<NameList>(list_of("yellow")));
|
||||
}
|
||||
CATCH_AND_STORE_WHAT_IN(threw, LLEventPump::OrderChange)
|
||||
threw = catch_what<LLEventPump::OrderChange>(
|
||||
[&button, &collector](){
|
||||
button.listen("of",
|
||||
boost::bind(&Collect::add, boost::ref(collector), "of", _1),
|
||||
make<NameList>(list_of("shoelaces")),
|
||||
make<NameList>(list_of("yellow")));
|
||||
});
|
||||
// Same remarks about the specific wording of the exception. Just
|
||||
// ensure that it contains enough information to clarify the
|
||||
// problem and what must be done to resolve it.
|
||||
|
|
@ -404,13 +398,11 @@ void events_object::test<8>()
|
|||
{ // nested scope
|
||||
// Hand-instantiate an LLEventStream...
|
||||
LLEventStream bob("bob");
|
||||
std::string threw;
|
||||
try
|
||||
{
|
||||
// then another with a duplicate name.
|
||||
LLEventStream bob2("bob");
|
||||
}
|
||||
CATCH_AND_STORE_WHAT_IN(threw, LLEventPump::DupPumpName)
|
||||
std::string threw = catch_what<LLEventPump::DupPumpName>(
|
||||
[](){
|
||||
// then another with a duplicate name.
|
||||
LLEventStream bob2("bob");
|
||||
});
|
||||
ensure("Caught DupPumpName", !threw.empty());
|
||||
} // delete first 'bob'
|
||||
LLEventStream bob("bob"); // should work, previous one unregistered
|
||||
|
|
@ -445,13 +437,11 @@ void events_object::test<9>()
|
|||
listener0.listenTo(random);
|
||||
eventSource("random");
|
||||
check_listener("got by pump name", listener0, 17);
|
||||
std::string threw;
|
||||
try
|
||||
{
|
||||
LLListenerOrPumpName empty;
|
||||
empty(17);
|
||||
}
|
||||
CATCH_AND_STORE_WHAT_IN(threw, LLListenerOrPumpName::Empty)
|
||||
std::string threw = catch_what<LLListenerOrPumpName::Empty>(
|
||||
[](){
|
||||
LLListenerOrPumpName empty;
|
||||
empty(17);
|
||||
});
|
||||
|
||||
ensure("threw Empty", !threw.empty());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@
|
|||
#include "linden_common.h"
|
||||
#include "llerrorcontrol.h"
|
||||
#include "lltut.h"
|
||||
#include "tests/wrapllerrs.h" // RecorderProxy
|
||||
#include "stringize.h"
|
||||
#include "namedtempfile.h"
|
||||
#include "lltrace.h"
|
||||
|
|
|
|||
Loading…
Reference in New Issue