DRTVWR-493: Introduce test catch_what(), catch_llerrs() functions.

Use them in place of awkward try/catch test boilerplate.
master
Nat Goodspeed 2019-08-10 20:33:59 -04:00
parent 8053bceaa0
commit adb3f447b3
13 changed files with 146 additions and 247 deletions

View File

@ -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 = 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 = catch_llerrs(
[&waiter, &debug](){
result = waiter.postAndSuspendWithLog(
LLSDMap("value", 31)("fail", LLSD()),
immediateAPI.getPump(), "reply", "error");
debug("no exception");
});
}
END
}

View File

@ -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");

View File

@ -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 = catch_llerrs([this](){
mainloop.post(17);
});
ensure_contains("errorAfter() timeout exception", threw, "timeout");
// Timing out cancels the timer. Verify that.
listener0.reset(0);

View File

@ -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 = 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 = 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 = catch_llerrs([&unkeyed](){
delete unkeyed;
});
}
ensure(! what.empty());
}

View File

@ -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");
}

View File

@ -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);

View File

@ -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)

View File

@ -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>
@ -86,6 +87,13 @@ struct WrapLLErrs
LLError::FatalFunction mPriorFatal;
};
/// Convenience wrapper for catch_what<WrapLLErrs::FatalException>()
template <typename FUNC>
std::string catch_llerrs(FUNC func)
{
return catch_what<WrapLLErrs::FatalException>(func);
}
/**
* Capture log messages. This is adapted (simplified) from the one in
* llerror_test.cpp.

View File

@ -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 = 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 = 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 = 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 = 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");

View File

@ -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 = 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 = catch_llerrs([&pumps, &request](){
pumps.obtain("LLXMLRPCTransaction").post(request);
});
ensure_contains("threw exception", threw, "unknown type");
}

View File

@ -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

View File

@ -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());
}

View File

@ -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"