diff options
author | Nat Goodspeed <nat@lindenlab.com> | 2023-10-29 11:56:17 -0400 |
---|---|---|
committer | Nat Goodspeed <nat@lindenlab.com> | 2023-10-29 11:56:17 -0400 |
commit | f7d2d40b3057f5bc249c88784b35443aad8de7aa (patch) | |
tree | 1e5a228889616e1130e0546ca432fa3096577f9a /indra/llcommon/tests | |
parent | 2667653d41d3b4799bf319783a884cbac7f826da (diff) |
DRTVWR-587: Fix LL::apply(function, LLSD array).
We define a specialization of LLSDParam<const char*> to support passing an
LLSD object to a const char* function parameter. Needless to remark, passing
object.asString().c_str() would be Bad: destroying the temporary std::string
returned by asString() would immediately invalidate the pointer returned by
its c_str(). But when you pass LLSDParam<const char*>(object) as the
parameter, that specialization itself stores the std::string so the c_str()
pointer remains valid as long as the LLSDParam object does.
Then there's LLSDParam<LLSD>, used when we don't have the parameter type
available to select the LLSDParam specialization. LLSDParam<LLSD> defines a
templated conversion operator T() that constructs an LLSDParam<T> to provide
the actual parameter value. So far, so good.
The trouble was with the implementation of LLSDParam<LLSD>: it constructed a
_temporary_ LLSDParam<T>, implicitly called its operator T() and immediately
destroyed it. Destroying LLSDParam<const char*> destroyed its stored string,
thus invalidating the c_str() pointer before the target function was entered.
Instead, make LLSDParam<LLSD>::operator T() capture each LLSDParam<T> it
constructs, extending its lifespan to the lifespan of the LLSDParam<LLSD>
instance. For this, derive each LLSDParam specialization from LLSDParamBase, a
trivial base class that simply establishes the virtual destructor. We can then
capture any specialization as a pointer to LLSDParamBase.
Also restore LazyEventAPI tests on Mac.
Diffstat (limited to 'indra/llcommon/tests')
-rw-r--r-- | indra/llcommon/tests/lleventdispatcher_test.cpp | 15 |
1 files changed, 4 insertions, 11 deletions
diff --git a/indra/llcommon/tests/lleventdispatcher_test.cpp b/indra/llcommon/tests/lleventdispatcher_test.cpp index 40643172ee..b0c532887c 100644 --- a/indra/llcommon/tests/lleventdispatcher_test.cpp +++ b/indra/llcommon/tests/lleventdispatcher_test.cpp @@ -178,6 +178,7 @@ struct Vars /*-------- Arbitrary-params (non-const, const, static) methods ---------*/ void methodna(NPARAMSa) { + DEBUG; // Because our const char* param cp might be NULL, and because we // intend to capture the value in a std::string, have to distinguish // between the NULL value and any non-NULL value. Use a convention @@ -189,7 +190,7 @@ struct Vars else vcp = std::string("'") + cp + "'"; - debug()("methodna(", b, + this->debug()("methodna(", b, ", ", i, ", ", f, ", ", d, @@ -227,7 +228,8 @@ struct Vars void cmethodna(NPARAMSa) const { - debug()('c', NONL); + DEBUG; + this->debug()('c', NONL); const_cast<Vars*>(this)->methodna(NARGSa); } @@ -1200,9 +1202,6 @@ namespace tut void object::test<20>() { set_test_name("call array-style functions with right-size arrays"); -#if defined(_MSC_VER) - skip("This test fails on VS"); -#endif std::vector<U8> binary; for (size_t h(0x01), i(0); i < 5; h+= 0x22, ++i) { @@ -1241,9 +1240,6 @@ namespace tut void object::test<21>() { set_test_name("verify that passing LLSD() to const char* sends NULL"); -#if defined(_MSC_VER) - skip("This test fails on VS"); -#endif ensure_equals("Vars::cp init", v.cp, ""); work("methodna_map_mdft", LLSDMap("cp", LLSD())); @@ -1257,9 +1253,6 @@ namespace tut template<> template<> void object::test<22>() { -#if defined(_MSC_VER) - skip("This test fails on VS"); -#endif set_test_name("call map-style functions with (full | oversized) (arrays | maps)"); const char binary[] = "\x99\x88\x77\x66\x55"; LLSD array_full(LLSDMap |