diff options
| author | Nat Goodspeed <nat@lindenlab.com> | 2019-08-12 17:43:09 -0400 | 
|---|---|---|
| committer | Nat Goodspeed <nat@lindenlab.com> | 2019-08-12 17:43:09 -0400 | 
| commit | a5f58663c00d9d6ffa12d4b9f8cf4eeee70b4d5e (patch) | |
| tree | 4655c10ed8baf9de95732f7bfbb8663e965b2a2a /indra | |
| parent | 3c552696bf8704e30c1525a4f9d4b3dd09034820 (diff) | |
| parent | 4fce6dc4353dbf9ccd3c9c3aced89df72a4f3abd (diff) | |
Automated merge with ssh://bitbucket.org/andreykproductengine/drtvwr-493
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/llcommon/llsingleton.h | 30 | ||||
| -rw-r--r-- | indra/llcommon/tests/lleventcoro_test.cpp | 33 | ||||
| -rw-r--r-- | indra/llcommon/tests/lleventdispatcher_test.cpp | 83 | ||||
| -rw-r--r-- | indra/llcommon/tests/lleventfilter_test.cpp | 12 | ||||
| -rw-r--r-- | indra/llcommon/tests/llinstancetracker_test.cpp | 33 | ||||
| -rw-r--r-- | indra/llcommon/tests/lllazy_test.cpp | 13 | ||||
| -rw-r--r-- | indra/llcommon/tests/llleap_test.cpp | 20 | ||||
| -rw-r--r-- | indra/llcommon/tests/llprocess_test.cpp | 16 | ||||
| -rw-r--r-- | indra/llcommon/tests/llsingleton_test.cpp | 129 | ||||
| -rw-r--r-- | indra/llcommon/tests/wrapllerrs.h | 26 | ||||
| -rw-r--r-- | indra/llmessage/tests/llareslistener_test.cpp | 48 | ||||
| -rw-r--r-- | indra/newview/tests/llxmlrpclistener_test.cpp | 24 | ||||
| -rw-r--r-- | indra/test/catch_and_store_what_in.h | 26 | ||||
| -rw-r--r-- | indra/test/llevents_tut.cpp | 76 | ||||
| -rw-r--r-- | indra/test/test.cpp | 1 | 
15 files changed, 308 insertions, 262 deletions
| diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h index 9be02f7e7d..596a2388a1 100644 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -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. diff --git a/indra/llcommon/tests/lleventcoro_test.cpp b/indra/llcommon/tests/lleventcoro_test.cpp index a459d17fb8..fa02d2bb1a 100644 --- a/indra/llcommon/tests/lleventcoro_test.cpp +++ b/indra/llcommon/tests/lleventcoro_test.cpp @@ -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      } diff --git a/indra/llcommon/tests/lleventdispatcher_test.cpp b/indra/llcommon/tests/lleventdispatcher_test.cpp index 5a4df81bf1..a181d5c941 100644 --- a/indra/llcommon/tests/lleventdispatcher_test.cpp +++ b/indra/llcommon/tests/lleventdispatcher_test.cpp @@ -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"); diff --git a/indra/llcommon/tests/lleventfilter_test.cpp b/indra/llcommon/tests/lleventfilter_test.cpp index eb98b12ef5..1875013794 100644 --- a/indra/llcommon/tests/lleventfilter_test.cpp +++ b/indra/llcommon/tests/lleventfilter_test.cpp @@ -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); diff --git a/indra/llcommon/tests/llinstancetracker_test.cpp b/indra/llcommon/tests/llinstancetracker_test.cpp index c7d4b8a06b..d94fc0c56d 100644 --- a/indra/llcommon/tests/llinstancetracker_test.cpp +++ b/indra/llcommon/tests/llinstancetracker_test.cpp @@ -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());      } diff --git a/indra/llcommon/tests/lllazy_test.cpp b/indra/llcommon/tests/lllazy_test.cpp index 32a717f4fc..542306ee22 100644 --- a/indra/llcommon/tests/lllazy_test.cpp +++ b/indra/llcommon/tests/lllazy_test.cpp @@ -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");      } diff --git a/indra/llcommon/tests/llleap_test.cpp b/indra/llcommon/tests/llleap_test.cpp index 45648536c4..bf0a74d10d 100644 --- a/indra/llcommon/tests/llleap_test.cpp +++ b/indra/llcommon/tests/llleap_test.cpp @@ -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); diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp index 5c87cdabd9..222d832084 100644 --- a/indra/llcommon/tests/llprocess_test.cpp +++ b/indra/llcommon/tests/llprocess_test.cpp @@ -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) diff --git a/indra/llcommon/tests/llsingleton_test.cpp b/indra/llcommon/tests/llsingleton_test.cpp index 56886bc73f..da7bc6355c 100644 --- a/indra/llcommon/tests/llsingleton_test.cpp +++ b/indra/llcommon/tests/llsingleton_test.cpp @@ -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()); +    }  } diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h index 08fbf19b1c..b07d5afbd8 100644 --- a/indra/llcommon/tests/wrapllerrs.h +++ b/indra/llcommon/tests/wrapllerrs.h @@ -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; diff --git a/indra/llmessage/tests/llareslistener_test.cpp b/indra/llmessage/tests/llareslistener_test.cpp index c04696c86b..254185cbd0 100644 --- a/indra/llmessage/tests/llareslistener_test.cpp +++ b/indra/llmessage/tests/llareslistener_test.cpp @@ -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"); diff --git a/indra/newview/tests/llxmlrpclistener_test.cpp b/indra/newview/tests/llxmlrpclistener_test.cpp index 6e9756e7d5..dbaae7280c 100644 --- a/indra/newview/tests/llxmlrpclistener_test.cpp +++ b/indra/newview/tests/llxmlrpclistener_test.cpp @@ -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");      } diff --git a/indra/test/catch_and_store_what_in.h b/indra/test/catch_and_store_what_in.h index 59f8cc0085..5beba06024 100644 --- a/indra/test/catch_and_store_what_in.h +++ b/indra/test/catch_and_store_what_in.h @@ -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. @@ -13,6 +13,30 @@  #define LL_CATCH_AND_STORE_WHAT_IN_H  /** + * In the brave new world of lambdas, we can use a nicer C++ idiom for testing + * exceptions than CATCH_AND_STORE_WHAT_IN() below, e.g.: + * + * @code + * std::string threw = catch_what<std::runtime_error>( + *     [](){ throw std::runtime_error("badness"); }); + * ensure_equals(threw, "badness"); + * @endcode + */ +template <typename EXCEPTION, typename FUNC> +std::string catch_what(FUNC func) +{ +    try +    { +        func(); +        return {}; +    } +    catch (const EXCEPTION& err) +    { +        return err.what(); +    } +} + +/**   * Idiom useful for test programs: catch an expected exception, store its   * what() string in a specified std::string variable. From there the caller   * can do things like: diff --git a/indra/test/llevents_tut.cpp b/indra/test/llevents_tut.cpp index 16edab6282..3abae3e43e 100644 --- a/indra/test/llevents_tut.cpp +++ b/indra/test/llevents_tut.cpp @@ -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());  } diff --git a/indra/test/test.cpp b/indra/test/test.cpp index 861ec1d942..d4cd4b951e 100644 --- a/indra/test/test.cpp +++ b/indra/test/test.cpp @@ -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" | 
