From bd20c548dd02778a2c7a6c318e2b8df6b2fc36c3 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 2 Oct 2023 13:09:02 -0400 Subject: DRTVWR-589: Add initial integration test for LLLUAmanager. The first test runs a Lua script that calls post_on(), listen_events() and await_event() to engage in LLEventPump handshakes with the test program. Make llluamanager.cpp testable by putting LL_TEST conditionals around lots of viewer-internals headers and the lua_function definitions that engage them. Since LuaListener::connect() is called by its constructor, make it a static method that explicitly accepts the lua_State* (instead of finding it as mState). Add that parameter to its two existing calls. Add a debug log message when LuaListener is destroyed. This surfaced the need to pass a no-op deleter when listen_events() constructs a LuaListener::ptr_t. When compiled for LL_TEST, make LuaListener::mReplyPump an LLEventLogProxyFor instead of a plain LLEventStream. For debugging purposes, add a type string "LLEventLogProxy" for LLEventPumps::make(). A make() call with this type will return an LLEventLogProxyFor. --- indra/newview/tests/llluamanager_test.cpp | 101 ++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 indra/newview/tests/llluamanager_test.cpp (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp new file mode 100644 index 0000000000..e5e06b095c --- /dev/null +++ b/indra/newview/tests/llluamanager_test.cpp @@ -0,0 +1,101 @@ +/** + * @file llluamanager_test.cpp + * @author Nat Goodspeed + * @date 2023-09-28 + * @brief Test for llluamanager. + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Copyright (c) 2023, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +//#include "llviewerprecompiledheaders.h" +// associated header +#include "../newview/llluamanager.h" +// STL headers +// std headers +// external library headers +// other Linden headers +#include "../test/lltut.h" +#include "llapp.h" +#include "llevents.h" +#include "lleventcoro.h" +#include "stringize.h" +#include "../llcommon/tests/StringVec.h" + +class LLTestApp : public LLApp +{ +public: + bool init() override { return true; } + bool cleanup() override { return true; } + bool frame() override { return true; } +}; + +/***************************************************************************** +* TUT +*****************************************************************************/ +namespace tut +{ + struct llluamanager_data + { + // We need an LLApp instance because LLLUAmanager uses coroutines, + // which suspend, and when a coroutine suspends it checks LLApp state, + // and if it's not APP_STATUS_RUNNING the coroutine terminates. + LLTestApp mApp; + }; + typedef test_group llluamanager_group; + typedef llluamanager_group::object object; + llluamanager_group llluamanagergrp("llluamanager"); + + template<> template<> + void object::test<1>() + { + set_test_name("test post_on(), listen_events(), await_event()"); + StringVec posts; + LLEventStream replypump("testpump"); + LLTempBoundListener conn( + replypump.listen("test<1>", + [&posts](const LLSD& post) + { + posts.push_back(post.asString()); + return false; + })); + const std::string lua( + "-- test post_on,listen_events,await_event\n" + "post_on('testpump', 'entry')\n" + "callback = function(pump, data)\n" + " -- just echo the data we received\n" + " post_on('testpump', data)\n" + "end\n" + "post_on('testpump', 'listen_events()')\n" + "replypump, cmdpump = listen_events(callback)\n" + "post_on('testpump', replypump)\n" + "post_on('testpump', 'await_event()')\n" + "await_event(replypump)\n" + "post_on('testpump', 'exit')\n" + ); + LLLUAmanager::runScriptLine(lua); + StringVec expected{ + "entry", + "listen_events()", + "", + "await_event()", + "message", + "exit" + }; + for (int i = 0; i < 10 && posts.size() <= 2 && posts[2].empty(); ++i) + { + llcoro::suspend(); + } + expected[2] = posts.at(2); + LL_DEBUGS() << "Found pumpname '" << expected[2] << "'" << LL_ENDL; + LLEventPump& luapump{ LLEventPumps::instance().obtain(expected[2]) }; + LL_DEBUGS() << "Found pump '" << luapump.getName() << "', type '" + << LLError::Log::classname(luapump) + << "': post('" << expected[4] << "')" << LL_ENDL; + luapump.post(expected[4]); + llcoro::suspend(); + ensure_equals("post_on() sequence", posts, expected); + } +} // namespace tut -- cgit v1.2.3 From 01a59bab1a4b7c4645271a21cfaadc3735b6029c Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 4 Oct 2023 21:46:31 -0400 Subject: DRTVWR-589: Add tests for LLSD-to-Lua round-trip conversions. Add from_lua() function to run a small Lua script that constructs a specified Lua object and posts it back to the test program via a temporary LLEventPump. Call this with a variety of Lua objects, comparing to the expected LLSD. Add round_trip() function to run another small Lua script that listens for incoming LLEventPump events and, for each, posts the received Lua data back to the test program as LLSD. Call this with a variety of LLSD objects, comparing to the expected LLSD. Also collect these objects into an LLSD array and send that for a round trip; also collect into an LLSD map and send that. Sadly, tests currently drive an access violation when trying to convert a nested Lua table to LLSD. Add verbose debug logging to lua_tollsd() to identify the context at which we hit the access violation. Add comments describing further exceptions to LLSD-to-Lua round trip identity. Add lua_what() iostream manipulator to stream whatever we can readily discover about a value at a specified Lua stack index. Add lua_stack() to report the contents of the Lua stack. Since the stack is created anew for every call to a C function, this shouldn't usually be enormous. Add hexdump.h with iostream manipulators to dump a byte range as hex digits, or to produce readable text from a mix of printing and nonprinting ASCII characters. --- indra/newview/tests/llluamanager_test.cpp | 215 +++++++++++++++++++++++++++++- 1 file changed, 210 insertions(+), 5 deletions(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index e5e06b095c..1363f114c1 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -15,12 +15,17 @@ #include "../newview/llluamanager.h" // STL headers // std headers +#include // external library headers // other Linden headers #include "../test/lltut.h" #include "llapp.h" +#include "lldate.h" #include "llevents.h" #include "lleventcoro.h" +#include "llsdutil.h" +#include "lluri.h" +#include "lluuid.h" #include "stringize.h" #include "../llcommon/tests/StringVec.h" @@ -32,6 +37,17 @@ public: bool frame() override { return true; } }; +template +auto listener(CALLABLE&& callable) +{ + return [callable=std::forward(callable)] + (const LLSD& data) + { + callable(data); + return false; + }; +} + /***************************************************************************** * TUT *****************************************************************************/ @@ -56,11 +72,8 @@ namespace tut LLEventStream replypump("testpump"); LLTempBoundListener conn( replypump.listen("test<1>", - [&posts](const LLSD& post) - { - posts.push_back(post.asString()); - return false; - })); + listener([&posts](const LLSD& data) + { posts.push_back(data.asString()); }))); const std::string lua( "-- test post_on,listen_events,await_event\n" "post_on('testpump', 'entry')\n" @@ -98,4 +111,196 @@ namespace tut llcoro::suspend(); ensure_equals("post_on() sequence", posts, expected); } + + void from_lua(const std::string& desc, const std::string_view& construct, const LLSD& expect) + { + LLSD fromlua; + LLEventStream replypump("testpump"); + LLTempBoundListener conn( + replypump.listen("llluamanager_test", + listener([&fromlua](const LLSD& data){ fromlua = data; }))); + const std::string lua(stringize( + "-- test LLSD synthesized by Lua\n", + // we expect the caller's Lua snippet to construct a Lua object + // called 'data' + construct, "\n" + "post_on('testpump', data)\n" + )); + LLLUAmanager::runScriptLine(lua); + // At this point LLLUAmanager::runScriptLine() has launched a new C++ + // coroutine to run the passed Lua snippet, but that coroutine hasn't + // yet had a chance to run. Poke the coroutine scheduler until the Lua + // script has sent its data. + for (int i = 0; i < 10 && fromlua.isUndefined(); ++i) + { + llcoro::suspend(); + } + // We woke up again ourselves because the coroutine running Lua has + // finished. + ensure_equals(desc, fromlua, expect); + } + + template<> template<> + void object::test<2>() + { + set_test_name("LLSD from Lua"); + from_lua("nil", "data = nil", LLSD()); + from_lua("true", "data = true", true); + from_lua("false", "data = false", false); + from_lua("int", "data = 17", 17); + from_lua("real", "data = 3.14", 3.14); + from_lua("string", "data = 'string'", "string"); + // can't synthesize Lua userdata in Lua code: that can only be + // constructed by a C function + from_lua("empty table", "data = {}", LLSD()); + from_lua("nested empty table", "data = { 1, 2, 3, {}, 5 }", + llsd::array(1, 2, 3, LLSD(), 5)); + from_lua("nested non-empty table", "data = { 1, 2, 3, {a=0, b=1}, 5 }", + llsd::array(1, 2, 3, llsd::map("a", 0, "b", 1), 5)); + } + + void round_trip(const std::string& desc, const LLSD& send, const LLSD& expect) + { + LLSD reply; + LLEventStream replypump("testpump"); + LLTempBoundListener conn( + replypump.listen("llluamanager_test", + listener([&reply](const LLSD& post){ reply = post; }))); + const std::string lua( + "-- test LLSD round trip\n" + "callback = function(pump, data)\n" + " -- just echo the data we received\n" + " post_on('testpump', data)\n" + "end\n" + "replypump, cmdpump = listen_events(callback)\n" + "post_on('testpump', replypump)\n" + "await_event(replypump)\n" + ); + LLLUAmanager::runScriptLine(lua); + // At this point LLLUAmanager::runScriptLine() has launched a new C++ + // coroutine to run the passed Lua snippet, but that coroutine hasn't + // yet had a chance to run. Poke the coroutine scheduler until the Lua + // script has sent its reply pump name. + for (int i = 0; i < 10 && reply.isUndefined(); ++i) + { + llcoro::suspend(); + } + // We woke up again ourselves because the coroutine running Lua has + // reached the await_event() call, which suspends the calling C++ + // coroutine (including the Lua code running on it) until we post + // something to that reply pump. + auto luapump{ reply.asString() }; + reply.clear(); + LLEventPumps::instance().post(luapump, send); + // The C++ coroutine running the Lua script is now ready to run. Run + // it so it will echo the LLSD back to us. + llcoro::suspend(); + ensure_equals(desc, reply, expect); + } + + // Define an RTItem to be used for round-trip LLSD testing: what it is, + // what we send to Lua, what we expect to get back. They could be the + // same. + struct RTItem + { + RTItem(const std::string& name, const LLSD& send, const LLSD& expect): + mName(name), + mSend(send), + mExpect(expect) + {} + RTItem(const std::string& name, const LLSD& both): + mName(name), + mSend(both), + mExpect(both) + {} + + std::string mName; + LLSD mSend, mExpect; + }; + + bool will_be_nil(const LLSD& data) + { + // undefined LLSD converts to Lua nil. + // empty LLSD array or empty LLSD map converts to nil. + return (data.isUndefined() || + ((data.isArray() || data.isMap()) && data.size() == 0)); + } + + template<> template<> + void object::test<3>() + { + set_test_name("LLSD round trip"); + LLSD::Binary binary{ 3, 1, 4, 1, 5, 9, 2, 6, 5 }; + const char* uuid{ "01234567-abcd-0123-4567-0123456789ab" }; + const char* date{ "2023-10-04T21:06:00Z" }; + const char* uri{ "https://secondlife.com/index.html" }; + std::vector items{ + RTItem("undefined", LLSD()), + RTItem("true", true), + RTItem("false", false), + RTItem("int", 17), + RTItem("real", 3.14), + RTItem("int real", 27.0, 27), + RTItem("string", "string"), + RTItem("binary", binary), + RTItem("empty array", LLSD::emptyArray(), LLSD()), + RTItem("empty map", LLSD::emptyMap(), LLSD()), + RTItem("UUID", LLUUID(uuid), uuid), + RTItem("date", LLDate(date), date), + RTItem("uri", LLURI(uri), uri) + }; + // scalars + for (const auto& item: items) + { + round_trip(item.mName, item.mSend, item.mExpect); + } + + // array + LLSD send_array{ LLSD::emptyArray() }, expect_array{ LLSD::emptyArray() }; + for (const auto& item: items) + { + // BUG AVOIDANCE: + // As of 2023-10-04, lua_tollsd() hits access violation in + // lua_next() when handed a table nested in another table. + if (! (item.mSend.isArray() || item.mSend.isMap())) + { + send_array.append(item.mSend); + expect_array.append(item.mExpect); + } + } + // Lua takes a table value of nil to mean: don't store this key. An + // LLSD array containing undefined entries (converted to nil) leaves + // "holes" in the Lua table. These will be converted back to undefined + // LLSD entries -- except at the end. Trailing undefined entries are + // simply omitted from the table -- so the table converts back to a + // shorter LLSD array. We've constructed send_array and expect_array + // according to 'items' above -- but truncate from expect_array any + // trailing entries that will map to Lua nil. + while (expect_array.size() > 0 && + will_be_nil(expect_array[expect_array.size() - 1])) + { + expect_array.erase(expect_array.size() - 1); + } + round_trip("array", send_array, expect_array); + + // map + LLSD send_map{ LLSD::emptyMap() }, expect_map{ LLSD::emptyMap() }; + for (const auto& item: items) + { + // BUG AVOIDANCE: + // see comment in the send_array construction loop above + if (! (item.mSend.isArray() || item.mSend.isMap())) + { + send_map[item.mName] = item.mSend; + // see comment in the expect_array truncation loop above -- + // keep this test because Lua never stores table entries with + // nil values + if (! will_be_nil(item.mExpect)) + { + expect_map[item.mName] = item.mExpect; + } + } + } + round_trip("map", send_map, expect_map); + } } // namespace tut -- cgit v1.2.3 From b8697234e095b3a8de579a3259dd99d00b1a36b4 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sat, 7 Oct 2023 09:42:36 -0400 Subject: DRTVWR-589: Solved the bug in traversing nested Lua tables. When lua_tollsd() makes a recursive call, it passes -1 as the index of the newly-encountered nested table. To traverse the nested table, lua_tollsd() starts by pushing nil as the initial key. But then calling lua_next(-1) finds nil -- NOT the nested table! Converting the index parameter to absolute before pushing nil solves. --- indra/newview/tests/llluamanager_test.cpp | 53 ++++++++++++++----------------- 1 file changed, 24 insertions(+), 29 deletions(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index 1363f114c1..6433ff1118 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -218,14 +218,6 @@ namespace tut LLSD mSend, mExpect; }; - bool will_be_nil(const LLSD& data) - { - // undefined LLSD converts to Lua nil. - // empty LLSD array or empty LLSD map converts to nil. - return (data.isUndefined() || - ((data.isArray() || data.isMap()) && data.size() == 0)); - } - template<> template<> void object::test<3>() { @@ -259,15 +251,12 @@ namespace tut LLSD send_array{ LLSD::emptyArray() }, expect_array{ LLSD::emptyArray() }; for (const auto& item: items) { - // BUG AVOIDANCE: - // As of 2023-10-04, lua_tollsd() hits access violation in - // lua_next() when handed a table nested in another table. - if (! (item.mSend.isArray() || item.mSend.isMap())) - { - send_array.append(item.mSend); - expect_array.append(item.mExpect); - } + send_array.append(item.mSend); + expect_array.append(item.mExpect); } + // exercise the array tail trimming below + send_array.append(items[0].mSend); + expect_array.append(items[0].mExpect); // Lua takes a table value of nil to mean: don't store this key. An // LLSD array containing undefined entries (converted to nil) leaves // "holes" in the Lua table. These will be converted back to undefined @@ -275,9 +264,9 @@ namespace tut // simply omitted from the table -- so the table converts back to a // shorter LLSD array. We've constructed send_array and expect_array // according to 'items' above -- but truncate from expect_array any - // trailing entries that will map to Lua nil. + // trailing entries whose mSend will map to Lua nil. while (expect_array.size() > 0 && - will_be_nil(expect_array[expect_array.size() - 1])) + send_array[expect_array.size() - 1].isUndefined()) { expect_array.erase(expect_array.size() - 1); } @@ -287,20 +276,26 @@ namespace tut LLSD send_map{ LLSD::emptyMap() }, expect_map{ LLSD::emptyMap() }; for (const auto& item: items) { - // BUG AVOIDANCE: - // see comment in the send_array construction loop above - if (! (item.mSend.isArray() || item.mSend.isMap())) + send_map[item.mName] = item.mSend; + // see comment in the expect_array truncation loop above -- + // Lua never stores table entries with nil values + if (item.mSend.isDefined()) { - send_map[item.mName] = item.mSend; - // see comment in the expect_array truncation loop above -- - // keep this test because Lua never stores table entries with - // nil values - if (! will_be_nil(item.mExpect)) - { - expect_map[item.mName] = item.mExpect; - } + expect_map[item.mName] = item.mExpect; } } round_trip("map", send_map, expect_map); + + // deeply nested map: exceed Lua's default stack space (20), + // i.e. verify that we have the right checkstack() calls + for (int i = 0; i < 20; ++i) + { + LLSD new_send_map{ send_map }, new_expect_map{ expect_map }; + new_send_map["nested map"] = send_map; + new_expect_map["nested map"] = expect_map; + send_map = new_send_map; + expect_map = new_expect_map; + } + round_trip("nested map", send_map, expect_map); } } // namespace tut -- cgit v1.2.3 From cf0838cd6917b7dd2c8f056d6cb3ef9f59d92fda Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 2 Nov 2023 09:05:41 -0400 Subject: DRTVWR-589: StringVec's operator<<() overload must precede lltut.h. If not, the resulting error message is so mysterious that it's worth adding an error check to explain how to avoid it. --- indra/newview/tests/llluamanager_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index 6433ff1118..98a2726af7 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -18,6 +18,7 @@ #include // external library headers // other Linden headers +#include "../llcommon/tests/StringVec.h" #include "../test/lltut.h" #include "llapp.h" #include "lldate.h" @@ -27,7 +28,6 @@ #include "lluri.h" #include "lluuid.h" #include "stringize.h" -#include "../llcommon/tests/StringVec.h" class LLTestApp : public LLApp { -- cgit v1.2.3 From 0c14c8a372a5d4639de3365f69e566962493fe78 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 7 Feb 2024 22:50:03 -0500 Subject: Fix tests broken by switching from Lua 5.4 to Luau. Add a new test<1>() that tests returning values from a Lua chunk using LLLUAmanager::waitScriptLine(). This exercises lua_tollsd() without yet involving LLEventPump machinery. For that purpose, extract from test<2>() the sequence of (description, expression, LLSD expected) triples into a static C array. The new test<1>() returns each such expression as a result; test<2>() posts each such expression to a test LLEventPump. test<2>() now uses waitScriptLine() instead of pumping the coroutine scheduler a few times and hoping. The pump-and-hope tactic worked before, but no longer does. waitScriptLine() is more robust anyway. Move the former test<1>() to test<3>() because it exercises still more machinery, specifically listen_events() and await_event(). Because this test involves a handshake with C++ code, use startScriptLine() to launch the Lua coroutine while providing a definite way to wait for completion later. Again, startScriptLine() followed by get() on the returned future is more robust than the previous pump-and-hope code. Similarly, the former test<3>(), now renamed test<4>(), uses startScriptLine() and Future::get() instead of pump-and-hope. --- indra/newview/tests/llluamanager_test.cpp | 143 ++++++++++++++++-------------- 1 file changed, 78 insertions(+), 65 deletions(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index 98a2726af7..1f25fd5f3b 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -27,6 +27,7 @@ #include "llsdutil.h" #include "lluri.h" #include "lluuid.h" +#include "lua_function.h" #include "stringize.h" class LLTestApp : public LLApp @@ -64,14 +65,80 @@ namespace tut typedef llluamanager_group::object object; llluamanager_group llluamanagergrp("llluamanager"); + static struct LuaExpr + { + std::string desc, expr; + LLSD expect; + } lua_expressions[] = { + { "nil", "nil", LLSD() }, + { "true", "true", true }, + { "false", "false", false }, + { "int", "17", 17 }, + { "real", "3.14", 3.14 }, + { "string", "'string'", "string" }, + // can't synthesize Lua userdata in Lua code: that can only be + // constructed by a C function + { "empty table", "{}", LLSD() }, + { "nested empty table", "{ 1, 2, 3, {}, 5 }", + llsd::array(1, 2, 3, LLSD(), 5) }, + { "nested non-empty table", "{ 1, 2, 3, {a=0, b=1}, 5 }", + llsd::array(1, 2, 3, llsd::map("a", 0, "b", 1), 5) }, + }; + template<> template<> void object::test<1>() + { + set_test_name("test Lua results"); + LuaState L; + for (auto& luax : lua_expressions) + { + auto [count, result] = + LLLUAmanager::waitScriptLine(L, "return " + luax.expr); + auto desc{ stringize("waitScriptLine(", luax.desc, ")") }; + ensure_equals(desc + ".count", count, 1); + ensure_equals(desc + ".result", result, luax.expect); + } + } + + void from_lua(const std::string& desc, const std::string_view& construct, const LLSD& expect) + { + LLSD fromlua; + LLEventStream replypump("testpump"); + LLTempBoundListener conn( + replypump.listen("llluamanager_test", + listener([&fromlua](const LLSD& data){ fromlua = data; }))); + const std::string lua(stringize( + "-- test LLSD synthesized by Lua\n", + "data = ", construct, "\n" + "post_on('testpump', data)\n" + )); + LuaState L; + auto [count, result] = LLLUAmanager::waitScriptLine(L, lua); + // We woke up again ourselves because the coroutine running Lua has + // finished. But our Lua chunk didn't actually return anything, so we + // expect count to be 0 and result to be undefined. + ensure_equals(desc + " count", count, 0); + ensure_equals(desc, fromlua, expect); + } + + template<> template<> + void object::test<2>() + { + set_test_name("LLSD from post_on()"); + for (auto& luax : lua_expressions) + { + from_lua(luax.desc, luax.expr, luax.expect); + } + } + + template<> template<> + void object::test<3>() { set_test_name("test post_on(), listen_events(), await_event()"); StringVec posts; LLEventStream replypump("testpump"); LLTempBoundListener conn( - replypump.listen("test<1>", + replypump.listen("test<3>", listener([&posts](const LLSD& data) { posts.push_back(data.asString()); }))); const std::string lua( @@ -88,7 +155,11 @@ namespace tut "await_event(replypump)\n" "post_on('testpump', 'exit')\n" ); - LLLUAmanager::runScriptLine(lua); + LuaState L; + // It's important to let the startScriptLine() coroutine run + // concurrently with ours until we've had a chance to post() our + // reply. + auto future = LLLUAmanager::startScriptLine(L, lua); StringVec expected{ "entry", "listen_events()", @@ -97,10 +168,6 @@ namespace tut "message", "exit" }; - for (int i = 0; i < 10 && posts.size() <= 2 && posts[2].empty(); ++i) - { - llcoro::suspend(); - } expected[2] = posts.at(2); LL_DEBUGS() << "Found pumpname '" << expected[2] << "'" << LL_ENDL; LLEventPump& luapump{ LLEventPumps::instance().obtain(expected[2]) }; @@ -108,57 +175,10 @@ namespace tut << LLError::Log::classname(luapump) << "': post('" << expected[4] << "')" << LL_ENDL; luapump.post(expected[4]); - llcoro::suspend(); + auto [count, result] = future.get(); ensure_equals("post_on() sequence", posts, expected); } - void from_lua(const std::string& desc, const std::string_view& construct, const LLSD& expect) - { - LLSD fromlua; - LLEventStream replypump("testpump"); - LLTempBoundListener conn( - replypump.listen("llluamanager_test", - listener([&fromlua](const LLSD& data){ fromlua = data; }))); - const std::string lua(stringize( - "-- test LLSD synthesized by Lua\n", - // we expect the caller's Lua snippet to construct a Lua object - // called 'data' - construct, "\n" - "post_on('testpump', data)\n" - )); - LLLUAmanager::runScriptLine(lua); - // At this point LLLUAmanager::runScriptLine() has launched a new C++ - // coroutine to run the passed Lua snippet, but that coroutine hasn't - // yet had a chance to run. Poke the coroutine scheduler until the Lua - // script has sent its data. - for (int i = 0; i < 10 && fromlua.isUndefined(); ++i) - { - llcoro::suspend(); - } - // We woke up again ourselves because the coroutine running Lua has - // finished. - ensure_equals(desc, fromlua, expect); - } - - template<> template<> - void object::test<2>() - { - set_test_name("LLSD from Lua"); - from_lua("nil", "data = nil", LLSD()); - from_lua("true", "data = true", true); - from_lua("false", "data = false", false); - from_lua("int", "data = 17", 17); - from_lua("real", "data = 3.14", 3.14); - from_lua("string", "data = 'string'", "string"); - // can't synthesize Lua userdata in Lua code: that can only be - // constructed by a C function - from_lua("empty table", "data = {}", LLSD()); - from_lua("nested empty table", "data = { 1, 2, 3, {}, 5 }", - llsd::array(1, 2, 3, LLSD(), 5)); - from_lua("nested non-empty table", "data = { 1, 2, 3, {a=0, b=1}, 5 }", - llsd::array(1, 2, 3, llsd::map("a", 0, "b", 1), 5)); - } - void round_trip(const std::string& desc, const LLSD& send, const LLSD& expect) { LLSD reply; @@ -176,15 +196,8 @@ namespace tut "post_on('testpump', replypump)\n" "await_event(replypump)\n" ); - LLLUAmanager::runScriptLine(lua); - // At this point LLLUAmanager::runScriptLine() has launched a new C++ - // coroutine to run the passed Lua snippet, but that coroutine hasn't - // yet had a chance to run. Poke the coroutine scheduler until the Lua - // script has sent its reply pump name. - for (int i = 0; i < 10 && reply.isUndefined(); ++i) - { - llcoro::suspend(); - } + LuaState L; + auto future = LLLUAmanager::startScriptLine(L, lua); // We woke up again ourselves because the coroutine running Lua has // reached the await_event() call, which suspends the calling C++ // coroutine (including the Lua code running on it) until we post @@ -194,7 +207,7 @@ namespace tut LLEventPumps::instance().post(luapump, send); // The C++ coroutine running the Lua script is now ready to run. Run // it so it will echo the LLSD back to us. - llcoro::suspend(); + auto [count, result] = future.get(); ensure_equals(desc, reply, expect); } @@ -219,7 +232,7 @@ namespace tut }; template<> template<> - void object::test<3>() + void object::test<4>() { set_test_name("LLSD round trip"); LLSD::Binary binary{ 3, 1, 4, 1, 5, 9, 2, 6, 5 }; -- cgit v1.2.3 From 85ef003ed7836cb351ee62ed44a4837a305e9dbd Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 22 Feb 2024 20:42:08 -0500 Subject: Lua listen_events(), await_event() => get_event_{pumps,next}(). Don't set up a Lua callback to receive incoming events, a la listen_events(). Don't listen on an arbitrary event pump, a la await_event(). Instead, the new get_event_pumps() entry point simply delivers the reply pump and command pump names (as listen_events() did) without storing a Lua callback. Make LuaListener capture incoming events on the reply pump in a queue. This avoids the problem of multiple events arriving too quickly for the Lua script to retrieve. If the queue gets too big, discard the excess instead of blocking the caller of post(). Then the new get_event_next() entry point retrieves the next (pump, data) pair from the queue, blocking the Lua script until a suitable event arrives. This is closer to the use of stdin for a LEAP plugin. It also addresses the question: what should the Lua script's C++ coroutine do while waiting for an incoming reply pump event? Recast llluamanager_test.cpp for this new, more straightforward API. Move LLLeap's and LuaListener's reply LLEventPump into LLLeapListener, which they both use. This simplifies LLLeapListener's API, which was a little convoluted: the caller supplied a connect callback to allow LLLeapListener to connect some listener to the caller's reply pump. Now, instead, the caller simply passes a bool(pumpname, data) callback to receive events incoming on LLLeapListener's own reply pump. Fix a latent bug in LLLeapListener: if a plugin called listen() more than once with the same listener name, the new connection would not have been saved. While at it, replace some older Boost features in LLLeapListener and LLLeap. --- indra/newview/tests/llluamanager_test.cpp | 35 +++++++++++++------------------ 1 file changed, 14 insertions(+), 21 deletions(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index 1f25fd5f3b..81ec186cf4 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -108,7 +108,6 @@ namespace tut replypump.listen("llluamanager_test", listener([&fromlua](const LLSD& data){ fromlua = data; }))); const std::string lua(stringize( - "-- test LLSD synthesized by Lua\n", "data = ", construct, "\n" "post_on('testpump', data)\n" )); @@ -134,7 +133,7 @@ namespace tut template<> template<> void object::test<3>() { - set_test_name("test post_on(), listen_events(), await_event()"); + set_test_name("test post_on(), get_event_pumps(), get_event_next()"); StringVec posts; LLEventStream replypump("testpump"); LLTempBoundListener conn( @@ -142,17 +141,14 @@ namespace tut listener([&posts](const LLSD& data) { posts.push_back(data.asString()); }))); const std::string lua( - "-- test post_on,listen_events,await_event\n" + "-- test post_on,get_event_pumps,get_event_next\n" "post_on('testpump', 'entry')\n" - "callback = function(pump, data)\n" - " -- just echo the data we received\n" - " post_on('testpump', data)\n" - "end\n" - "post_on('testpump', 'listen_events()')\n" - "replypump, cmdpump = listen_events(callback)\n" + "post_on('testpump', 'get_event_pumps()')\n" + "replypump, cmdpump = get_event_pumps()\n" "post_on('testpump', replypump)\n" - "post_on('testpump', 'await_event()')\n" - "await_event(replypump)\n" + "post_on('testpump', 'get_event_next()')\n" + "pump, data = get_event_next()\n" + "post_on('testpump', data)\n" "post_on('testpump', 'exit')\n" ); LuaState L; @@ -162,9 +158,9 @@ namespace tut auto future = LLLUAmanager::startScriptLine(L, lua); StringVec expected{ "entry", - "listen_events()", + "get_event_pumps()", "", - "await_event()", + "get_event_next()", "message", "exit" }; @@ -188,18 +184,15 @@ namespace tut listener([&reply](const LLSD& post){ reply = post; }))); const std::string lua( "-- test LLSD round trip\n" - "callback = function(pump, data)\n" - " -- just echo the data we received\n" - " post_on('testpump', data)\n" - "end\n" - "replypump, cmdpump = listen_events(callback)\n" + "replypump, cmdpump = get_event_pumps()\n" "post_on('testpump', replypump)\n" - "await_event(replypump)\n" + "pump, data = get_event_next()\n" + "return data\n" ); LuaState L; auto future = LLLUAmanager::startScriptLine(L, lua); // We woke up again ourselves because the coroutine running Lua has - // reached the await_event() call, which suspends the calling C++ + // reached the get_event_next() call, which suspends the calling C++ // coroutine (including the Lua code running on it) until we post // something to that reply pump. auto luapump{ reply.asString() }; @@ -208,7 +201,7 @@ namespace tut // The C++ coroutine running the Lua script is now ready to run. Run // it so it will echo the LLSD back to us. auto [count, result] = future.get(); - ensure_equals(desc, reply, expect); + ensure_equals(desc, result, expect); } // Define an RTItem to be used for round-trip LLSD testing: what it is, -- cgit v1.2.3 From efdda0b93d2dbf28e7722150028476286f0ec623 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 8 Mar 2024 10:53:50 -0500 Subject: Enhance llluamanager_test.cpp. Sketch in an initial test that requires one of our bundled Lua modules. Each time we run Lua, report any error returned by the Lua engine. Use llcoro::suspendUntilEventOn(LLEventMailDrop) as shorthand for initializing an explicit LLTempBoundListener with a listen() call with a lambda. --- indra/newview/tests/llluamanager_test.cpp | 34 +++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 11 deletions(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index 81ec186cf4..1c2be900d3 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -94,9 +94,10 @@ namespace tut { auto [count, result] = LLLUAmanager::waitScriptLine(L, "return " + luax.expr); - auto desc{ stringize("waitScriptLine(", luax.desc, ")") }; - ensure_equals(desc + ".count", count, 1); - ensure_equals(desc + ".result", result, luax.expect); + auto desc{ stringize("waitScriptLine(", luax.desc, "): ") }; + // if count < 0, report Lua error message + ensure_equals(desc + result.asString(), count, 1); + ensure_equals(desc + "result", result, luax.expect); } } @@ -116,7 +117,7 @@ namespace tut // We woke up again ourselves because the coroutine running Lua has // finished. But our Lua chunk didn't actually return anything, so we // expect count to be 0 and result to be undefined. - ensure_equals(desc + " count", count, 0); + ensure_equals(desc + ": " + result.asString(), count, 0); ensure_equals(desc, fromlua, expect); } @@ -172,16 +173,13 @@ namespace tut << "': post('" << expected[4] << "')" << LL_ENDL; luapump.post(expected[4]); auto [count, result] = future.get(); + ensure_equals("post_on(): " + result.asString(), count, 0); ensure_equals("post_on() sequence", posts, expected); } void round_trip(const std::string& desc, const LLSD& send, const LLSD& expect) { - LLSD reply; - LLEventStream replypump("testpump"); - LLTempBoundListener conn( - replypump.listen("llluamanager_test", - listener([&reply](const LLSD& post){ reply = post; }))); + LLEventMailDrop replypump("testpump"); const std::string lua( "-- test LLSD round trip\n" "replypump, cmdpump = get_event_pumps()\n" @@ -195,12 +193,12 @@ namespace tut // reached the get_event_next() call, which suspends the calling C++ // coroutine (including the Lua code running on it) until we post // something to that reply pump. - auto luapump{ reply.asString() }; - reply.clear(); + auto luapump{ llcoro::suspendUntilEventOn(replypump).asString() }; LLEventPumps::instance().post(luapump, send); // The C++ coroutine running the Lua script is now ready to run. Run // it so it will echo the LLSD back to us. auto [count, result] = future.get(); + ensure_equals(stringize("round_trip(", desc, "): ", result.asString()), count, 1); ensure_equals(desc, result, expect); } @@ -304,4 +302,18 @@ namespace tut } round_trip("nested map", send_map, expect_map); } + + template<> template<> + void object::test<5>() + { + set_test_name("test leap.lua"); + const std::string lua( + "-- test leap.lua\n" + "leap = require('leap')\n" + ); + LuaState L; + auto future = LLLUAmanager::startScriptLine(L, lua); + auto [count, result] = future.get(); + ensure_equals("leap.lua: " + result.asString(), count, 0); + } } // namespace tut -- cgit v1.2.3 From 199907fa280cb3d1ea5a27dbe94e69df9256c101 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 11 Mar 2024 12:57:46 -0400 Subject: Add llluamanager_test test exercising leap.WaitFor. --- indra/newview/tests/llluamanager_test.cpp | 35 +++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index 1c2be900d3..36b8bb046a 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -28,6 +28,7 @@ #include "lluri.h" #include "lluuid.h" #include "lua_function.h" +#include "lualistener.h" #include "stringize.h" class LLTestApp : public LLApp @@ -309,10 +310,44 @@ namespace tut set_test_name("test leap.lua"); const std::string lua( "-- test leap.lua\n" + "\n" "leap = require('leap')\n" + "\n" + "-- negative priority ensures catchall is always last\n" + "catchall = leap.WaitFor:new(-1, 'catchall')\n" + "function catchall:filter(pump, data)\n" + " return data\n" + "end\n" + "\n" + "-- but first, catch events with 'special' key\n" + "catch_special = leap.WaitFor:new(2, 'catch_special')\n" + "function catch_special:filter(pump, data)\n" + " return if data['special'] ~= nil then data else nil\n" + "end\n" + "\n" + "function drain(waitfor)\n" + " print(waitfor.name .. ' start')\n" + " for item in waitfor.wait, waitfor do\n" + " print(waitfor.name .. ' caught', item)\n" + " end\n" + " print(waitfor.name .. ' done')\n" + "end\n" + "\n" + "co_all = coroutine.create(drain)\n" + "co_special = coroutine.create(drain)\n" + "coroutine.resume(co_all, catchall)\n" + "coroutine.resume(co_special, catch_special)\n" + "\n" + "leap.process()\n" ); LuaState L; auto future = LLLUAmanager::startScriptLine(L, lua); + auto replyname{ L.obtainListener()->getReplyName() }; + auto& replypump{ LLEventPumps::instance().obtain(replyname) }; + replypump.post(llsd::map("special", "K")); + replypump.post(llsd::map("name", "not special")); + // tell leap.process() we're done + replypump.post(LLSD()); auto [count, result] = future.get(); ensure_equals("leap.lua: " + result.asString(), count, 0); } -- cgit v1.2.3 From 7f25ec566ed671119ecf3d47c4f3be54232969cb Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 13 Mar 2024 14:46:14 -0400 Subject: Add tests for leap.request(). Use new coro.lua module. request() test ensures that the response for a given reqid is routed to the correct coroutine even when responses arrive out of order. --- indra/newview/tests/llluamanager_test.cpp | 51 ++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 5 deletions(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index 36b8bb046a..069e10e9cf 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -312,6 +312,7 @@ namespace tut "-- test leap.lua\n" "\n" "leap = require('leap')\n" + "coro = require('coro')\n" "\n" "-- negative priority ensures catchall is always last\n" "catchall = leap.WaitFor:new(-1, 'catchall')\n" @@ -327,25 +328,65 @@ namespace tut "\n" "function drain(waitfor)\n" " print(waitfor.name .. ' start')\n" - " for item in waitfor.wait, waitfor do\n" + " -- It seems as though we ought to be able to code this loop\n" + " -- over waitfor:wait() as:\n" + " -- for item in waitfor.wait, waitfor do\n" + " -- However, that seems to stitch a detour through C code into\n" + " -- the coroutine call stack, which prohibits coroutine.yield():\n" + " -- 'attempt to yield across metamethod/C-call boundary'\n" + " -- So we resort to two different calls to waitfor:wait().\n" + " item = waitfor:wait()\n" + " while item do\n" " print(waitfor.name .. ' caught', item)\n" + " item = waitfor:wait()\n" " end\n" " print(waitfor.name .. ' done')\n" "end\n" "\n" - "co_all = coroutine.create(drain)\n" - "co_special = coroutine.create(drain)\n" - "coroutine.resume(co_all, catchall)\n" - "coroutine.resume(co_special, catch_special)\n" + "function requester(name)\n" + " print('requester('..name..') start')\n" + " response = leap.request('testpump', {name=name})\n" + " print('requester('..name..') got '..tostring(response))\n" + " -- verify that the correct response was dispatched to this coroutine\n" + " assert(response.name == name)\n" + "end\n" + "\n" + "coro.launch(drain, catchall)\n" + "coro.launch(drain, catch_special)\n" + "coro.launch(requester, 'a')\n" + "coro.launch(requester, 'b')\n" "\n" "leap.process()\n" ); + + LLSD requests; + LLEventStream pump("testpump", false); + LLTempBoundListener conn{ + pump.listen("test<5>()", + listener([&requests](const LLSD& data) + { + LL_DEBUGS("Lua") << "testpump got: " << data << LL_ENDL; + requests.append(data); + })) + }; + LuaState L; auto future = LLLUAmanager::startScriptLine(L, lua); auto replyname{ L.obtainListener()->getReplyName() }; auto& replypump{ LLEventPumps::instance().obtain(replyname) }; + // By the time leap.process() calls get_event_next() and wakes us up, + // we expect that both requester() coroutines have posted and are + // waiting for a reply. + ensure_equals("didn't get both requests", requests.size(), 2); + // moreover, we expect they arrived in the order they were created + ensure_equals("a wasn't first", requests[0]["name"].asString(), "a"); + ensure_equals("b wasn't second", requests[1]["name"].asString(), "b"); replypump.post(llsd::map("special", "K")); + // respond to requester(b) FIRST + replypump.post(requests[1]); replypump.post(llsd::map("name", "not special")); + // now respond to requester(a) + replypump.post(requests[0]); // tell leap.process() we're done replypump.post(LLSD()); auto [count, result] = future.get(); -- cgit v1.2.3 From 0566af988790e95414ed18cd82206710094d8fae Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 21 Mar 2024 23:56:46 +0900 Subject: WIP: Add fiber.lua module and use in leap.lua and WaitQueue.lua. fiber.lua goes beyond coro.lua in that it distinguishes ready suspended coroutines from waiting suspended coroutines, and presents a rudimentary scheduler in fiber.yield(). yield() can determine that when all coroutines are waiting, it's time to retrieve the next incoming event from the viewer. Moreover, it can detect when all coroutines have completed and exit without being explicitly told. fiber.launch() associates a name with each fiber for debugging purposes. fiber.get_name() retrieves the name of the specified fiber, or the running fiber. fiber.status() is like coroutine.status(), but can return 'ready' or 'waiting' instead of 'suspended'. fiber.yield() leaves the calling fiber ready, but lets other ready fibers run. fiber.wait() suspends the calling fiber and lets other ready fibers run. fiber.wake(), called from some other coroutine, returns the passed fiber to ready status for a future call to fiber.yield(). fiber.run() drives the scheduler to run all fibers to completion. If, on completion of the subject Lua script, LuaState::expr() detects that the script loaded fiber.lua, it calls fiber.run() to finish running any dangling fibers. This lets a script make calls to fiber.launch() and then just fall off the end, leaving the implicit fiber.run() call to run them all. fiber.lua is designed to allow the main thread, as well as explicitly launched coroutines, to make leap.request() calls. This part still needs debugging. The leap.lua module now configures a fiber.set_idle() function that honors leap.done(), but calls get_event_next() and dispatches the next incoming event. leap.request() and generate() now leave the reqid stamp in the response. This lets a caller handle subsequent events with the same reqid, e.g. for LLLuaFloater. Remove leap.process(): it has been superseded by fiber.run(). Remove leap.WaitFor:iterate(): unfortunately that would run afoul of the Luau bug that prevents suspending the calling coroutine within a generic 'for' iterator function. Make leap.lua use weak tables to track WaitFor objects. Make WaitQueue:Dequeue() call fiber.wait() to suspend its caller when the queue is empty, and Enqueue() call fiber.wake() to set it ready again when a new item is pushed. Make llluamanager_test.cpp's leap test script use the fiber module to launch coroutines, instead of the coro module. Fix a bug in which its drain() function was inadvertently setting and testing the global 'item' variable instead of one local to the function. Since some other modules had the same bug, it was getting confused. Also add printf.lua, providing a printf() function. printf() is short for print(string.format()), but it can also print tables: anything not a number or string is formatted using the inspect() function. Clean up some LL_DEBUGS() output left over from debugging lua_tollsd(). --- indra/newview/tests/llluamanager_test.cpp | 34 ++++++++++++++++++------------- 1 file changed, 20 insertions(+), 14 deletions(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index 069e10e9cf..1dd081fb98 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -311,23 +311,27 @@ namespace tut const std::string lua( "-- test leap.lua\n" "\n" + "fiber = require('fiber')\n" "leap = require('leap')\n" - "coro = require('coro')\n" + "-- debug = require('printf')\n" + "local function debug(...) end\n" "\n" "-- negative priority ensures catchall is always last\n" "catchall = leap.WaitFor:new(-1, 'catchall')\n" "function catchall:filter(pump, data)\n" + " debug('catchall:filter(%s, %s)', pump, data)\n" " return data\n" "end\n" "\n" "-- but first, catch events with 'special' key\n" "catch_special = leap.WaitFor:new(2, 'catch_special')\n" "function catch_special:filter(pump, data)\n" + " debug('catch_special:filter(%s, %s)', pump, data)\n" " return if data['special'] ~= nil then data else nil\n" "end\n" "\n" "function drain(waitfor)\n" - " print(waitfor.name .. ' start')\n" + " debug('%s start', waitfor.name)\n" " -- It seems as though we ought to be able to code this loop\n" " -- over waitfor:wait() as:\n" " -- for item in waitfor.wait, waitfor do\n" @@ -335,28 +339,30 @@ namespace tut " -- the coroutine call stack, which prohibits coroutine.yield():\n" " -- 'attempt to yield across metamethod/C-call boundary'\n" " -- So we resort to two different calls to waitfor:wait().\n" - " item = waitfor:wait()\n" + " local item = waitfor:wait()\n" " while item do\n" - " print(waitfor.name .. ' caught', item)\n" + " debug('%s caught %s', waitfor.name, item)\n" " item = waitfor:wait()\n" " end\n" - " print(waitfor.name .. ' done')\n" + " debug('%s done', waitfor.name)\n" "end\n" "\n" "function requester(name)\n" - " print('requester('..name..') start')\n" - " response = leap.request('testpump', {name=name})\n" - " print('requester('..name..') got '..tostring(response))\n" + " debug('requester(%s) start', name)\n" + " local response = leap.request('testpump', {name=name})\n" + " debug('requester(%s) got %s', name, response)\n" " -- verify that the correct response was dispatched to this coroutine\n" " assert(response.name == name)\n" "end\n" "\n" - "coro.launch(drain, catchall)\n" - "coro.launch(drain, catch_special)\n" - "coro.launch(requester, 'a')\n" - "coro.launch(requester, 'b')\n" - "\n" - "leap.process()\n" + "-- fiber.print_all()\n" + "fiber.launch('catchall', drain, catchall)\n" + "fiber.launch('catch_special', drain, catch_special)\n" + "fiber.launch('requester(a)', requester, 'a')\n" + "-- requester(a)\n" + "fiber.launch('requester(b)', requester, 'b')\n" + "-- fiber.print_all()\n" + "-- fiber.run()\n" ); LLSD requests; -- cgit v1.2.3 From bb39a8b223f78205a10ffcb61e3b3bfe05b3fd1a Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 22 Mar 2024 21:04:48 +0900 Subject: Fix a couple bugs in fiber.lua machinery. This fixes a hang if the Lua script explicitly calls fiber.run() before LuaState::expr()'s implicit fiber.run() call. Make fiber.run() remove the calling fiber from the ready list to avoid an infinite loop when all other fibers have terminated: "You're ready!" "Okay, yield()." "You're ready again!" ... But don't claim it's waiting, either, because then when all other fibers have terminated, we'd call idle() in the vain hope that something would make that one last fiber ready. WaitQueue:_wake_waiters() needs to wake waiting fibers if the queue's not empty OR it's been closed. Introduce leap.WaitFor:close() to close the queue gracefully so that a looping waiter can terminate, instead of using WaitFor:exception(), which stops the whole script once it propagates. Make leap's cleanup() function call close(). Streamline fiber.get_name() by using 'or' instead of if ... then. Streamline fiber.status() and fiber.set_waiting() by using table.find() instead of a loop. --- indra/newview/tests/llluamanager_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index 1dd081fb98..d1beed84ef 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -361,8 +361,8 @@ namespace tut "fiber.launch('requester(a)', requester, 'a')\n" "-- requester(a)\n" "fiber.launch('requester(b)', requester, 'b')\n" + "fiber.run()\n" "-- fiber.print_all()\n" - "-- fiber.run()\n" ); LLSD requests; -- cgit v1.2.3 From 2dc003779443db99f46b3db6d17a1954f7b141dd Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sat, 23 Mar 2024 17:43:07 +0900 Subject: Make leap.request() work even from Lua's main thread. Recast fiber.yield() as internal function scheduler(). Move fiber.run() after it so it can call scheduler() as a local function. Add new fiber.yield() that also calls scheduler(); the added value of this new fiber.yield() over plain scheduler() is that if scheduler() returns before the caller is ready (because the configured set_idle() function returned non-nil), it produces an explicit error rather than returning to its caller. So the caller can assume that when fiber.yield() returns normally, the calling fiber is ready. This allows any fiber, including the main thread, to call fiber.yield() or fiber.wait(). This supports using leap.request(), which posts a request and then waits on a WaitForReqid, which calls ErrorQueue:Dequeue(), which calls fiber.wait(). WaitQueue:_wake_waiters() must call fiber.status() instead of coroutine.status() so it understands the special token 'main'. Add a new llluamanager_test.cpp test to exercise calling leap.request() from Lua's main thread. --- indra/newview/tests/llluamanager_test.cpp | 43 ++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 6 deletions(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index d1beed84ef..0fd91c1354 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -307,9 +307,43 @@ namespace tut template<> template<> void object::test<5>() { - set_test_name("test leap.lua"); + set_test_name("leap.request() from main thread"); const std::string lua( - "-- test leap.lua\n" + "-- leap.request() from main thread\n" + "\n" + "leap = require 'leap'\n" + "\n" + "return {\n" + " a=leap.request('echo', {data='a'}).data,\n" + " b=leap.request('echo', {data='b'}).data\n" + "}\n" + ); + + LLEventStream pump("echo", false); + LLTempBoundListener conn{ + pump.listen( + "test<5>()", + listener([](const LLSD& data) + { + LL_DEBUGS("Lua") << "echo pump got: " << data << LL_ENDL; + LLEventPumps::instance().post( + data["reply"], + llsd::map("reqid", data["reqid"], "data", data["data"])); + })) + }; + + LuaState L; + auto [count, result] = LLLUAmanager::waitScriptLine(L, lua); + ensure_equals("Lua script didn't return item", count, 1); + ensure_equals("echo failed", result, llsd::map("a", "a", "b", "b")); + } + + template<> template<> + void object::test<6>() + { + set_test_name("interleave leap.request() responses"); + const std::string lua( + "-- interleave leap.request() responses\n" "\n" "fiber = require('fiber')\n" "leap = require('leap')\n" @@ -359,16 +393,13 @@ namespace tut "fiber.launch('catchall', drain, catchall)\n" "fiber.launch('catch_special', drain, catch_special)\n" "fiber.launch('requester(a)', requester, 'a')\n" - "-- requester(a)\n" "fiber.launch('requester(b)', requester, 'b')\n" - "fiber.run()\n" - "-- fiber.print_all()\n" ); LLSD requests; LLEventStream pump("testpump", false); LLTempBoundListener conn{ - pump.listen("test<5>()", + pump.listen("test<6>()", listener([&requests](const LLSD& data) { LL_DEBUGS("Lua") << "testpump got: " << data << LL_ENDL; -- cgit v1.2.3 From 93b30f960ea327fe3c36deed72a8075ce0d13f19 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sun, 24 Mar 2024 02:16:55 +0900 Subject: Introduce LLStreamListener: bundle LLEventStream+LLTempBoundListener. This is a very common pattern, especially in test code, but elsewhere in the viewer too. Use it in llluamanager_test.cpp. --- indra/newview/tests/llluamanager_test.cpp | 53 ++++++++++++------------------- 1 file changed, 21 insertions(+), 32 deletions(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index 0fd91c1354..872d7827fe 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -105,10 +105,8 @@ namespace tut void from_lua(const std::string& desc, const std::string_view& construct, const LLSD& expect) { LLSD fromlua; - LLEventStream replypump("testpump"); - LLTempBoundListener conn( - replypump.listen("llluamanager_test", - listener([&fromlua](const LLSD& data){ fromlua = data; }))); + LLStreamListener pump("testpump", + listener([&fromlua](const LLSD& data){ fromlua = data; })); const std::string lua(stringize( "data = ", construct, "\n" "post_on('testpump', data)\n" @@ -137,11 +135,9 @@ namespace tut { set_test_name("test post_on(), get_event_pumps(), get_event_next()"); StringVec posts; - LLEventStream replypump("testpump"); - LLTempBoundListener conn( - replypump.listen("test<3>", - listener([&posts](const LLSD& data) - { posts.push_back(data.asString()); }))); + LLStreamListener pump("testpump", + listener([&posts](const LLSD& data) + { posts.push_back(data.asString()); })); const std::string lua( "-- test post_on,get_event_pumps,get_event_next\n" "post_on('testpump', 'entry')\n" @@ -180,7 +176,7 @@ namespace tut void round_trip(const std::string& desc, const LLSD& send, const LLSD& expect) { - LLEventMailDrop replypump("testpump"); + LLEventMailDrop testpump("testpump"); const std::string lua( "-- test LLSD round trip\n" "replypump, cmdpump = get_event_pumps()\n" @@ -194,7 +190,7 @@ namespace tut // reached the get_event_next() call, which suspends the calling C++ // coroutine (including the Lua code running on it) until we post // something to that reply pump. - auto luapump{ llcoro::suspendUntilEventOn(replypump).asString() }; + auto luapump{ llcoro::suspendUntilEventOn(testpump).asString() }; LLEventPumps::instance().post(luapump, send); // The C++ coroutine running the Lua script is now ready to run. Run // it so it will echo the LLSD back to us. @@ -319,18 +315,13 @@ namespace tut "}\n" ); - LLEventStream pump("echo", false); - LLTempBoundListener conn{ - pump.listen( - "test<5>()", - listener([](const LLSD& data) - { - LL_DEBUGS("Lua") << "echo pump got: " << data << LL_ENDL; - LLEventPumps::instance().post( - data["reply"], - llsd::map("reqid", data["reqid"], "data", data["data"])); - })) - }; + LLStreamListener pump( + "echo", + listener([](const LLSD& data) + { + LL_DEBUGS("Lua") << "echo pump got: " << data << LL_ENDL; + sendReply(data, data); + })); LuaState L; auto [count, result] = LLLUAmanager::waitScriptLine(L, lua); @@ -397,15 +388,13 @@ namespace tut ); LLSD requests; - LLEventStream pump("testpump", false); - LLTempBoundListener conn{ - pump.listen("test<6>()", - listener([&requests](const LLSD& data) - { - LL_DEBUGS("Lua") << "testpump got: " << data << LL_ENDL; - requests.append(data); - })) - }; + LLStreamListener pump( + "testpump", + listener([&requests](const LLSD& data) + { + LL_DEBUGS("Lua") << "testpump got: " << data << LL_ENDL; + requests.append(data); + })); LuaState L; auto future = LLLUAmanager::startScriptLine(L, lua); -- cgit v1.2.3 From ac4fa418e3a7402f9d9122c726d2fbfc4b8767b2 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 25 Mar 2024 16:29:17 -0400 Subject: Add LL. prefix to viewer entry points, fix existing references. --- indra/newview/tests/llluamanager_test.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index 872d7827fe..e10dedcf53 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -109,7 +109,7 @@ namespace tut listener([&fromlua](const LLSD& data){ fromlua = data; })); const std::string lua(stringize( "data = ", construct, "\n" - "post_on('testpump', data)\n" + "LL.post_on('testpump', data)\n" )); LuaState L; auto [count, result] = LLLUAmanager::waitScriptLine(L, lua); @@ -140,14 +140,14 @@ namespace tut { posts.push_back(data.asString()); })); const std::string lua( "-- test post_on,get_event_pumps,get_event_next\n" - "post_on('testpump', 'entry')\n" - "post_on('testpump', 'get_event_pumps()')\n" - "replypump, cmdpump = get_event_pumps()\n" - "post_on('testpump', replypump)\n" - "post_on('testpump', 'get_event_next()')\n" - "pump, data = get_event_next()\n" - "post_on('testpump', data)\n" - "post_on('testpump', 'exit')\n" + "LL.post_on('testpump', 'entry')\n" + "LL.post_on('testpump', 'get_event_pumps()')\n" + "replypump, cmdpump = LL.get_event_pumps()\n" + "LL.post_on('testpump', replypump)\n" + "LL.post_on('testpump', 'get_event_next()')\n" + "pump, data = LL.get_event_next()\n" + "LL.post_on('testpump', data)\n" + "LL.post_on('testpump', 'exit')\n" ); LuaState L; // It's important to let the startScriptLine() coroutine run @@ -179,9 +179,9 @@ namespace tut LLEventMailDrop testpump("testpump"); const std::string lua( "-- test LLSD round trip\n" - "replypump, cmdpump = get_event_pumps()\n" - "post_on('testpump', replypump)\n" - "pump, data = get_event_next()\n" + "replypump, cmdpump = LL.get_event_pumps()\n" + "LL.post_on('testpump', replypump)\n" + "pump, data = LL.get_event_next()\n" "return data\n" ); LuaState L; -- cgit v1.2.3 From ce73e5c5ab0c33673067d9322c98ae8800fa9224 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 28 Mar 2024 07:11:31 -0400 Subject: Terminate Lua scripts hanging in LL.get_event_next(). Make LuaListener listen for "LLApp" viewer shutdown events. On receiving such, it closes its queue. Then the C++ coroutine calling getNext() wakes up with an LLThreadSafeQueue exception, and calls LLCoros::checkStop() to throw one of the exceptions recognized by LLCoros::toplevel(). Add an llluamanager_test.cpp test to verify this behavior. --- indra/newview/tests/llluamanager_test.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index e10dedcf53..682289bd93 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -418,4 +418,25 @@ namespace tut auto [count, result] = future.get(); ensure_equals("leap.lua: " + result.asString(), count, 0); } + + template<> template<> + void object::test<7>() + { + set_test_name("stop hanging Lua script"); + const std::string lua( + "-- hanging Lua script should terminate\n" + "\n" + "LL.get_event_next()\n" + ); + LuaState L; + auto future = LLLUAmanager::startScriptLine(L, lua); + // The problem with this test is that the LuaState is destroyed + // (disconnecting the listener) before the LLTestApp instance mApp is + // destroyed (sending the shutdown event). Explicitly simulate LLApp's + // event. + LLEventPumps::instance().obtain("LLApp").post(llsd::map("status", "quitting")); + // but now we have to give the startScriptLine() coroutine a chance to run + auto [count, result] = future.get(); + ensure_equals(result.asString(), count, 0); + } } // namespace tut -- cgit v1.2.3 From ba74839cd19c3b17757345ba81b1aa97c57f43d4 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 28 Mar 2024 11:49:19 -0400 Subject: Use LLApp::setQuitting(). Expect killed-script error. --- indra/newview/tests/llluamanager_test.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index 682289bd93..b907ac6619 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -430,13 +430,12 @@ namespace tut ); LuaState L; auto future = LLLUAmanager::startScriptLine(L, lua); - // The problem with this test is that the LuaState is destroyed - // (disconnecting the listener) before the LLTestApp instance mApp is - // destroyed (sending the shutdown event). Explicitly simulate LLApp's - // event. - LLEventPumps::instance().obtain("LLApp").post(llsd::map("status", "quitting")); + // Poke LLTestApp to send its preliminary shutdown message. + mApp.setQuitting(); // but now we have to give the startScriptLine() coroutine a chance to run auto [count, result] = future.get(); - ensure_equals(result.asString(), count, 0); + ensure_equals("killed Lua script terminated normally", count, -1); + ensure_equals("unexpected killed Lua script error", + result.asString(), "viewer is stopping"); } } // namespace tut -- cgit v1.2.3 From 426dc4da45f91afbb1107aecf075e501e774e8ee Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 18 Apr 2024 16:53:12 -0400 Subject: Add llluamanager_test.cpp test that terminates runaway Lua script. Also tweak existing Lua interleaved-responses test to accommodate new Lua periodic suspend behavior. --- indra/newview/tests/llluamanager_test.cpp | 35 +++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index b907ac6619..cf1bf25b5c 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -400,9 +400,16 @@ namespace tut auto future = LLLUAmanager::startScriptLine(L, lua); auto replyname{ L.obtainListener()->getReplyName() }; auto& replypump{ LLEventPumps::instance().obtain(replyname) }; - // By the time leap.process() calls get_event_next() and wakes us up, - // we expect that both requester() coroutines have posted and are - // waiting for a reply. + // LuaState::expr() periodically interrupts a running chunk to ensure + // the rest of our coroutines get cycles. Nonetheless, for this test + // we have to wait until both requester() coroutines have posted and + // are waiting for a reply. + for (unsigned count=0; count < 100; ++count) + { + if (requests.size() == 2) + break; + llcoro::suspend(); + } ensure_equals("didn't get both requests", requests.size(), 2); // moreover, we expect they arrived in the order they were created ensure_equals("a wasn't first", requests[0]["name"].asString(), "a"); @@ -413,7 +420,7 @@ namespace tut replypump.post(llsd::map("name", "not special")); // now respond to requester(a) replypump.post(requests[0]); - // tell leap.process() we're done + // tell leap we're done replypump.post(LLSD()); auto [count, result] = future.get(); ensure_equals("leap.lua: " + result.asString(), count, 0); @@ -438,4 +445,24 @@ namespace tut ensure_equals("unexpected killed Lua script error", result.asString(), "viewer is stopping"); } + + template<> template<> + void object::test<8>() + { + set_test_name("stop looping Lua script"); + const std::string desc("looping Lua script should terminate"); + const std::string lua( + "-- " + desc + "\n" + "\n" + "while true do\n" + " x = 1\n" + "end\n" + ); + LuaState L; + auto [count, result] = LLLUAmanager::waitScriptLine(L, lua); + // We expect the above erroneous script has been forcibly terminated + // because it ran too long without doing any actual work. + ensure_equals(desc + " count: " + result.asString(), count, -1); + ensure_contains(desc + " result", result.asString(), "terminated"); + } } // namespace tut -- cgit v1.2.3 From 5b6a5c757deaba3c2b361eb49f2e61630fe3eb47 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 17 Jun 2024 11:18:09 -0400 Subject: Store script's LuaListener in userdata in lua_State's Registry. Instead of deriving LuaListener from LLInstanceTracker with an int key, generating a unique int key and storing that key in the Registry, use new lua_emplace() to store the LuaListener directly in a Lua userdata object in the Lua Registry. Because lua_emplace() uses LL.atexit() to guarantee that ~LuaState will destroy the T object, we no longer need ~LuaState() to make a special call specifically to destroy the LuaListener, if any. So we no longer need LuaState::getListener() separate from obtainListener(). Since LuaListener is no longer an LLInstanceTracker subclass, make LuaState::obtainListener() return LuaListener& rather than LuaListener::ptr_t. --- indra/newview/tests/llluamanager_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index cf1bf25b5c..2d525f7913 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -398,7 +398,7 @@ namespace tut LuaState L; auto future = LLLUAmanager::startScriptLine(L, lua); - auto replyname{ L.obtainListener()->getReplyName() }; + auto replyname{ L.obtainListener().getReplyName() }; auto& replypump{ LLEventPumps::instance().obtain(replyname) }; // LuaState::expr() periodically interrupts a running chunk to ensure // the rest of our coroutines get cycles. Nonetheless, for this test -- cgit v1.2.3 From e26727e03bb02d26b3f0d83f748dbd8eb88e4940 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 18 Jun 2024 13:13:39 -0400 Subject: Remove special-case ~LuaState() code to call fiber.run(). Instead, make fiber.lua call LL.atexit(fiber.run) to schedule that final run() call at ~LuaState() time using the generic mechanism. Append an explicit fiber.run() call to a specific test in llluamanager_test.cpp because the test code wants to interact with multiple Lua fibers *before* we destroy the LuaState. --- indra/newview/tests/llluamanager_test.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index 2d525f7913..206dbd9e71 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -385,6 +385,12 @@ namespace tut "fiber.launch('catch_special', drain, catch_special)\n" "fiber.launch('requester(a)', requester, 'a')\n" "fiber.launch('requester(b)', requester, 'b')\n" + // A script can normally count on an implicit fiber.run() call + // because fiber.lua calls LL.atexit(fiber.run). But atexit() + // functions are called by ~LuaState(), which (in the code below) + // won't be called until *after* we expect to interact with the + // various fibers. So make an explicit call for test purposes. + "fiber.run()\n" ); LLSD requests; -- cgit v1.2.3 From 0cc7436be1f57299384c5acad5d32e13f2f4d1cf Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 27 Jun 2024 19:47:00 -0400 Subject: Introduce TypeTag template whose int value differs for each T. This replaces type_tag(), which searched and possibly extended the type_tags unordered_map at runtime. If we called lua_emplace() from different threads, that would require locking type_tags. In contrast, the compiler must instantiate a distinct TypeTag for every distinct T passed to lua_emplace(), so each gets a distinct value at static initialization time. No locking is required; no lookup; no allocations. Add a test to llluamanager_test.cpp to verify that each distinct T passed to lua_emplace() gets its own TypeTag::value, and that each gets its own destructor -- but that different lua_emplace() calls with the same T share the same TypeTag::value and the same destructor. --- indra/newview/tests/llluamanager_test.cpp | 35 +++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index 2d525f7913..d3fc70dfd5 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -465,4 +465,39 @@ namespace tut ensure_equals(desc + " count: " + result.asString(), count, -1); ensure_contains(desc + " result", result.asString(), "terminated"); } + + template + struct Visible + { + Visible(T name): name(name) + { + LL_INFOS() << "Visible<" << LLError::Log::classname() << ">('" << name << "')" << LL_ENDL; + } + Visible(const Visible&) = delete; + Visible& operator=(const Visible&) = delete; + ~Visible() + { + LL_INFOS() << "~Visible<" << LLError::Log::classname() << ">('" << name << "')" << LL_ENDL; + } + T name; + }; + + template<> template<> + void object::test<9>() + { + set_test_name("track distinct lua_emplace() types"); + LuaState L; + lua_emplace>(L, "std::string 0"); + int st0tag = lua_userdatatag(L, -1); + lua_emplace>(L, "const char* 0"); + int cp0tag = lua_userdatatag(L, -1); + lua_emplace>(L, "std::string 1"); + int st1tag = lua_userdatatag(L, -1); + lua_emplace>(L, "const char* 1"); + int cp1tag = lua_userdatatag(L, -1); + lua_settop(L, 0); + ensure_equals("lua_emplace() tags diverge", st0tag, st1tag); + ensure_equals("lua_emplace() tags diverge", cp0tag, cp1tag); + ensure_not_equals("lua_emplace<>() tags collide", st0tag, cp0tag); + } } // namespace tut -- cgit v1.2.3 From f8357732a108e579c285a76a53c550b8b5c0a153 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 2 Jul 2024 12:09:59 -0400 Subject: Make require() implementation honor LuaRequirePath setting. Remove LL_TEST special case from require() code (to search in the viewer's source tree). Instead, make llluamanager_test.cpp append to LuaRequirePath to get the same effect. --- indra/newview/tests/llluamanager_test.cpp | 33 +++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index d3fc70dfd5..55e87acaea 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -21,6 +21,7 @@ #include "../llcommon/tests/StringVec.h" #include "../test/lltut.h" #include "llapp.h" +#include "llcontrol.h" #include "lldate.h" #include "llevents.h" #include "lleventcoro.h" @@ -39,6 +40,8 @@ public: bool frame() override { return true; } }; +LLControlGroup gSavedSettings("Global"); + template auto listener(CALLABLE&& callable) { @@ -57,6 +60,36 @@ namespace tut { struct llluamanager_data { + llluamanager_data() + { + // Load gSavedSettings from source tree + // indra/newview/tests/llluamanager_test.cpp => + // indra/newview + auto newview{ fsyspath(__FILE__).parent_path().parent_path() }; + auto settings{ newview / "app_settings" / "settings.xml" }; + // true suppresses implicit declare; implicit declare requires + // that every variable in settings.xml has a Comment, which many don't. + gSavedSettings.loadFromFile(settings.u8string().c_str(), true); + // At test time, since we don't have the app bundle available, + // extend LuaRequirePath to include the require directory in the + // source tree. + auto require{ (newview / "scripts" / "lua" / "require").u8string() }; + auto paths{ gSavedSettings.getLLSD("LuaRequirePath") }; + bool found = false; + for (const auto& path : llsd::inArray(paths)) + { + if (path.asString() == require) + { + found = true; + break; + } + } + if (! found) + { + paths.append(require); + gSavedSettings.setLLSD("LuaRequirePath", paths); + } + } // We need an LLApp instance because LLLUAmanager uses coroutines, // which suspend, and when a coroutine suspends it checks LLApp state, // and if it's not APP_STATUS_RUNNING the coroutine terminates. -- cgit v1.2.3 From 9a3c770a3bf430da8878a8691cee9b726a5f026c Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 2 Jul 2024 13:12:40 -0400 Subject: Eliminate c_str() calls from LLControlGroup::loadFromFile() calls. Passing std::string::c_str() to a (const std::string&) function parameter is worse than clutter, it's pointless overhead: it forces the compiler to construct a new std::string instance, instead of passing a const reference to the one you already have in hand. --- indra/newview/tests/llluamanager_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index 55e87acaea..824ddd445b 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -69,7 +69,7 @@ namespace tut auto settings{ newview / "app_settings" / "settings.xml" }; // true suppresses implicit declare; implicit declare requires // that every variable in settings.xml has a Comment, which many don't. - gSavedSettings.loadFromFile(settings.u8string().c_str(), true); + gSavedSettings.loadFromFile(settings.u8string(), true); // At test time, since we don't have the app bundle available, // extend LuaRequirePath to include the require directory in the // source tree. -- cgit v1.2.3 From 8c94ff566a4f9076607d1b988f3eb7ad7e200bd9 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 10 Jul 2024 15:14:13 -0400 Subject: Remove ability to reuse a LuaState between LLLUAmanager functions. Remove LLLUAmanager::mumbleScriptLine() LuaState& parameters. Make startScriptLine(), waitScriptLine() and runScriptLine() exactly parallel to startScriptFile(), waitScriptFile() and runScriptFile(). That means that runScriptLine()'s C++ coroutine instantiates and destroys its own LuaState, which means that LL.atexit() functions will run on the Lua-specific C++ coroutine rather than (say) the viewer's main coroutine. Introduce LLLUAmanager::script_result typedef for std::pair and use in method returns. Remove LuaState::initLuaState(); move its logic back into the constructor. Remove initLuaState() calls in the expr() error cases: they're moot now that we won't get subsequent expr() calls on the same LuaState instance. Remove LLFloaterLUADebug "Use clean lua_State" checkbox and the cleanLuaState() method. Remove mState member. Remove explicit LuaState declarations from LLLUAmanager tests. Adapt one test for implicit LuaState: it was directly calling LuaState::obtainListener() to discover the LuaListener's reply-pump name. But since that test also captures two leap.request() calls from the Lua script, it can just look at the "reply" key in either of those requests. --- indra/newview/tests/llluamanager_test.cpp | 34 ++++++++++++------------------- 1 file changed, 13 insertions(+), 21 deletions(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index 824ddd445b..79ec9b9d3a 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -123,11 +123,10 @@ namespace tut void object::test<1>() { set_test_name("test Lua results"); - LuaState L; for (auto& luax : lua_expressions) { auto [count, result] = - LLLUAmanager::waitScriptLine(L, "return " + luax.expr); + LLLUAmanager::waitScriptLine("return " + luax.expr); auto desc{ stringize("waitScriptLine(", luax.desc, "): ") }; // if count < 0, report Lua error message ensure_equals(desc + result.asString(), count, 1); @@ -144,8 +143,7 @@ namespace tut "data = ", construct, "\n" "LL.post_on('testpump', data)\n" )); - LuaState L; - auto [count, result] = LLLUAmanager::waitScriptLine(L, lua); + auto [count, result] = LLLUAmanager::waitScriptLine(lua); // We woke up again ourselves because the coroutine running Lua has // finished. But our Lua chunk didn't actually return anything, so we // expect count to be 0 and result to be undefined. @@ -182,11 +180,10 @@ namespace tut "LL.post_on('testpump', data)\n" "LL.post_on('testpump', 'exit')\n" ); - LuaState L; // It's important to let the startScriptLine() coroutine run // concurrently with ours until we've had a chance to post() our // reply. - auto future = LLLUAmanager::startScriptLine(L, lua); + auto future = LLLUAmanager::startScriptLine(lua); StringVec expected{ "entry", "get_event_pumps()", @@ -217,8 +214,7 @@ namespace tut "pump, data = LL.get_event_next()\n" "return data\n" ); - LuaState L; - auto future = LLLUAmanager::startScriptLine(L, lua); + auto future = LLLUAmanager::startScriptLine(lua); // We woke up again ourselves because the coroutine running Lua has // reached the get_event_next() call, which suspends the calling C++ // coroutine (including the Lua code running on it) until we post @@ -356,8 +352,7 @@ namespace tut sendReply(data, data); })); - LuaState L; - auto [count, result] = LLLUAmanager::waitScriptLine(L, lua); + auto [count, result] = LLLUAmanager::waitScriptLine(lua); ensure_equals("Lua script didn't return item", count, 1); ensure_equals("echo failed", result, llsd::map("a", "a", "b", "b")); } @@ -371,18 +366,18 @@ namespace tut "\n" "fiber = require('fiber')\n" "leap = require('leap')\n" - "-- debug = require('printf')\n" "local function debug(...) end\n" + "-- debug = require('printf')\n" "\n" "-- negative priority ensures catchall is always last\n" - "catchall = leap.WaitFor:new(-1, 'catchall')\n" + "catchall = leap.WaitFor(-1, 'catchall')\n" "function catchall:filter(pump, data)\n" " debug('catchall:filter(%s, %s)', pump, data)\n" " return data\n" "end\n" "\n" "-- but first, catch events with 'special' key\n" - "catch_special = leap.WaitFor:new(2, 'catch_special')\n" + "catch_special = leap.WaitFor(2, 'catch_special')\n" "function catch_special:filter(pump, data)\n" " debug('catch_special:filter(%s, %s)', pump, data)\n" " return if data['special'] ~= nil then data else nil\n" @@ -429,10 +424,7 @@ namespace tut requests.append(data); })); - LuaState L; - auto future = LLLUAmanager::startScriptLine(L, lua); - auto replyname{ L.obtainListener().getReplyName() }; - auto& replypump{ LLEventPumps::instance().obtain(replyname) }; + auto future = LLLUAmanager::startScriptLine(lua); // LuaState::expr() periodically interrupts a running chunk to ensure // the rest of our coroutines get cycles. Nonetheless, for this test // we have to wait until both requester() coroutines have posted and @@ -444,6 +436,8 @@ namespace tut llcoro::suspend(); } ensure_equals("didn't get both requests", requests.size(), 2); + auto replyname{ requests[0]["reply"].asString() }; + auto& replypump{ LLEventPumps::instance().obtain(replyname) }; // moreover, we expect they arrived in the order they were created ensure_equals("a wasn't first", requests[0]["name"].asString(), "a"); ensure_equals("b wasn't second", requests[1]["name"].asString(), "b"); @@ -468,8 +462,7 @@ namespace tut "\n" "LL.get_event_next()\n" ); - LuaState L; - auto future = LLLUAmanager::startScriptLine(L, lua); + auto future = LLLUAmanager::startScriptLine(lua); // Poke LLTestApp to send its preliminary shutdown message. mApp.setQuitting(); // but now we have to give the startScriptLine() coroutine a chance to run @@ -491,8 +484,7 @@ namespace tut " x = 1\n" "end\n" ); - LuaState L; - auto [count, result] = LLLUAmanager::waitScriptLine(L, lua); + auto [count, result] = LLLUAmanager::waitScriptLine(lua); // We expect the above erroneous script has been forcibly terminated // because it ran too long without doing any actual work. ensure_equals(desc + " count: " + result.asString(), count, -1); -- cgit v1.2.3 From 35ee96709ef2704a2636a11c67d61190dd6bdd50 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 18 Jul 2024 12:55:38 -0400 Subject: Make `LLEventPump::listen()` also accept new `LLAwareListener`. `listen()` still takes `LLEventListener`, a `callable(const LLSD&)`, but now also accepts `LLAwareListener`, a `callable(const LLBoundListener&, const LLSD&)`. This uses `boost::signals2::signal::connect_extended()`, which, when the signal is called, passes to a connected listener the `LLBoundListener` (aka `boost::signals2::connection`) representing its own connection. This allows a listener to disconnect itself when done. Internally, `listen_impl()` now always uses `connect_extended()`. When passed a classic `LLEventListener`, `listen()` wraps it in a lambda that ignores the passed `LLBoundListener`. `listen()` also now accepts `LLVoidListener`, and internally wraps it in a lambda that returns `false` on its behalf. --- indra/newview/tests/llluamanager_test.cpp | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index 26a4ac95e3..3209d93d39 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -42,17 +42,6 @@ public: LLControlGroup gSavedSettings("Global"); -template -auto listener(CALLABLE&& callable) -{ - return [callable=std::forward(callable)] - (const LLSD& data) - { - callable(data); - return false; - }; -} - /***************************************************************************** * TUT *****************************************************************************/ @@ -138,7 +127,7 @@ namespace tut { LLSD fromlua; LLStreamListener pump("testpump", - listener([&fromlua](const LLSD& data){ fromlua = data; })); + [&fromlua](const LLSD& data){ fromlua = data; }); const std::string lua(stringize( "data = ", construct, "\n" "LL.post_on('testpump', data)\n" @@ -167,8 +156,8 @@ namespace tut set_test_name("test post_on(), get_event_pumps(), get_event_next()"); StringVec posts; LLStreamListener pump("testpump", - listener([&posts](const LLSD& data) - { posts.push_back(data.asString()); })); + [&posts](const LLSD& data) + { posts.push_back(data.asString()); }); const std::string lua( "-- test post_on,get_event_pumps,get_event_next\n" "LL.post_on('testpump', 'entry')\n" @@ -346,11 +335,11 @@ namespace tut LLStreamListener pump( "echo", - listener([](const LLSD& data) + [](const LLSD& data) { LL_DEBUGS("Lua") << "echo pump got: " << data << LL_ENDL; sendReply(data, data); - })); + }); auto [count, result] = LLLUAmanager::waitScriptLine(lua); ensure_equals("Lua script didn't return item", count, 1); @@ -424,11 +413,11 @@ namespace tut LLSD requests; LLStreamListener pump( "testpump", - listener([&requests](const LLSD& data) + [&requests](const LLSD& data) { LL_DEBUGS("Lua") << "testpump got: " << data << LL_ENDL; requests.append(data); - })); + }); auto future = LLLUAmanager::startScriptLine(lua); // LuaState::expr() periodically interrupts a running chunk to ensure -- cgit v1.2.3 From ed388f61bad7f6873ee3a2e4d673c9b991b4ef88 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Mon, 29 Jul 2024 16:51:37 +0300 Subject: Update expired cert in integration test (#2140) see fe8c976 for more info Co-authored-by: Andrey Lihatskiy --- indra/newview/tests/llsechandler_basic_test.cpp | 670 ++++++++++++------------ 1 file changed, 345 insertions(+), 325 deletions(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llsechandler_basic_test.cpp b/indra/newview/tests/llsechandler_basic_test.cpp index bfe32406cb..cf37a4713c 100644 --- a/indra/newview/tests/llsechandler_basic_test.cpp +++ b/indra/newview/tests/llsechandler_basic_test.cpp @@ -232,381 +232,402 @@ namespace tut "Certificate:\n" " Data:\n" " Version: 3 (0x2)\n" - " Serial Number:\n" - " 82:2f:8f:eb:8d:06:24:b0\n" + " Serial Number: ef:54:d8:f7:da:18:e8:19\n" " Signature Algorithm: sha256WithRSAEncryption\n" " Issuer: C=US, ST=California, L=San Francisco, O=Linden Lab, OU=Second Life Engineering, CN=Integration Test Root CA/emailAddress=noreply@lindenlab.com\n" " Validity\n" - " Not Before: May 22 22:19:45 2018 GMT\n" - " Not After : May 17 22:19:45 2038 GMT\n" + " Not Before: Jul 23 11:46:26 2024 GMT\n" + " Not After : Jul 21 11:46:26 2034 GMT\n" " Subject: C=US, ST=California, L=San Francisco, O=Linden Lab, OU=Second Life Engineering, CN=Integration Test Root CA/emailAddress=noreply@lindenlab.com\n" " Subject Public Key Info:\n" " Public Key Algorithm: rsaEncryption\n" " Public-Key: (4096 bit)\n" " Modulus:\n" - " 00:bd:e0:79:dd:3b:a6:ac:87:d0:39:f0:58:c7:a4:\n" - " 42:42:f6:5f:93:b0:36:04:b5:e2:d5:f7:2a:c0:6c:\n" - " a0:13:d2:1e:02:81:57:02:50:4c:57:b7:ef:27:9e:\n" - " f6:f1:f1:30:30:72:1e:57:34:e5:3f:82:3c:21:c4:\n" - " 66:d2:73:63:6c:91:e6:dd:49:9e:9c:b1:34:6a:81:\n" - " 45:a1:6e:c4:50:28:f2:d8:e3:fe:80:2f:83:aa:28:\n" - " 91:b4:8c:57:c9:f1:16:d9:0c:87:3c:25:80:a0:81:\n" - " 8d:71:f2:96:e2:16:f1:97:c4:b0:d8:53:bb:13:6c:\n" - " 73:54:2f:29:94:85:cf:86:6e:75:71:ad:39:e3:fc:\n" - " 39:12:53:93:1c:ce:39:e0:33:da:49:b7:3d:af:b0:\n" - " 37:ce:77:09:03:27:32:70:c0:9c:7f:9c:89:ce:90:\n" - " 45:b0:7d:94:8b:ff:13:27:ba:88:7f:ae:c4:aa:73:\n" - " d5:47:b8:87:69:89:80:0c:c1:22:18:78:c2:0d:47:\n" - " d9:10:ff:80:79:0d:46:71:ec:d9:ba:c9:f3:77:fd:\n" - " 92:6d:1f:0f:d9:54:18:6d:f6:72:24:5c:5c:3d:43:\n" - " 49:35:3e:1c:28:de:7e:44:dc:29:c3:9f:62:04:46:\n" - " aa:c4:e6:69:6a:15:f8:e3:74:1c:14:e9:f4:97:7c:\n" - " 30:6c:d4:28:fc:2a:0e:1d:6d:39:2e:1d:f9:17:43:\n" - " 35:5d:23:e7:ba:e3:a8:e9:97:6b:3c:3e:23:ef:d8:\n" - " bc:fb:7a:57:37:39:93:59:03:fc:78:ca:b1:31:ef:\n" - " 26:19:ed:56:e1:63:c3:ad:99:80:5b:47:b5:03:35:\n" - " 5f:fe:6a:a6:21:63:ec:50:fb:4e:c9:f9:ae:a5:66:\n" - " d0:55:33:8d:e6:c5:50:5a:c6:8f:5c:34:45:a7:72:\n" - " da:50:f6:66:4c:19:f5:d1:e4:fb:11:8b:a1:b5:4e:\n" - " 09:43:81:3d:39:28:86:3b:fe:07:28:97:02:b5:3a:\n" - " 07:5f:4a:20:80:1a:7d:a4:8c:f7:6c:f6:c5:9b:f6:\n" - " 61:e5:c7:b0:c3:d5:58:38:7b:bb:47:1e:34:d6:16:\n" - " 55:c5:d2:6c:b0:93:77:b1:90:69:06:b1:53:cb:1b:\n" - " 84:71:cf:b8:87:1b:1e:44:35:b4:2b:bb:04:59:58:\n" - " 0b:e8:93:d8:ae:21:9b:b1:1c:89:30:ae:11:80:77:\n" - " cc:16:f3:d6:35:ed:a1:b3:70:b3:4f:cd:a1:56:99:\n" - " ee:0e:c0:00:a4:09:70:c3:5b:0b:be:a1:07:18:dd:\n" - " c6:f4:6d:8b:58:bc:f9:bb:4b:01:2c:f6:cc:2c:9b:\n" - " 87:0e:b1:4f:9c:10:be:fc:45:e2:a4:ec:7e:fc:ff:\n" - " 45:b8:53\n" + " 00:c6:cc:07:f4:0b:17:06:4d:a6:30:b4:c7:02:6b:\n" + " 9d:a4:47:a6:09:0e:60:1a:32:d4:6b:42:88:ee:c5:\n" + " b9:e9:fb:b5:0b:60:dc:a2:45:92:a5:bb:88:12:fc:\n" + " 42:1a:80:32:79:16:62:7a:97:af:84:28:53:3c:c1:\n" + " f2:68:c0:4e:45:e4:0a:63:f9:34:1d:a2:8b:cc:70:\n" + " df:c6:65:c0:ba:31:32:d2:9d:0c:c8:ce:dc:11:12:\n" + " a4:11:fa:d3:c8:56:e2:31:8a:e3:fb:91:40:da:25:\n" + " 55:d1:f2:75:9b:4d:fa:b8:1f:b5:6d:9b:e1:fe:5d:\n" + " e8:c4:02:79:14:ef:7d:5a:b3:3a:1e:b6:d0:60:2c:\n" + " 90:dc:22:e2:c5:ae:85:1f:b4:9d:7a:20:f8:af:63:\n" + " 56:25:1a:64:f3:9c:3f:9a:cf:68:08:0a:37:db:d0:\n" + " a3:65:26:db:80:82:ff:e0:1b:51:c8:ee:f6:ad:c2:\n" + " b4:f2:ab:d2:e8:85:86:77:28:d0:63:4a:71:78:41:\n" + " e3:8c:7f:71:51:31:af:24:3f:fa:8d:d0:d8:0b:e2:\n" + " 7e:79:33:8a:bb:d2:00:9e:2e:c8:cd:d5:50:92:b8:\n" + " 5c:5a:0b:99:ef:05:39:67:da:be:70:36:51:37:37:\n" + " 20:6f:84:ab:29:11:00:7b:38:32:ba:0b:bc:34:a6:\n" + " b5:c6:a7:f0:c0:25:2d:38:0b:72:40:ab:cf:e6:ff:\n" + " 97:75:ff:e2:a9:3c:2a:57:ce:e4:52:20:8c:de:fe:\n" + " 68:ce:54:85:37:ba:b3:7f:2e:53:58:ea:9b:ac:79:\n" + " 6b:16:65:b8:11:88:5a:46:eb:9e:9e:80:3c:89:91:\n" + " 35:e0:c5:33:45:c8:86:4d:25:51:39:b1:72:97:2b:\n" + " b3:c8:c9:e8:11:cd:32:41:c8:c1:56:22:7e:33:81:\n" + " 85:61:ab:da:9e:6e:5f:24:1c:0f:9b:fa:da:9d:86:\n" + " 1a:66:f6:32:2a:10:80:ea:72:7a:4a:ef:c0:f2:7c:\n" + " 43:02:e6:70:19:6a:e1:02:0a:00:80:51:1c:a3:03:\n" + " 8b:6d:89:9f:91:37:90:d6:d8:9c:73:77:06:9e:bc:\n" + " 95:89:66:ee:43:40:a3:ee:43:a3:f6:2d:43:dd:7b:\n" + " f0:2f:0b:12:37:49:b7:81:5a:e2:54:6d:71:88:ff:\n" + " fe:7e:41:25:35:4c:b4:b9:62:65:dd:9f:1f:7a:06:\n" + " 6e:2b:20:58:78:da:08:66:a8:f1:89:de:8f:7f:5c:\n" + " 5e:c2:72:33:7f:b6:8e:41:4c:26:f6:4c:d4:0e:11:\n" + " 44:da:c7:14:f7:8b:79:4e:53:29:87:15:b1:12:e9:\n" + " 19:2b:54:33:d6:2e:7f:bd:42:20:be:fc:d7:9c:b4:\n" + " 7a:0a:db\n" " Exponent: 65537 (0x10001)\n" " X509v3 extensions:\n" - " X509v3 Subject Key Identifier: \n" - " 8A:22:C6:9C:2E:11:F3:40:0C:CE:82:0C:22:59:FF:F8:7F:D0:B9:13\n" - " X509v3 Authority Key Identifier: \n" - " keyid:8A:22:C6:9C:2E:11:F3:40:0C:CE:82:0C:22:59:FF:F8:7F:D0:B9:13\n" + " X509v3 Subject Key Identifier:\n" + " 4D:7D:AE:0D:A5:5E:22:5A:6A:8F:19:61:54:B3:58:CB:7B:C0:BD:DA\n" + " X509v3 Authority Key Identifier:\n" + " keyid:4D:7D:AE:0D:A5:5E:22:5A:6A:8F:19:61:54:B3:58:CB:7B:C0:BD:DA\n" "\n" - " X509v3 Basic Constraints: critical\n" + " X509v3 Basic Constraints:\n" " CA:TRUE\n" - " X509v3 Key Usage: critical\n" - " Digital Signature, Certificate Sign, CRL Sign\n" " Signature Algorithm: sha256WithRSAEncryption\n" - " b3:cb:33:eb:0e:02:64:f4:55:9a:3d:03:9a:cf:6a:4c:18:43:\n" - " f7:42:cb:65:dc:61:52:e5:9f:2f:42:97:3c:93:16:22:d4:af:\n" - " ae:b2:0f:c3:9b:ef:e0:cc:ee:b6:b1:69:a3:d8:da:26:c3:ad:\n" - " 3b:c5:64:dc:9f:d4:c2:53:4b:91:6d:c4:92:09:0b:ac:f0:99:\n" - " be:6f:b9:3c:03:4a:6d:9f:01:5d:ec:5a:9a:f3:a7:e5:3b:2c:\n" - " 99:57:7d:7e:25:15:68:20:12:30:96:16:86:f5:db:74:90:60:\n" - " fe:8b:df:99:f6:f7:62:49:9f:bc:8d:45:23:0a:c8:73:b8:79:\n" - " 80:3c:b9:e5:72:85:4b:b3:81:66:74:a2:72:92:4c:44:fd:7b:\n" - " 46:2e:21:a2:a9:81:a2:f3:26:4d:e3:89:7d:78:b0:c6:6f:b5:\n" - " 87:cb:ee:25:ed:27:1f:75:13:fa:6d:e9:37:73:ad:07:bb:af:\n" - " d3:6c:87:ea:02:01:70:bd:53:aa:ce:39:2c:d4:66:39:33:aa:\n" - " d1:9c:ee:67:e3:a9:45:d2:7b:2e:54:09:af:70:5f:3f:5a:67:\n" - " 2e:6c:72:ef:e0:9d:92:28:4a:df:ba:0b:b7:23:ca:5b:04:11:\n" - " 45:d1:51:e9:ea:c9:ec:54:fa:34:46:ae:fc:dc:6c:f8:1e:2c:\n" - " 9e:f4:71:51:8d:b5:a1:26:9a:13:30:be:1e:41:25:59:58:05:\n" - " 2c:64:c8:f9:5e:38:ae:dc:93:b0:8a:d6:38:74:02:cb:ce:ce:\n" - " 95:31:76:f6:7c:bf:a4:a1:8e:27:fd:ca:74:82:d1:e1:4d:b6:\n" - " 48:51:fa:c5:17:59:22:a3:84:be:82:c8:83:ec:61:a0:f4:ee:\n" - " 2c:e3:a3:ea:e5:51:c9:d3:4f:db:85:bd:ba:7a:52:14:b6:03:\n" - " ed:43:17:d8:d7:1c:22:5e:c9:56:d9:d6:81:96:11:e3:5e:01:\n" - " 40:91:30:09:da:a3:5f:d3:27:60:e5:9d:6c:da:d0:f0:39:01:\n" - " 23:4a:a6:15:7a:4a:82:eb:ec:72:4a:1d:36:dc:6f:83:c4:85:\n" - " 84:b5:8d:cd:09:e5:12:63:f3:21:56:c8:64:6b:db:b8:cf:d4:\n" - " df:ca:a8:24:8e:df:8d:63:a5:96:84:bf:ff:8b:7e:46:7a:f0:\n" - " c7:73:7c:70:8a:f5:17:d0:ac:c8:89:1e:d7:89:42:0f:4d:66:\n" - " c4:d8:bb:36:a8:ae:ca:e1:cf:e2:88:f6:cf:b0:44:4a:5f:81:\n" - " 50:4b:d6:28:81:cd:6c:f0:ec:e6:09:08:f2:59:91:a2:69:ac:\n" - " c7:81:fa:ab:61:3e:db:6f:f6:7f:db:1a:9e:b9:5d:cc:cc:33:\n" - " fa:95:c6:f7:8d:4b:30:f3\n" + " 5b:40:71:96:c8:d1:57:3f:fc:f2:3c:75:fb:c9:a6:a7:63:8a:\n" + " 22:23:96:0f:40:77:77:e2:7f:76:fc:5f:7b:1c:bd:ea:ca:f0:\n" + " be:1a:fd:59:e6:0e:00:d1:78:44:01:28:f4:01:68:67:78:cf:\n" + " 78:43:36:ac:b2:5c:13:0e:2a:94:59:88:9e:64:46:42:0a:9b:\n" + " be:7d:2d:10:11:fe:8b:64:01:fb:00:c5:2e:47:63:c0:93:3a:\n" + " 4a:f8:6c:fc:a9:16:58:ab:bc:7b:6b:20:31:9d:d7:d8:84:01:\n" + " cc:ce:52:7f:a1:18:2f:5c:c9:59:58:9a:98:b9:ef:54:d7:a0:\n" + " 56:79:28:ba:ad:f5:e5:fd:7e:d8:d6:be:dd:25:76:6f:fa:8a:\n" + " 07:f6:8e:0f:83:43:19:ee:96:c4:c9:54:df:19:5a:4c:ae:25:\n" + " 57:a2:5d:d5:e8:0a:66:d8:19:e9:c4:44:ba:6a:3b:b3:86:ae:\n" + " 44:c0:7c:6e:e5:a0:6c:45:bb:7f:34:94:e9:d3:d4:f4:04:0b:\n" + " eb:fc:9a:fa:67:d4:e5:83:5e:08:09:9c:70:a9:d3:0d:8a:08:\n" + " ed:3c:04:33:4f:ac:02:d9:5c:99:62:12:fc:0e:8d:55:8a:ce:\n" + " ca:28:5a:1a:9e:c9:59:8e:f0:f5:19:c7:30:1e:59:1f:3c:77:\n" + " 6d:fc:a2:31:ec:bf:83:fd:14:26:91:68:88:05:4c:87:82:e0:\n" + " 33:f4:ee:d8:56:97:23:3a:00:9b:e7:a2:10:c2:83:28:c6:c0:\n" + " c1:92:49:95:c1:d3:e1:43:e8:8f:0c:d0:ae:e3:50:17:1a:8d:\n" + " 0f:4a:60:71:76:8e:9e:fb:15:76:cd:cd:69:2c:59:24:69:d2:\n" + " 0f:f2:d5:0e:96:95:2b:2e:d7:81:ed:b3:7b:6f:ce:60:32:b5:\n" + " f0:f6:74:ea:27:3a:ee:2c:96:7b:e0:06:6c:33:25:c4:60:da:\n" + " 76:de:c4:a1:22:b6:b1:63:57:10:3c:62:60:98:47:39:9e:38:\n" + " ce:c7:ef:75:75:19:d3:26:2a:cf:46:e3:b0:72:38:49:ee:c3:\n" + " 4e:52:97:e5:e5:b8:bc:b1:45:56:98:54:0a:63:c8:87:ff:a0:\n" + " cb:28:12:5c:8f:a2:6e:a7:f9:50:98:2d:a5:26:08:df:16:29:\n" + " 19:63:7f:6c:b4:41:20:f7:5d:ef:6a:90:fd:1a:08:1c:c2:4c:\n" + " 3e:77:ea:e0:df:c0:dd:aa:a2:36:e7:e8:be:98:39:0a:68:59:\n" + " 8e:a0:71:2f:7c:92:ab:e0:c4:c1:c2:eb:89:b6:34:ce:44:ab:\n" + " f9:f6:a4:c8:7b:ad:a8:bc:c9:04:7c:d5:4c:a4:d2:8b:54:23:\n" + " 89:68:86:4e:07:36:d9:bc\n" "-----BEGIN CERTIFICATE-----\n" - "MIIGXDCCBESgAwIBAgIJAIIvj+uNBiSwMA0GCSqGSIb3DQEBCwUAMIG6MQswCQYD\n" + "MIIGSTCCBDGgAwIBAgIJAO9U2PfaGOgZMA0GCSqGSIb3DQEBCwUAMIG6MQswCQYD\n" "VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5j\n" "aXNjbzETMBEGA1UECgwKTGluZGVuIExhYjEgMB4GA1UECwwXU2Vjb25kIExpZmUg\n" "RW5naW5lZXJpbmcxITAfBgNVBAMMGEludGVncmF0aW9uIFRlc3QgUm9vdCBDQTEk\n" - "MCIGCSqGSIb3DQEJARYVbm9yZXBseUBsaW5kZW5sYWIuY29tMB4XDTE4MDUyMjIy\n" - "MTk0NVoXDTM4MDUxNzIyMTk0NVowgboxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApD\n" + "MCIGCSqGSIb3DQEJARYVbm9yZXBseUBsaW5kZW5sYWIuY29tMB4XDTI0MDcyMzEx\n" + "NDYyNloXDTM0MDcyMTExNDYyNlowgboxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApD\n" "YWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRMwEQYDVQQKDApMaW5k\n" "ZW4gTGFiMSAwHgYDVQQLDBdTZWNvbmQgTGlmZSBFbmdpbmVlcmluZzEhMB8GA1UE\n" "AwwYSW50ZWdyYXRpb24gVGVzdCBSb290IENBMSQwIgYJKoZIhvcNAQkBFhVub3Jl\n" "cGx5QGxpbmRlbmxhYi5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC\n" - "AQC94HndO6ash9A58FjHpEJC9l+TsDYEteLV9yrAbKAT0h4CgVcCUExXt+8nnvbx\n" - "8TAwch5XNOU/gjwhxGbSc2NskebdSZ6csTRqgUWhbsRQKPLY4/6AL4OqKJG0jFfJ\n" - "8RbZDIc8JYCggY1x8pbiFvGXxLDYU7sTbHNULymUhc+GbnVxrTnj/DkSU5Mczjng\n" - "M9pJtz2vsDfOdwkDJzJwwJx/nInOkEWwfZSL/xMnuoh/rsSqc9VHuIdpiYAMwSIY\n" - "eMINR9kQ/4B5DUZx7Nm6yfN3/ZJtHw/ZVBht9nIkXFw9Q0k1Phwo3n5E3CnDn2IE\n" - "RqrE5mlqFfjjdBwU6fSXfDBs1Cj8Kg4dbTkuHfkXQzVdI+e646jpl2s8PiPv2Lz7\n" - "elc3OZNZA/x4yrEx7yYZ7VbhY8OtmYBbR7UDNV/+aqYhY+xQ+07J+a6lZtBVM43m\n" - "xVBaxo9cNEWnctpQ9mZMGfXR5PsRi6G1TglDgT05KIY7/gcolwK1OgdfSiCAGn2k\n" - "jPds9sWb9mHlx7DD1Vg4e7tHHjTWFlXF0mywk3exkGkGsVPLG4Rxz7iHGx5ENbQr\n" - "uwRZWAvok9iuIZuxHIkwrhGAd8wW89Y17aGzcLNPzaFWme4OwACkCXDDWwu+oQcY\n" - "3cb0bYtYvPm7SwEs9swsm4cOsU+cEL78ReKk7H78/0W4UwIDAQABo2MwYTAdBgNV\n" - "HQ4EFgQUiiLGnC4R80AMzoIMIln/+H/QuRMwHwYDVR0jBBgwFoAUiiLGnC4R80AM\n" - "zoIMIln/+H/QuRMwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJ\n" - "KoZIhvcNAQELBQADggIBALPLM+sOAmT0VZo9A5rPakwYQ/dCy2XcYVLlny9ClzyT\n" - "FiLUr66yD8Ob7+DM7raxaaPY2ibDrTvFZNyf1MJTS5FtxJIJC6zwmb5vuTwDSm2f\n" - "AV3sWprzp+U7LJlXfX4lFWggEjCWFob123SQYP6L35n292JJn7yNRSMKyHO4eYA8\n" - "ueVyhUuzgWZ0onKSTET9e0YuIaKpgaLzJk3jiX14sMZvtYfL7iXtJx91E/pt6Tdz\n" - "rQe7r9Nsh+oCAXC9U6rOOSzUZjkzqtGc7mfjqUXSey5UCa9wXz9aZy5scu/gnZIo\n" - "St+6C7cjylsEEUXRUenqyexU+jRGrvzcbPgeLJ70cVGNtaEmmhMwvh5BJVlYBSxk\n" - "yPleOK7ck7CK1jh0AsvOzpUxdvZ8v6Shjif9ynSC0eFNtkhR+sUXWSKjhL6CyIPs\n" - "YaD07izjo+rlUcnTT9uFvbp6UhS2A+1DF9jXHCJeyVbZ1oGWEeNeAUCRMAnao1/T\n" - "J2DlnWza0PA5ASNKphV6SoLr7HJKHTbcb4PEhYS1jc0J5RJj8yFWyGRr27jP1N/K\n" - "qCSO341jpZaEv/+LfkZ68MdzfHCK9RfQrMiJHteJQg9NZsTYuzaorsrhz+KI9s+w\n" - "REpfgVBL1iiBzWzw7OYJCPJZkaJprMeB+qthPttv9n/bGp65XczMM/qVxveNSzDz\n" + "AQDGzAf0CxcGTaYwtMcCa52kR6YJDmAaMtRrQojuxbnp+7ULYNyiRZKlu4gS/EIa\n" + "gDJ5FmJ6l6+EKFM8wfJowE5F5Apj+TQdoovMcN/GZcC6MTLSnQzIztwREqQR+tPI\n" + "VuIxiuP7kUDaJVXR8nWbTfq4H7Vtm+H+XejEAnkU731aszoettBgLJDcIuLFroUf\n" + "tJ16IPivY1YlGmTznD+az2gICjfb0KNlJtuAgv/gG1HI7vatwrTyq9LohYZ3KNBj\n" + "SnF4QeOMf3FRMa8kP/qN0NgL4n55M4q70gCeLsjN1VCSuFxaC5nvBTln2r5wNlE3\n" + "NyBvhKspEQB7ODK6C7w0prXGp/DAJS04C3JAq8/m/5d1/+KpPCpXzuRSIIze/mjO\n" + "VIU3urN/LlNY6puseWsWZbgRiFpG656egDyJkTXgxTNFyIZNJVE5sXKXK7PIyegR\n" + "zTJByMFWIn4zgYVhq9qebl8kHA+b+tqdhhpm9jIqEIDqcnpK78DyfEMC5nAZauEC\n" + "CgCAURyjA4ttiZ+RN5DW2JxzdwaevJWJZu5DQKPuQ6P2LUPde/AvCxI3SbeBWuJU\n" + "bXGI//5+QSU1TLS5YmXdnx96Bm4rIFh42ghmqPGJ3o9/XF7CcjN/to5BTCb2TNQO\n" + "EUTaxxT3i3lOUymHFbES6RkrVDPWLn+9QiC+/NectHoK2wIDAQABo1AwTjAdBgNV\n" + "HQ4EFgQUTX2uDaVeIlpqjxlhVLNYy3vAvdowHwYDVR0jBBgwFoAUTX2uDaVeIlpq\n" + "jxlhVLNYy3vAvdowDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAW0Bx\n" + "lsjRVz/88jx1+8mmp2OKIiOWD0B3d+J/dvxfexy96srwvhr9WeYOANF4RAEo9AFo\n" + "Z3jPeEM2rLJcEw4qlFmInmRGQgqbvn0tEBH+i2QB+wDFLkdjwJM6Svhs/KkWWKu8\n" + "e2sgMZ3X2IQBzM5Sf6EYL1zJWViamLnvVNegVnkouq315f1+2Na+3SV2b/qKB/aO\n" + "D4NDGe6WxMlU3xlaTK4lV6Jd1egKZtgZ6cREumo7s4auRMB8buWgbEW7fzSU6dPU\n" + "9AQL6/ya+mfU5YNeCAmccKnTDYoI7TwEM0+sAtlcmWIS/A6NVYrOyihaGp7JWY7w\n" + "9RnHMB5ZHzx3bfyiMey/g/0UJpFoiAVMh4LgM/Tu2FaXIzoAm+eiEMKDKMbAwZJJ\n" + "lcHT4UPojwzQruNQFxqND0pgcXaOnvsVds3NaSxZJGnSD/LVDpaVKy7Xge2ze2/O\n" + "YDK18PZ06ic67iyWe+AGbDMlxGDadt7EoSK2sWNXEDxiYJhHOZ44zsfvdXUZ0yYq\n" + "z0bjsHI4Se7DTlKX5eW4vLFFVphUCmPIh/+gyygSXI+ibqf5UJgtpSYI3xYpGWN/\n" + "bLRBIPdd72qQ/RoIHMJMPnfq4N/A3aqiNufovpg5CmhZjqBxL3ySq+DEwcLribY0\n" + "zkSr+fakyHutqLzJBHzVTKTSi1QjiWiGTgc22bw=\n" "-----END CERTIFICATE-----\n" - ); + ); + const std::string mPemIntermediateCert( "Certificate:\n" " Data:\n" " Version: 3 (0x2)\n" - " Serial Number: 4096 (0x1000)\n" + " Serial Number: 85:bb:4b:66:26:db:9a:c6\n" " Signature Algorithm: sha256WithRSAEncryption\n" " Issuer: C=US, ST=California, L=San Francisco, O=Linden Lab, OU=Second Life Engineering, CN=Integration Test Root CA/emailAddress=noreply@lindenlab.com\n" " Validity\n" - " Not Before: May 22 22:39:08 2018 GMT\n" - " Not After : May 19 22:39:08 2028 GMT\n" - " Subject: C=US, ST=California, O=Linden Lab, OU=Second Life Engineering, CN=Integration Test Intermediate CA/emailAddress=noreply@lindenlab.com\n" + " Not Before: Jul 23 11:46:33 2024 GMT\n" + " Not After : Jul 21 11:46:33 2034 GMT\n" + " Subject: C=US, ST=California, L=San Francisco, O=Linden Lab, OU=Second Life Engineering, CN=Integration Test Intermediate CA/emailAddress=noreply@lindenlab.com\n" " Subject Public Key Info:\n" " Public Key Algorithm: rsaEncryption\n" " Public-Key: (4096 bit)\n" " Modulus:\n" - " 00:ce:a3:70:e2:c4:fb:4b:97:90:a1:30:bb:c1:1b:\n" - " 13:b9:aa:7e:46:17:a3:26:8d:69:3f:5e:73:95:e8:\n" - " 6a:b1:0a:b4:8f:50:65:e3:c6:5c:39:24:34:df:0b:\n" - " b7:cc:ce:62:0c:36:5a:12:2c:fe:35:4c:e9:1c:ac:\n" - " 80:5e:24:99:d7:aa:bd:be:48:c0:62:64:77:36:88:\n" - " 66:ce:f4:a8:dd:d2:76:24:62:90:55:41:fc:1d:13:\n" - " 4e:a7:4e:57:bc:a8:a4:59:4b:2c:5a:1c:d8:cc:16:\n" - " de:e8:88:30:c9:95:df:2f:a6:14:28:0f:eb:34:46:\n" - " 12:58:ba:da:0e:e6:de:9c:15:f6:f4:e3:9f:74:aa:\n" - " 70:89:79:8b:e9:5a:7b:18:54:15:94:3a:23:0a:65:\n" - " 78:05:d9:33:90:2a:ce:15:18:0d:52:fc:5c:31:65:\n" - " 20:d0:12:37:8c:11:80:ba:d4:b0:82:73:00:4b:49:\n" - " be:cb:d6:bc:e7:cd:61:f3:00:98:99:74:5a:37:81:\n" - " 49:96:7e:14:01:1b:86:d2:d0:06:94:40:63:63:46:\n" - " 11:fc:33:5c:bd:3a:5e:d4:e5:44:47:64:50:bd:a6:\n" - " 97:55:70:64:9b:26:cc:de:20:82:90:6a:83:41:9c:\n" - " 6f:71:47:14:be:cb:68:7c:85:be:ef:2e:76:12:19:\n" - " d3:c9:87:32:b4:ac:60:20:16:28:2d:af:bc:e8:01:\n" - " c6:7f:fb:d8:11:d5:f4:b7:14:bd:27:08:5b:72:be:\n" - " 09:e0:91:c8:9c:7b:b4:b3:12:ef:32:36:be:b1:b9:\n" - " a2:b7:e3:69:47:30:76:ba:9c:9b:19:99:4d:53:dd:\n" - " 5c:e8:2c:f1:b2:64:69:cf:15:bd:f8:bb:58:95:73:\n" - " 58:38:95:b4:7a:cf:84:29:a6:c2:db:f0:bd:ef:97:\n" - " 26:d4:99:ac:d7:c7:be:b0:0d:11:f4:26:86:2d:77:\n" - " 42:52:25:d7:56:c7:e3:97:b1:36:5c:97:71:d0:9b:\n" - " f5:b5:50:8d:f9:ff:fb:10:77:3c:b5:53:6d:a1:43:\n" - " 35:a9:03:32:05:ab:d7:f5:d1:19:bd:5f:92:a3:00:\n" - " 2a:79:37:a4:76:4f:e9:32:0d:e4:86:bb:ea:c3:1a:\n" - " c5:33:e8:16:d4:a5:d8:e0:e8:bb:c2:f0:22:15:e2:\n" - " d9:8c:ae:ac:7d:2b:bf:eb:a3:4c:3b:29:1d:94:ac:\n" - " a3:bb:6d:ba:6d:03:91:03:cf:46:12:c4:66:21:c5:\n" - " c6:67:d8:11:19:79:01:0e:6e:84:1c:76:6f:11:3d:\n" - " eb:94:89:c5:6a:26:1f:cd:e0:11:8b:51:ee:99:35:\n" - " 69:e5:7f:0b:77:2a:94:e4:4b:64:b9:83:04:30:05:\n" - " e4:a2:e3\n" + " 00:be:f7:d2:cb:e4:5c:46:7b:e2:11:22:89:72:da:\n" + " 77:72:ec:05:87:19:f7:77:07:fd:67:d7:af:13:d5:\n" + " 76:12:92:dd:69:4d:22:47:b0:3d:94:8a:6a:95:85:\n" + " 34:b8:78:c3:9d:63:32:b1:4b:0a:b6:0e:05:7b:ab:\n" + " 06:23:fc:0d:21:b5:fc:c6:6a:5a:36:be:6e:fc:c7:\n" + " 47:97:a3:18:2e:33:cd:0e:8a:75:2b:b7:29:e9:68:\n" + " 4a:90:53:45:db:73:ff:b3:e5:c1:d4:6b:dd:3a:b1:\n" + " ef:53:9f:23:e9:c6:87:ce:67:b9:fb:a4:d5:76:21:\n" + " 03:cb:c5:72:6b:c5:a6:07:55:fb:47:90:e8:92:38:\n" + " 73:14:11:8e:ff:21:b9:35:64:5a:61:c7:fc:1f:e4:\n" + " 4d:47:e5:03:cc:0b:c3:69:66:71:84:0c:18:2f:61:\n" + " 7f:34:dd:f2:91:e3:b7:9d:a8:b8:db:3f:6e:6f:96:\n" + " fa:34:06:82:04:c8:18:cc:de:8b:7f:26:b5:48:53:\n" + " fb:fb:15:7b:0e:38:60:fe:da:21:98:8d:73:07:b2:\n" + " 6b:fd:ad:21:59:e7:84:66:e1:04:16:1c:be:13:34:\n" + " 28:43:2c:09:3d:e4:77:2a:a4:ad:6d:f9:26:04:f7:\n" + " 43:73:9b:d9:ea:1a:43:6a:b4:db:88:f8:f9:bd:34:\n" + " f8:a6:e8:7a:ab:b4:b2:e1:29:47:a6:ba:b8:65:9c:\n" + " c6:b3:af:13:43:38:ef:2a:05:77:9f:8f:f0:0c:56:\n" + " 21:c2:92:d2:2c:c3:32:50:d1:62:ae:51:fc:99:e6:\n" + " b8:38:f8:83:1d:8d:40:11:e0:1d:51:5d:3f:fa:55:\n" + " 61:b6:18:09:1e:71:af:95:64:9c:ea:c6:11:64:f0:\n" + " a8:02:7d:bb:c8:54:2e:57:48:32:7c:51:66:0d:d6:\n" + " 3e:0e:ed:5e:30:a8:a6:47:03:64:5c:89:21:45:90:\n" + " e1:4c:91:bc:bd:81:6e:73:a9:14:27:e6:0d:6d:38:\n" + " dc:50:9d:b2:56:66:60:6c:66:b9:5d:bb:8c:96:2d:\n" + " 89:5e:0d:2b:ed:b8:03:31:ce:0a:ff:82:03:f5:b2:\n" + " 3b:e5:27:de:61:d8:8f:bf:a2:6a:64:b0:4a:87:23:\n" + " 40:28:a3:f1:ec:96:50:cd:83:50:2d:78:71:92:f2:\n" + " 88:75:b0:9d:cd:0b:e4:62:a6:a5:63:11:fc:b4:ba:\n" + " 9f:c6:67:40:2c:ad:a4:ef:94:f0:f9:a0:ba:e1:52:\n" + " 2e:27:d9:6b:1d:82:23:ed:3c:0b:0b:d2:bc:14:be:\n" + " 6d:b1:69:ad:3e:25:3a:66:d2:d1:af:9f:88:45:25:\n" + " 6b:6e:be:1f:a0:e7:b2:9f:6d:24:94:0d:f4:c2:75:\n" + " f9:1f:5d\n" " Exponent: 65537 (0x10001)\n" " X509v3 extensions:\n" - " X509v3 Subject Key Identifier: \n" - " 83:21:DE:EC:C0:79:03:6D:1E:83:F3:E5:97:29:D5:5A:C0:96:40:FA\n" - " X509v3 Authority Key Identifier: \n" - " keyid:8A:22:C6:9C:2E:11:F3:40:0C:CE:82:0C:22:59:FF:F8:7F:D0:B9:13\n" - "\n" - " X509v3 Basic Constraints: critical\n" + " X509v3 Basic Constraints:\n" " CA:TRUE, pathlen:0\n" - " X509v3 Key Usage: critical\n" + " X509v3 Key Usage:\n" " Digital Signature, Certificate Sign, CRL Sign\n" + " X509v3 Subject Key Identifier:\n" + " 56:98:DC:45:25:11:E2:8C:2B:EA:D6:C6:E2:C8:BE:2C:C8:69:FF:FF\n" + " X509v3 Authority Key Identifier:\n" + " keyid:4D:7D:AE:0D:A5:5E:22:5A:6A:8F:19:61:54:B3:58:CB:7B:C0:BD:DA\n" + " DirName:/C=US/ST=California/L=San Francisco/O=Linden Lab/OU=Second Life Engineering/CN=Integration Test Root CA/emailAddress=noreply@lindenlab.com\n" + " serial:EF:54:D8:F7:DA:18:E8:19\n" " Signature Algorithm: sha256WithRSAEncryption\n" - " a3:6c:85:9a:2e:4e:7e:5d:83:63:0f:f5:4f:a9:7d:ec:0e:6f:\n" - " ae:d7:ba:df:64:e0:46:0e:3d:da:18:15:2c:f3:73:ca:81:b1:\n" - " 10:d9:53:14:21:7d:72:5c:94:88:a5:9d:ad:ab:45:42:c6:64:\n" - " a9:d9:2e:4e:29:47:2c:b1:95:07:b7:62:48:68:1f:68:13:1c:\n" - " d2:a0:fb:5e:38:24:4a:82:0a:87:c9:93:20:43:7e:e9:f9:79:\n" - " ef:03:a2:bd:9e:24:6b:0a:01:5e:4a:36:c5:7d:7a:fe:d6:aa:\n" - " 2f:c2:8c:38:8a:99:3c:b0:6a:e5:60:be:56:d6:eb:60:03:55:\n" - " 24:42:a0:1a:fa:91:24:a3:53:15:75:5d:c8:eb:7c:1e:68:5a:\n" - " 7e:13:34:e3:85:37:1c:76:3f:77:67:1b:ed:1b:52:17:fc:4a:\n" - " a3:e2:74:84:80:2c:69:fc:dd:7d:26:97:c4:2a:69:7d:9c:dc:\n" - " 61:97:70:29:a7:3f:2b:5b:2b:22:51:fd:fe:6a:5d:f9:e7:14:\n" - " 48:b7:2d:c8:33:58:fc:f2:5f:27:f7:26:16:be:be:b5:aa:a2:\n" - " 64:53:3c:69:e8:b5:61:eb:ab:91:a5:b4:09:9b:f6:98:b8:5c:\n" - " 5b:24:2f:93:f5:2b:9c:8c:58:fb:26:3f:67:53:d7:42:64:e8:\n" - " 79:77:73:41:4e:e3:02:39:0b:b6:68:97:8b:84:e8:1d:83:a8:\n" - " 15:f1:06:46:47:80:42:5e:14:e2:61:8a:76:84:d5:d4:71:7f:\n" - " 4e:ff:d9:74:87:ff:32:c5:87:20:0a:d4:59:40:3e:d8:17:ef:\n" - " da:65:e9:0a:51:fe:1e:c3:46:91:d2:ee:e4:23:57:97:87:d4:\n" - " a6:a5:eb:ef:81:6a:d8:8c:d6:1f:8e:b1:18:4c:6b:89:32:55:\n" - " 53:68:26:9e:bb:03:be:2c:e9:8b:ff:97:9c:1c:ac:28:c3:9f:\n" - " 0b:b7:93:23:24:31:63:e4:19:13:f2:bb:08:71:b7:c5:c5:c4:\n" - " 10:ff:dc:fc:33:54:a4:5e:ec:a3:fe:0a:80:ca:9c:bc:95:6f:\n" - " 5f:39:91:3b:61:69:16:94:0f:57:4b:fc:4b:b1:be:72:98:5d:\n" - " 10:f9:08:a7:d6:e0:e8:3d:5d:54:7d:fa:4b:6a:dd:98:41:ed:\n" - " 84:a1:39:67:5c:6c:7f:0c:b0:e1:98:c1:14:ed:fe:1e:e8:05:\n" - " 8d:7f:6a:24:cb:1b:05:42:0d:7f:13:ba:ca:b5:91:db:a5:f0:\n" - " 40:2b:70:7a:2a:a5:5d:ed:56:0c:f0:c2:72:ee:63:dd:cb:5d:\n" - " 76:f6:08:e6:e6:30:ef:3a:b2:16:34:41:a4:e1:30:14:bc:c7:\n" - " f9:23:3a:1a:70:df:b8:cc\n" + " ae:d0:30:ac:31:49:20:86:0b:34:01:58:08:94:68:cc:38:9c:\n" + " f7:13:5c:46:19:33:ed:54:5e:e4:43:f3:59:33:5c:50:d9:89:\n" + " 8b:ee:75:67:a8:c7:0e:d1:30:c2:4e:a3:2e:a8:64:2d:6a:a8:\n" + " f4:bd:b1:32:dc:bc:46:48:5d:1a:18:d8:e8:0b:8c:fe:7b:51:\n" + " d9:dd:b9:e3:4b:d1:f9:e0:22:46:dd:37:5b:b2:cb:72:8e:9c:\n" + " 4b:da:67:df:fd:ce:86:49:21:31:4e:99:b6:d4:38:0b:14:5d:\n" + " ad:97:ba:8f:e2:08:15:85:73:eb:4a:7d:01:49:af:63:ae:2d:\n" + " e3:9d:0a:d7:11:c2:03:d3:15:21:97:be:3d:d2:ea:ab:cc:93:\n" + " 16:98:64:80:72:eb:c2:78:0a:09:69:c4:2b:5d:df:30:7b:be:\n" + " 9b:02:34:73:62:9f:95:b1:cf:08:e8:9e:57:a8:37:31:cf:2c:\n" + " 8c:18:b1:d5:7a:25:90:d6:b6:76:28:1b:e2:b1:cf:1b:f1:ef:\n" + " dd:2f:d3:07:af:81:e3:5f:fc:5a:e7:3c:a9:37:0d:9c:78:5b:\n" + " 58:dc:89:54:70:a4:5b:ff:9f:64:30:a3:85:12:32:69:a5:02:\n" + " 73:d9:1d:ff:69:1f:d4:97:8f:d0:a8:90:8c:dd:2e:45:a1:b1:\n" + " e3:8a:82:fc:fc:08:41:01:51:92:87:9a:09:7b:35:c3:cc:48:\n" + " 81:39:30:a9:f4:41:3b:06:a3:06:21:cc:4b:bc:1b:76:58:94:\n" + " d1:e4:22:70:7f:20:7e:7a:b4:fa:7f:e8:79:c1:8c:89:9e:e9:\n" + " e3:72:2a:43:72:47:9e:bb:26:ed:64:2c:c8:54:f7:b4:95:c2:\n" + " c4:e9:8b:df:d5:10:a7:ed:a5:7a:94:97:c4:76:45:e3:6c:c0:\n" + " 0e:a6:2a:76:d5:1d:2f:ad:99:32:c6:7b:f6:41:e0:65:37:0f:\n" + " c0:1f:c5:99:4a:75:fd:6c:e0:f1:f0:58:49:2d:81:10:ca:d8:\n" + " eb:2b:c3:9b:a9:d9:a9:f5:6c:6d:26:fd:b8:32:92:58:f4:65:\n" + " 0b:d1:8e:03:1e:d5:6a:95:d4:46:9e:65:dd:e5:85:36:e6:31:\n" + " 77:3a:1a:20:2b:07:b7:f1:9a:4e:8d:54:22:5a:54:1c:72:5c:\n" + " 1f:b4:1a:5b:21:ed:06:5a:9a:e5:3c:01:c9:9b:af:50:61:f2:\n" + " 29:6b:ec:6d:19:bb:2e:02:94:ca:36:71:ef:45:39:f1:a5:25:\n" + " 10:0e:90:bc:a7:b3:5b:ab:af:f1:19:88:6a:09:2f:1f:d0:24:\n" + " a8:62:ed:d9:1a:65:89:65:16:a5:55:de:33:e8:7a:81:66:72:\n" + " 91:17:5e:1d:22:72:f7:b8\n" "-----BEGIN CERTIFICATE-----\n" - "MIIGSDCCBDCgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgboxCzAJBgNVBAYTAlVT\n" - "MRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRMw\n" - "EQYDVQQKDApMaW5kZW4gTGFiMSAwHgYDVQQLDBdTZWNvbmQgTGlmZSBFbmdpbmVl\n" - "cmluZzEhMB8GA1UEAwwYSW50ZWdyYXRpb24gVGVzdCBSb290IENBMSQwIgYJKoZI\n" - "hvcNAQkBFhVub3JlcGx5QGxpbmRlbmxhYi5jb20wHhcNMTgwNTIyMjIzOTA4WhcN\n" - "MjgwNTE5MjIzOTA4WjCBqjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3Ju\n" - "aWExEzARBgNVBAoMCkxpbmRlbiBMYWIxIDAeBgNVBAsMF1NlY29uZCBMaWZlIEVu\n" - "Z2luZWVyaW5nMSkwJwYDVQQDDCBJbnRlZ3JhdGlvbiBUZXN0IEludGVybWVkaWF0\n" - "ZSBDQTEkMCIGCSqGSIb3DQEJARYVbm9yZXBseUBsaW5kZW5sYWIuY29tMIICIjAN\n" - "BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAzqNw4sT7S5eQoTC7wRsTuap+Rhej\n" - "Jo1pP15zlehqsQq0j1Bl48ZcOSQ03wu3zM5iDDZaEiz+NUzpHKyAXiSZ16q9vkjA\n" - "YmR3NohmzvSo3dJ2JGKQVUH8HRNOp05XvKikWUssWhzYzBbe6IgwyZXfL6YUKA/r\n" - "NEYSWLraDubenBX29OOfdKpwiXmL6Vp7GFQVlDojCmV4BdkzkCrOFRgNUvxcMWUg\n" - "0BI3jBGAutSwgnMAS0m+y9a8581h8wCYmXRaN4FJln4UARuG0tAGlEBjY0YR/DNc\n" - "vTpe1OVER2RQvaaXVXBkmybM3iCCkGqDQZxvcUcUvstofIW+7y52EhnTyYcytKxg\n" - "IBYoLa+86AHGf/vYEdX0txS9Jwhbcr4J4JHInHu0sxLvMja+sbmit+NpRzB2upyb\n" - "GZlNU91c6CzxsmRpzxW9+LtYlXNYOJW0es+EKabC2/C975cm1Jms18e+sA0R9CaG\n" - "LXdCUiXXVsfjl7E2XJdx0Jv1tVCN+f/7EHc8tVNtoUM1qQMyBavX9dEZvV+SowAq\n" - "eTekdk/pMg3khrvqwxrFM+gW1KXY4Oi7wvAiFeLZjK6sfSu/66NMOykdlKyju226\n" - "bQORA89GEsRmIcXGZ9gRGXkBDm6EHHZvET3rlInFaiYfzeARi1HumTVp5X8LdyqU\n" - "5EtkuYMEMAXkouMCAwEAAaNmMGQwHQYDVR0OBBYEFIMh3uzAeQNtHoPz5Zcp1VrA\n" - "lkD6MB8GA1UdIwQYMBaAFIoixpwuEfNADM6CDCJZ//h/0LkTMBIGA1UdEwEB/wQI\n" - "MAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQCjbIWa\n" - "Lk5+XYNjD/VPqX3sDm+u17rfZOBGDj3aGBUs83PKgbEQ2VMUIX1yXJSIpZ2tq0VC\n" - "xmSp2S5OKUcssZUHt2JIaB9oExzSoPteOCRKggqHyZMgQ37p+XnvA6K9niRrCgFe\n" - "SjbFfXr+1qovwow4ipk8sGrlYL5W1utgA1UkQqAa+pEko1MVdV3I63weaFp+EzTj\n" - "hTccdj93ZxvtG1IX/Eqj4nSEgCxp/N19JpfEKml9nNxhl3Appz8rWysiUf3+al35\n" - "5xRIty3IM1j88l8n9yYWvr61qqJkUzxp6LVh66uRpbQJm/aYuFxbJC+T9SucjFj7\n" - "Jj9nU9dCZOh5d3NBTuMCOQu2aJeLhOgdg6gV8QZGR4BCXhTiYYp2hNXUcX9O/9l0\n" - "h/8yxYcgCtRZQD7YF+/aZekKUf4ew0aR0u7kI1eXh9SmpevvgWrYjNYfjrEYTGuJ\n" - "MlVTaCaeuwO+LOmL/5ecHKwow58Lt5MjJDFj5BkT8rsIcbfFxcQQ/9z8M1SkXuyj\n" - "/gqAypy8lW9fOZE7YWkWlA9XS/xLsb5ymF0Q+Qin1uDoPV1UffpLat2YQe2EoTln\n" - "XGx/DLDhmMEU7f4e6AWNf2okyxsFQg1/E7rKtZHbpfBAK3B6KqVd7VYM8MJy7mPd\n" - "y1129gjm5jDvOrIWNEGk4TAUvMf5IzoacN+4zA==\n" + "MIIHNjCCBR6gAwIBAgIJAIW7S2Ym25rGMA0GCSqGSIb3DQEBCwUAMIG6MQswCQYD\n" + "VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5j\n" + "aXNjbzETMBEGA1UECgwKTGluZGVuIExhYjEgMB4GA1UECwwXU2Vjb25kIExpZmUg\n" + "RW5naW5lZXJpbmcxITAfBgNVBAMMGEludGVncmF0aW9uIFRlc3QgUm9vdCBDQTEk\n" + "MCIGCSqGSIb3DQEJARYVbm9yZXBseUBsaW5kZW5sYWIuY29tMB4XDTI0MDcyMzEx\n" + "NDYzM1oXDTM0MDcyMTExNDYzM1owgcIxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApD\n" + "YWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRMwEQYDVQQKDApMaW5k\n" + "ZW4gTGFiMSAwHgYDVQQLDBdTZWNvbmQgTGlmZSBFbmdpbmVlcmluZzEpMCcGA1UE\n" + "AwwgSW50ZWdyYXRpb24gVGVzdCBJbnRlcm1lZGlhdGUgQ0ExJDAiBgkqhkiG9w0B\n" + "CQEWFW5vcmVwbHlAbGluZGVubGFiLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP\n" + "ADCCAgoCggIBAL730svkXEZ74hEiiXLad3LsBYcZ93cH/WfXrxPVdhKS3WlNIkew\n" + "PZSKapWFNLh4w51jMrFLCrYOBXurBiP8DSG1/MZqWja+bvzHR5ejGC4zzQ6KdSu3\n" + "KeloSpBTRdtz/7PlwdRr3Tqx71OfI+nGh85nufuk1XYhA8vFcmvFpgdV+0eQ6JI4\n" + "cxQRjv8huTVkWmHH/B/kTUflA8wLw2lmcYQMGC9hfzTd8pHjt52ouNs/bm+W+jQG\n" + "ggTIGMzei38mtUhT+/sVew44YP7aIZiNcweya/2tIVnnhGbhBBYcvhM0KEMsCT3k\n" + "dyqkrW35JgT3Q3Ob2eoaQ2q024j4+b00+Kboequ0suEpR6a6uGWcxrOvE0M47yoF\n" + "d5+P8AxWIcKS0izDMlDRYq5R/JnmuDj4gx2NQBHgHVFdP/pVYbYYCR5xr5VknOrG\n" + "EWTwqAJ9u8hULldIMnxRZg3WPg7tXjCopkcDZFyJIUWQ4UyRvL2BbnOpFCfmDW04\n" + "3FCdslZmYGxmuV27jJYtiV4NK+24AzHOCv+CA/WyO+Un3mHYj7+iamSwSocjQCij\n" + "8eyWUM2DUC14cZLyiHWwnc0L5GKmpWMR/LS6n8ZnQCytpO+U8PmguuFSLifZax2C\n" + "I+08CwvSvBS+bbFprT4lOmbS0a+fiEUla26+H6Dnsp9tJJQN9MJ1+R9dAgMBAAGj\n" + "ggEzMIIBLzAPBgNVHRMECDAGAQH/AgEAMAsGA1UdDwQEAwIBhjAdBgNVHQ4EFgQU\n" + "VpjcRSUR4owr6tbG4si+LMhp//8wge8GA1UdIwSB5zCB5IAUTX2uDaVeIlpqjxlh\n" + "VLNYy3vAvdqhgcCkgb0wgboxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9y\n" + "bmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRMwEQYDVQQKDApMaW5kZW4gTGFi\n" + "MSAwHgYDVQQLDBdTZWNvbmQgTGlmZSBFbmdpbmVlcmluZzEhMB8GA1UEAwwYSW50\n" + "ZWdyYXRpb24gVGVzdCBSb290IENBMSQwIgYJKoZIhvcNAQkBFhVub3JlcGx5QGxp\n" + "bmRlbmxhYi5jb22CCQDvVNj32hjoGTANBgkqhkiG9w0BAQsFAAOCAgEArtAwrDFJ\n" + "IIYLNAFYCJRozDic9xNcRhkz7VRe5EPzWTNcUNmJi+51Z6jHDtEwwk6jLqhkLWqo\n" + "9L2xMty8RkhdGhjY6AuM/ntR2d2540vR+eAiRt03W7LLco6cS9pn3/3OhkkhMU6Z\n" + "ttQ4CxRdrZe6j+IIFYVz60p9AUmvY64t450K1xHCA9MVIZe+PdLqq8yTFphkgHLr\n" + "wngKCWnEK13fMHu+mwI0c2KflbHPCOieV6g3Mc8sjBix1XolkNa2digb4rHPG/Hv\n" + "3S/TB6+B41/8Wuc8qTcNnHhbWNyJVHCkW/+fZDCjhRIyaaUCc9kd/2kf1JeP0KiQ\n" + "jN0uRaGx44qC/PwIQQFRkoeaCXs1w8xIgTkwqfRBOwajBiHMS7wbdliU0eQicH8g\n" + "fnq0+n/oecGMiZ7p43IqQ3JHnrsm7WQsyFT3tJXCxOmL39UQp+2lepSXxHZF42zA\n" + "DqYqdtUdL62ZMsZ79kHgZTcPwB/FmUp1/Wzg8fBYSS2BEMrY6yvDm6nZqfVsbSb9\n" + "uDKSWPRlC9GOAx7VapXURp5l3eWFNuYxdzoaICsHt/GaTo1UIlpUHHJcH7QaWyHt\n" + "Blqa5TwByZuvUGHyKWvsbRm7LgKUyjZx70U58aUlEA6QvKezW6uv8RmIagkvH9Ak\n" + "qGLt2RpliWUWpVXeM+h6gWZykRdeHSJy97g=\n" "-----END CERTIFICATE-----\n" - ); + ); const std::string mPemChildCert( "Certificate:\n" " Data:\n" " Version: 3 (0x2)\n" - " Serial Number: 4096 (0x1000)\n" + " Serial Number: 9e:8d:34:13:e7:9b:f9:31\n" " Signature Algorithm: sha256WithRSAEncryption\n" - " Issuer: C=US, ST=California, O=Linden Lab, OU=Second Life Engineering, CN=Integration Test Intermediate CA/emailAddress=noreply@lindenlab.com\n" + " Issuer: C=US, ST=California, L=San Francisco, O=Linden Lab, OU=Second Life Engineering, CN=Integration Test Intermediate CA/emailAddress=noreply@lindenlab.com\n" " Validity\n" - " Not Before: May 22 22:58:15 2018 GMT\n" - " Not After : Jul 19 22:58:15 2024 GMT\n" + " Not Before: Jul 23 11:46:39 2024 GMT\n" + " Not After : Jul 21 11:46:39 2034 GMT\n" " Subject: C=US, ST=California, L=San Francisco, O=Linden Lab, OU=Second Life Engineering, CN=Integration Test Server Cert/emailAddress=noreply@lindenlab.com\n" " Subject Public Key Info:\n" " Public Key Algorithm: rsaEncryption\n" - " Public-Key: (2048 bit)\n" + " Public-Key: (4096 bit)\n" " Modulus:\n" - " 00:bf:a1:1c:76:82:4a:10:1d:25:0e:02:e2:7a:64:\n" - " 54:c7:94:c5:c0:98:d5:35:f3:cb:cb:30:ba:31:9c:\n" - " bd:4c:2f:4a:4e:24:03:4b:87:5c:c1:5c:fe:d9:89:\n" - " 3b:cb:01:bc:eb:a5:b7:78:dc:b3:58:e5:78:a7:15:\n" - " 34:50:30:aa:16:3a:b2:94:17:6d:1e:7f:b2:70:1e:\n" - " 96:41:bb:1d:e3:22:80:fa:dc:00:6a:fb:34:3e:67:\n" - " e7:c2:21:2f:1b:d3:af:04:49:91:eb:bb:60:e0:26:\n" - " 52:75:28:8a:08:5b:91:56:4e:51:50:40:51:70:af:\n" - " cb:80:66:c8:59:e9:e2:48:a8:62:d0:26:67:80:0a:\n" - " 12:16:d1:f6:15:9e:1f:f5:92:37:f3:c9:2f:03:9e:\n" - " 22:f6:60:5a:76:45:8c:01:2c:99:54:72:19:db:b7:\n" - " 72:e6:5a:69:f3:e9:31:65:5d:0f:c7:5c:9c:17:29:\n" - " 71:14:7f:db:47:c9:1e:65:a2:41:b0:2f:14:17:ec:\n" - " 4b:25:f2:43:8f:b4:a3:8d:37:1a:07:34:b3:29:bb:\n" - " 8a:44:8e:84:08:a2:1b:76:7a:cb:c2:39:2f:6e:e3:\n" - " fc:d6:91:b5:1f:ce:58:91:57:70:35:6e:25:a9:48:\n" - " 0e:07:cf:4e:dd:16:42:65:cf:8a:42:b3:27:e6:fe:\n" - " 6a:e3\n" + " 00:d8:ac:0c:27:8f:ea:c0:4d:21:e4:75:55:31:57:\n" + " 83:46:47:14:1e:f5:67:ae:98:60:c4:97:6d:e8:53:\n" + " f2:4d:3b:ec:6f:08:bc:1e:c0:e2:a6:75:b5:90:1d:\n" + " 30:a2:59:68:32:10:2b:29:67:fc:99:f1:24:6a:36:\n" + " 73:60:31:6b:c7:a0:b8:b0:38:60:b1:59:23:2c:ab:\n" + " 25:a2:c8:b0:bc:2c:c6:d7:4c:87:37:1b:5e:51:a4:\n" + " 63:3e:c4:6d:ed:da:5e:d3:ad:8a:6d:52:e4:87:38:\n" + " 33:76:cf:f2:86:58:b3:10:a4:91:8d:3d:4f:27:9a:\n" + " 8b:b4:d7:67:90:31:1c:f5:7f:78:af:6f:f2:dd:39:\n" + " d0:16:16:7b:46:ad:88:1b:3b:74:6b:10:29:8b:64:\n" + " ba:ed:9f:a7:69:99:55:8f:73:0d:18:a3:7f:40:20:\n" + " 3a:41:4a:94:39:62:8b:fe:c6:9d:79:d0:cd:1c:e2:\n" + " d4:74:bb:43:75:eb:86:8b:30:c1:8d:cc:14:ab:75:\n" + " 2e:f5:3e:0c:05:cb:e4:c3:92:d8:81:8c:df:a5:4e:\n" + " 2e:0b:ae:17:15:9b:e6:dd:9e:16:46:42:27:92:8a:\n" + " 0e:3a:74:1e:d1:3f:ee:7e:a5:d7:ec:1c:63:d4:96:\n" + " 5b:36:f9:15:ee:da:66:ac:5e:de:91:d9:08:24:fb:\n" + " 5d:fc:9b:77:dd:ff:20:a6:67:6f:48:41:5e:5a:ac:\n" + " 13:a4:2c:2a:f2:a3:15:86:e2:84:33:34:e3:91:27:\n" + " 8b:37:ba:b0:c7:5e:1a:0d:b9:f2:4e:0c:55:e6:bb:\n" + " d9:63:f5:05:7b:aa:19:e5:57:ce:a5:b1:46:4b:b3:\n" + " 04:f6:a0:97:26:ed:48:ed:97:93:a6:75:b1:a3:42:\n" + " fc:cc:57:89:da:44:e9:16:a6:30:2c:01:8e:f2:ed:\n" + " be:45:05:08:8a:af:1e:07:51:89:cf:51:4c:aa:f3:\n" + " b3:f0:6f:db:21:80:11:32:0a:23:e2:ff:cc:59:15:\n" + " eb:ff:d2:b8:d6:a1:c1:b4:96:12:82:bf:3f:68:ad:\n" + " c8:61:50:f8:88:4f:d0:be:8e:29:64:1a:16:a5:d9:\n" + " 29:76:16:cd:70:37:c4:f2:1f:4e:c6:57:36:dd:c1:\n" + " 27:19:72:ef:98:7e:34:25:3f:76:b1:ea:15:b2:38:\n" + " 6e:d3:43:03:7a:2b:78:91:9a:19:26:2a:31:b7:5e:\n" + " b7:22:c4:fd:bf:93:10:a4:23:3f:d7:79:53:28:5d:\n" + " 2e:ba:0c:b0:5e:0a:b4:c4:a1:71:75:88:1b:b2:0e:\n" + " 2c:67:08:7b:f0:f6:37:d3:aa:39:50:03:a3:7c:17:\n" + " 1d:52:52:2a:6b:d0:a2:54:2e:ba:11:bc:26:a9:16:\n" + " a6:1b:79\n" " Exponent: 65537 (0x10001)\n" " X509v3 extensions:\n" - " X509v3 Basic Constraints: \n" + " X509v3 Basic Constraints:\n" " CA:FALSE\n" - " Netscape Cert Type: \n" - " SSL Server\n" - " Netscape Comment: \n" - " OpenSSL Generated Server Certificate\n" - " X509v3 Subject Key Identifier: \n" - " BB:59:9F:DE:6B:51:A7:6C:B3:6D:5B:8B:42:F7:B1:65:77:17:A4:E4\n" - " X509v3 Authority Key Identifier: \n" - " keyid:83:21:DE:EC:C0:79:03:6D:1E:83:F3:E5:97:29:D5:5A:C0:96:40:FA\n" - " DirName:/C=US/ST=California/L=San Francisco/O=Linden Lab/OU=Second Life Engineering/CN=Integration Test Root CA/emailAddress=noreply@lindenlab.com\n" - " serial:10:00\n" - "\n" - " X509v3 Key Usage: critical\n" + " X509v3 Key Usage:\n" " Digital Signature, Key Encipherment\n" - " X509v3 Extended Key Usage: \n" + " X509v3 Extended Key Usage:\n" " TLS Web Server Authentication\n" + " X509v3 Subject Key Identifier:\n" + " 7B:1A:F9:2B:C4:B2:F6:AE:D6:F2:8E:B1:73:FB:DD:11:CA:DB:F8:87\n" + " X509v3 Authority Key Identifier:\n" + " keyid:56:98:DC:45:25:11:E2:8C:2B:EA:D6:C6:E2:C8:BE:2C:C8:69:FF:FF\n" + " DirName:/C=US/ST=California/L=San Francisco/O=Linden Lab/OU=Second Life Engineering/CN=Integration Test Root CA/emailAddress=noreply@lindenlab.com\n" + " serial:85:BB:4B:66:26:DB:9A:C6\n" " Signature Algorithm: sha256WithRSAEncryption\n" - " 18:a6:58:55:9b:d4:af:7d:8a:27:d3:28:3a:4c:4b:42:4e:f0:\n" - " 30:d6:d9:95:11:48:12:0a:96:40:d9:2b:21:39:c5:d4:8d:e5:\n" - " 10:bc:68:78:69:0b:9f:15:4a:0b:f1:ab:99:45:0c:20:5f:27:\n" - " df:e7:14:2d:4a:30:f2:c2:8d:37:73:36:1a:27:55:5a:08:5f:\n" - " 71:a1:5e:05:83:b2:59:fe:02:5e:d7:4a:30:15:23:58:04:cf:\n" - " 48:cc:b0:71:88:9c:6b:57:f0:04:0a:d3:a0:64:6b:ee:f3:5f:\n" - " ea:ac:e1:2b:b9:7f:79:b8:db:ce:72:48:72:db:c8:5c:38:72:\n" - " 31:55:d0:ff:6b:bd:73:23:a7:30:18:5d:ed:47:18:0a:67:8e:\n" - " 53:32:0e:99:9b:96:72:45:7f:c6:00:2c:5d:1a:97:53:75:3a:\n" - " 0b:49:3d:3a:00:37:14:67:0c:28:97:34:87:aa:c5:32:e4:ae:\n" - " 34:83:12:4a:10:f7:0e:74:d4:5f:73:bd:ef:0c:b7:d8:0a:7d:\n" - " 8e:8d:5a:48:bd:f4:8e:7b:f9:4a:15:3b:61:c9:5e:40:59:6e:\n" - " c7:a8:a4:02:28:72:c5:54:8c:77:f4:55:a7:86:c0:38:a0:68:\n" - " 19:da:0f:72:5a:a9:7e:69:9f:9c:3a:d6:66:aa:e1:f4:fd:f9:\n" - " b8:4b:6c:71:9e:f0:38:02:c7:6a:9e:dc:e6:fb:ef:23:59:4f:\n" - " 5c:84:0a:df:ea:86:1f:fd:0e:5c:fa:c4:e5:50:1c:10:cf:89:\n" - " 4e:08:0e:4c:4b:61:1a:49:12:f7:e9:4b:17:71:43:7b:6d:b6:\n" - " b5:9f:d4:3b:c7:88:53:48:63:b6:00:80:8f:49:0a:c5:7e:58:\n" - " ac:78:d8:b9:06:b0:bc:86:e2:2e:48:5b:c3:24:fa:aa:72:d8:\n" - " ec:f6:c7:91:9f:0f:c8:b5:fd:2b:b2:a7:bc:2f:40:20:2b:47:\n" - " e0:d1:1d:94:52:6f:6b:be:12:b6:8c:dc:11:db:71:e6:19:ef:\n" - " a8:71:8b:ad:d3:32:c0:1c:a4:3f:b3:0f:af:e5:50:e1:ff:41:\n" - " a4:b7:6f:57:71:af:fd:16:4c:e8:24:b3:99:1b:cf:12:8f:43:\n" - " 05:80:ba:18:19:0a:a5:ec:49:81:41:4c:7e:28:b2:21:f2:59:\n" - " 6e:4a:ed:de:f9:fa:99:85:60:1f:e6:c2:42:5c:08:00:3c:84:\n" - " 06:a9:24:d4:cf:7b:6e:1b:59:1d:f4:70:16:03:a1:e0:0b:00:\n" - " 95:5c:39:03:fc:9d:1c:8e:f7:59:0c:61:47:f6:7f:07:22:48:\n" - " 83:40:ac:e1:98:5f:c7:be:05:d5:29:2b:bf:0d:03:0e:e9:5e:\n" - " 2b:dd:09:18:fe:5e:30:61\n" + " ad:7c:50:12:24:62:62:83:e9:dd:81:1a:12:1c:6d:ae:1e:a6:\n" + " 01:cc:93:8b:ac:83:7c:3d:57:d7:7f:d2:13:40:82:c7:27:07:\n" + " 31:d8:c4:01:04:64:9c:dc:ae:7b:52:bd:f5:62:7a:d0:7c:13:\n" + " 1a:19:86:6a:ce:9a:ba:69:07:77:75:b6:67:56:d0:c3:8d:6f:\n" + " 59:5f:ac:31:83:32:2c:4f:8c:85:8c:f3:56:5b:e0:83:16:19:\n" + " c9:55:4d:56:2c:e0:06:f8:71:85:4b:7e:c6:20:b3:f6:5b:85:\n" + " 6a:b7:0f:0e:0c:75:38:6a:aa:53:cc:b0:bf:c1:fd:a1:01:8a:\n" + " 7e:5a:0b:4d:51:fc:1b:14:b0:8d:62:17:b7:5d:6a:64:30:80:\n" + " aa:50:9a:23:9e:19:46:11:9d:49:d1:35:81:87:80:8c:9c:71:\n" + " 61:26:07:23:5d:a7:ea:4e:0c:53:77:bd:eb:18:6d:63:8b:2c:\n" + " e1:83:bb:bb:f8:3e:7c:e8:0d:19:1e:be:35:aa:99:0f:c7:25:\n" + " 0c:a8:f9:74:02:c8:4c:8e:bb:13:18:fd:aa:21:34:bc:2d:9f:\n" + " 10:96:e2:99:e3:9a:d7:91:0e:1e:77:20:70:e9:b4:63:25:f8:\n" + " ea:14:1f:24:b0:6a:8b:2a:f4:61:b1:0d:7d:18:bc:1d:6d:04:\n" + " 11:b2:9f:a2:a7:55:be:2b:2c:2f:c1:d8:95:13:73:af:1c:96:\n" + " 49:30:9c:9c:94:81:6c:9b:a7:87:5c:cf:46:95:95:4a:6f:bf:\n" + " df:c9:3d:74:3e:24:6e:44:1e:14:8b:68:23:e4:00:b5:a5:b7:\n" + " 5b:a9:ea:16:5f:fa:b1:d3:1a:b1:9b:36:ef:a4:7a:6f:a3:b0:\n" + " 97:35:ac:70:c0:cc:8e:a2:d3:40:0e:c1:70:0b:d5:ce:cd:51:\n" + " 82:8a:40:72:04:8d:62:af:ba:a8:e7:a8:e9:b9:99:b7:5c:5d:\n" + " 27:96:b2:3d:f9:0d:26:8c:3f:db:ac:86:97:be:f1:2c:0b:ca:\n" + " 90:07:93:96:f4:75:c3:e8:4c:f6:a8:a2:3f:da:11:21:e7:b1:\n" + " 8c:62:36:ae:91:a9:2a:73:ba:67:f5:24:16:c3:ee:b7:b1:b4:\n" + " e3:8a:28:23:84:cf:38:c6:f0:8e:21:f6:b8:76:9a:6d:d1:e3:\n" + " 74:81:7a:22:20:a0:82:2a:31:8a:ba:44:0b:61:5a:aa:ba:c6:\n" + " 07:99:36:0a:24:06:2f:8e:c1:1c:4b:f0:65:72:fb:e9:b5:31:\n" + " 59:13:2c:c6:f8:5b:91:e2:d8:96:f3:1a:06:0b:2a:62:12:4d:\n" + " 5e:65:c9:e9:e4:00:99:a6:d3:60:1f:c3:d6:cc:a6:9b:a5:14:\n" + " 1b:4d:db:e7:3d:52:7e:2c\n" "-----BEGIN CERTIFICATE-----\n" - "MIIGbjCCBFagAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgaoxCzAJBgNVBAYTAlVT\n" - "MRMwEQYDVQQIDApDYWxpZm9ybmlhMRMwEQYDVQQKDApMaW5kZW4gTGFiMSAwHgYD\n" - "VQQLDBdTZWNvbmQgTGlmZSBFbmdpbmVlcmluZzEpMCcGA1UEAwwgSW50ZWdyYXRp\n" - "b24gVGVzdCBJbnRlcm1lZGlhdGUgQ0ExJDAiBgkqhkiG9w0BCQEWFW5vcmVwbHlA\n" - "bGluZGVubGFiLmNvbTAeFw0xODA1MjIyMjU4MTVaFw0yNDA3MTkyMjU4MTVaMIG+\n" - "MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2Fu\n" - "IEZyYW5jaXNjbzETMBEGA1UECgwKTGluZGVuIExhYjEgMB4GA1UECwwXU2Vjb25k\n" - "IExpZmUgRW5naW5lZXJpbmcxJTAjBgNVBAMMHEludGVncmF0aW9uIFRlc3QgU2Vy\n" - "dmVyIENlcnQxJDAiBgkqhkiG9w0BCQEWFW5vcmVwbHlAbGluZGVubGFiLmNvbTCC\n" - "ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL+hHHaCShAdJQ4C4npkVMeU\n" - "xcCY1TXzy8swujGcvUwvSk4kA0uHXMFc/tmJO8sBvOult3jcs1jleKcVNFAwqhY6\n" - "spQXbR5/snAelkG7HeMigPrcAGr7ND5n58IhLxvTrwRJkeu7YOAmUnUoighbkVZO\n" - "UVBAUXCvy4BmyFnp4kioYtAmZ4AKEhbR9hWeH/WSN/PJLwOeIvZgWnZFjAEsmVRy\n" - "Gdu3cuZaafPpMWVdD8dcnBcpcRR/20fJHmWiQbAvFBfsSyXyQ4+0o403Ggc0sym7\n" - "ikSOhAiiG3Z6y8I5L27j/NaRtR/OWJFXcDVuJalIDgfPTt0WQmXPikKzJ+b+auMC\n" - "AwEAAaOCAYYwggGCMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgZAMDMGCWCG\n" - "SAGG+EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRlZCBTZXJ2ZXIgQ2VydGlmaWNhdGUw\n" - "HQYDVR0OBBYEFLtZn95rUadss21bi0L3sWV3F6TkMIHoBgNVHSMEgeAwgd2AFIMh\n" - "3uzAeQNtHoPz5Zcp1VrAlkD6oYHApIG9MIG6MQswCQYDVQQGEwJVUzETMBEGA1UE\n" - "CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzETMBEGA1UECgwK\n" - "TGluZGVuIExhYjEgMB4GA1UECwwXU2Vjb25kIExpZmUgRW5naW5lZXJpbmcxITAf\n" - "BgNVBAMMGEludGVncmF0aW9uIFRlc3QgUm9vdCBDQTEkMCIGCSqGSIb3DQEJARYV\n" - "bm9yZXBseUBsaW5kZW5sYWIuY29tggIQADAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0l\n" - "BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggIBABimWFWb1K99iifTKDpM\n" - "S0JO8DDW2ZURSBIKlkDZKyE5xdSN5RC8aHhpC58VSgvxq5lFDCBfJ9/nFC1KMPLC\n" - "jTdzNhonVVoIX3GhXgWDsln+Al7XSjAVI1gEz0jMsHGInGtX8AQK06Bka+7zX+qs\n" - "4Su5f3m4285ySHLbyFw4cjFV0P9rvXMjpzAYXe1HGApnjlMyDpmblnJFf8YALF0a\n" - "l1N1OgtJPToANxRnDCiXNIeqxTLkrjSDEkoQ9w501F9zve8Mt9gKfY6NWki99I57\n" - "+UoVO2HJXkBZbseopAIocsVUjHf0VaeGwDigaBnaD3JaqX5pn5w61maq4fT9+bhL\n" - "bHGe8DgCx2qe3Ob77yNZT1yECt/qhh/9Dlz6xOVQHBDPiU4IDkxLYRpJEvfpSxdx\n" - "Q3tttrWf1DvHiFNIY7YAgI9JCsV+WKx42LkGsLyG4i5IW8Mk+qpy2Oz2x5GfD8i1\n" - "/Suyp7wvQCArR+DRHZRSb2u+EraM3BHbceYZ76hxi63TMsAcpD+zD6/lUOH/QaS3\n" - "b1dxr/0WTOgks5kbzxKPQwWAuhgZCqXsSYFBTH4osiHyWW5K7d75+pmFYB/mwkJc\n" - "CAA8hAapJNTPe24bWR30cBYDoeALAJVcOQP8nRyO91kMYUf2fwciSINArOGYX8e+\n" - "BdUpK78NAw7pXivdCRj+XjBh\n" + "MIIHSTCCBTGgAwIBAgIJAJ6NNBPnm/kxMA0GCSqGSIb3DQEBCwUAMIHCMQswCQYD\n" + "VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5j\n" + "aXNjbzETMBEGA1UECgwKTGluZGVuIExhYjEgMB4GA1UECwwXU2Vjb25kIExpZmUg\n" + "RW5naW5lZXJpbmcxKTAnBgNVBAMMIEludGVncmF0aW9uIFRlc3QgSW50ZXJtZWRp\n" + "YXRlIENBMSQwIgYJKoZIhvcNAQkBFhVub3JlcGx5QGxpbmRlbmxhYi5jb20wHhcN\n" + "MjQwNzIzMTE0NjM5WhcNMzQwNzIxMTE0NjM5WjCBvjELMAkGA1UEBhMCVVMxEzAR\n" + "BgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xEzARBgNV\n" + "BAoMCkxpbmRlbiBMYWIxIDAeBgNVBAsMF1NlY29uZCBMaWZlIEVuZ2luZWVyaW5n\n" + "MSUwIwYDVQQDDBxJbnRlZ3JhdGlvbiBUZXN0IFNlcnZlciBDZXJ0MSQwIgYJKoZI\n" + "hvcNAQkBFhVub3JlcGx5QGxpbmRlbmxhYi5jb20wggIiMA0GCSqGSIb3DQEBAQUA\n" + "A4ICDwAwggIKAoICAQDYrAwnj+rATSHkdVUxV4NGRxQe9WeumGDEl23oU/JNO+xv\n" + "CLwewOKmdbWQHTCiWWgyECspZ/yZ8SRqNnNgMWvHoLiwOGCxWSMsqyWiyLC8LMbX\n" + "TIc3G15RpGM+xG3t2l7TrYptUuSHODN2z/KGWLMQpJGNPU8nmou012eQMRz1f3iv\n" + "b/LdOdAWFntGrYgbO3RrECmLZLrtn6dpmVWPcw0Yo39AIDpBSpQ5Yov+xp150M0c\n" + "4tR0u0N164aLMMGNzBSrdS71PgwFy+TDktiBjN+lTi4LrhcVm+bdnhZGQieSig46\n" + "dB7RP+5+pdfsHGPUlls2+RXu2masXt6R2Qgk+138m3fd/yCmZ29IQV5arBOkLCry\n" + "oxWG4oQzNOORJ4s3urDHXhoNufJODFXmu9lj9QV7qhnlV86lsUZLswT2oJcm7Ujt\n" + "l5OmdbGjQvzMV4naROkWpjAsAY7y7b5FBQiKrx4HUYnPUUyq87Pwb9shgBEyCiPi\n" + "/8xZFev/0rjWocG0lhKCvz9orchhUPiIT9C+jilkGhal2Sl2Fs1wN8TyH07GVzbd\n" + "wScZcu+YfjQlP3ax6hWyOG7TQwN6K3iRmhkmKjG3XrcixP2/kxCkIz/XeVMoXS66\n" + "DLBeCrTEoXF1iBuyDixnCHvw9jfTqjlQA6N8Fx1SUipr0KJULroRvCapFqYbeQID\n" + "AQABo4IBQjCCAT4wCQYDVR0TBAIwADALBgNVHQ8EBAMCBaAwEwYDVR0lBAwwCgYI\n" + "KwYBBQUHAwEwHQYDVR0OBBYEFHsa+SvEsvau1vKOsXP73RHK2/iHMIHvBgNVHSME\n" + "gecwgeSAFFaY3EUlEeKMK+rWxuLIvizIaf//oYHApIG9MIG6MQswCQYDVQQGEwJV\n" + "UzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzET\n" + "MBEGA1UECgwKTGluZGVuIExhYjEgMB4GA1UECwwXU2Vjb25kIExpZmUgRW5naW5l\n" + "ZXJpbmcxITAfBgNVBAMMGEludGVncmF0aW9uIFRlc3QgUm9vdCBDQTEkMCIGCSqG\n" + "SIb3DQEJARYVbm9yZXBseUBsaW5kZW5sYWIuY29tggkAhbtLZibbmsYwDQYJKoZI\n" + "hvcNAQELBQADggIBAK18UBIkYmKD6d2BGhIcba4epgHMk4usg3w9V9d/0hNAgscn\n" + "BzHYxAEEZJzcrntSvfVietB8ExoZhmrOmrppB3d1tmdW0MONb1lfrDGDMixPjIWM\n" + "81Zb4IMWGclVTVYs4Ab4cYVLfsYgs/ZbhWq3Dw4MdThqqlPMsL/B/aEBin5aC01R\n" + "/BsUsI1iF7ddamQwgKpQmiOeGUYRnUnRNYGHgIyccWEmByNdp+pODFN3vesYbWOL\n" + "LOGDu7v4PnzoDRkevjWqmQ/HJQyo+XQCyEyOuxMY/aohNLwtnxCW4pnjmteRDh53\n" + "IHDptGMl+OoUHySwaosq9GGxDX0YvB1tBBGyn6KnVb4rLC/B2JUTc68clkkwnJyU\n" + "gWybp4dcz0aVlUpvv9/JPXQ+JG5EHhSLaCPkALWlt1up6hZf+rHTGrGbNu+kem+j\n" + "sJc1rHDAzI6i00AOwXAL1c7NUYKKQHIEjWKvuqjnqOm5mbdcXSeWsj35DSaMP9us\n" + "hpe+8SwLypAHk5b0dcPoTPaooj/aESHnsYxiNq6RqSpzumf1JBbD7rextOOKKCOE\n" + "zzjG8I4h9rh2mm3R43SBeiIgoIIqMYq6RAthWqq6xgeZNgokBi+OwRxL8GVy++m1\n" + "MVkTLMb4W5Hi2JbzGgYLKmISTV5lyenkAJmm02Afw9bMppulFBtN2+c9Un4s\n" "-----END CERTIFICATE-----\n" - ); + ); + // Test wrapper declaration : wrapping nothing for the moment struct sechandler_basic_test @@ -701,14 +722,13 @@ namespace tut //std::ostringstream llsd_value; //llsd_value << LLSDOStreamer(llsd_cert) << std::endl; LL_DEBUGS() << "test 1 cert " << llsd_cert << LL_ENDL; - ensure_equals("Issuer Name/commonName", (std::string)llsd_cert["issuer_name"]["commonName"], "Integration Test Intermediate CA"); ensure_equals("Issuer Name/countryName", (std::string)llsd_cert["issuer_name"]["countryName"], "US"); ensure_equals("Issuer Name/state", (std::string)llsd_cert["issuer_name"]["stateOrProvinceName"], "California"); ensure_equals("Issuer Name/org name", (std::string)llsd_cert["issuer_name"]["organizationName"], "Linden Lab"); ensure_equals("Issuer Name/org unit", (std::string)llsd_cert["issuer_name"]["organizationalUnitName"], "Second Life Engineering"); ensure_equals("Issuer name string", (std::string)llsd_cert["issuer_name_string"], - "emailAddress=noreply@lindenlab.com,CN=Integration Test Intermediate CA,OU=Second Life Engineering,O=Linden Lab,ST=California,C=US"); + "emailAddress=noreply@lindenlab.com,CN=Integration Test Intermediate CA,OU=Second Life Engineering,O=Linden Lab,L=San Francisco,ST=California,C=US"); ensure_equals("subject Name/commonName", (std::string)llsd_cert["subject_name"]["commonName"], "Integration Test Server Cert"); ensure_equals("subject Name/countryName", (std::string)llsd_cert["subject_name"]["countryName"], "US"); @@ -721,9 +741,9 @@ namespace tut ensure_equals("subject name string", (std::string)llsd_cert["subject_name_string"], "emailAddress=noreply@lindenlab.com,CN=Integration Test Server Cert,OU=Second Life Engineering,O=Linden Lab,L=San Francisco,ST=California,C=US"); - ensure_equals("serial number", (std::string)llsd_cert["serial_number"], "1000"); - ensure_equals("valid from", (std::string)llsd_cert["valid_from"], "2018-05-22T22:58:15Z"); - ensure_equals("valid to", (std::string)llsd_cert["valid_to"], "2024-07-19T22:58:15Z"); + ensure_equals("serial number", (std::string)llsd_cert["serial_number"], "9E8D3413E79BF931"); + ensure_equals("valid from", (std::string)llsd_cert["valid_from"], "2024-07-23T11:46:39Z"); + ensure_equals("valid to", (std::string)llsd_cert["valid_to"], "2034-07-21T11:46:39Z"); LLSD expectedKeyUsage = LLSD::emptyArray(); expectedKeyUsage.append(LLSD((std::string)"digitalSignature")); expectedKeyUsage.append(LLSD((std::string)"keyEncipherment")); @@ -1042,7 +1062,7 @@ namespace tut //validate find LLSD find_info = LLSD::emptyMap(); - find_info["subjectKeyIdentifier"] = "bb:59:9f:de:6b:51:a7:6c:b3:6d:5b:8b:42:f7:b1:65:77:17:a4:e4"; + find_info["subjectKeyIdentifier"] = "7b:1a:f9:2b:c4:b2:f6:ae:d6:f2:8e:b1:73:fb:dd:11:ca:db:f8:87"; LLBasicCertificateVector::iterator found_cert = test_vector->find(find_info); ensure("found some cert", found_cert != test_vector->end()); X509* found_x509 = (*found_cert).get()->getOpenSSLX509(); @@ -1225,7 +1245,7 @@ namespace tut X509_STORE_CTX_set0_untrusted(test_store, NULL); test_chain = new LLBasicCertificateChain(test_store); X509_STORE_CTX_free(test_store); - ensure_equals("two elements in store", test_chain->size(), 1); + ensure_equals("two elements in store [1]", test_chain->size(), 1); X509* test_cert = (*test_chain)[0]->getOpenSSLX509(); ensure("validate first element in store is expected cert", !X509_cmp(test_cert, mX509ChildCert)); X509_free(test_cert); @@ -1238,7 +1258,7 @@ namespace tut sk_X509_push(X509_STORE_CTX_get0_untrusted(test_store), mX509IntermediateCert); test_chain = new LLBasicCertificateChain(test_store); X509_STORE_CTX_free(test_store); - ensure_equals("two elements in store", test_chain->size(), 2); + ensure_equals("two elements in store [2]", test_chain->size(), 2); test_cert = (*test_chain)[0]->getOpenSSLX509(); ensure("validate first element in store is expected cert", !X509_cmp(test_cert, mX509ChildCert)); X509_free(test_cert); @@ -1254,7 +1274,7 @@ namespace tut sk_X509_push(X509_STORE_CTX_get0_untrusted(test_store), mX509TestCert); test_chain = new LLBasicCertificateChain(test_store); X509_STORE_CTX_free(test_store); - ensure_equals("two elements in store", test_chain->size(), 1); + ensure_equals("two elements in store [3]", test_chain->size(), 1); test_cert = (*test_chain)[0]->getOpenSSLX509(); ensure("validate first element in store is expected cert", !X509_cmp(test_cert, mX509ChildCert)); X509_free(test_cert); @@ -1267,7 +1287,7 @@ namespace tut sk_X509_push(X509_STORE_CTX_get0_untrusted(test_store), mX509TestCert); test_chain = new LLBasicCertificateChain(test_store); X509_STORE_CTX_free(test_store); - ensure_equals("two elements in store", test_chain->size(), 2); + ensure_equals("two elements in store [4]", test_chain->size(), 2); test_cert = (*test_chain)[0]->getOpenSSLX509(); ensure("validate first element in store is expected cert", !X509_cmp(test_cert, mX509ChildCert)); X509_free(test_cert); -- cgit v1.2.3 From 03d7f2b84daf9ab991de6cad7d6149abda1ef716 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 28 Aug 2024 21:16:56 -0400 Subject: Ditch trailing spaces. --- indra/newview/tests/llluamanager_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index 3209d93d39..4b143b52db 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -3,7 +3,7 @@ * @author Nat Goodspeed * @date 2023-09-28 * @brief Test for llluamanager. - * + * * $LicenseInfo:firstyear=2023&license=viewerlgpl$ * Copyright (c) 2023, Linden Research, Inc. * $/LicenseInfo$ -- cgit v1.2.3 From a6b85244a6f943a4598ff9b7b8a3343eb1e0d11e Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 4 Sep 2024 10:26:40 -0400 Subject: Fix test: new traceback info changed error message. --- indra/newview/tests/llluamanager_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index 3209d93d39..c2abd27f96 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -463,8 +463,8 @@ namespace tut // but now we have to give the startScriptLine() coroutine a chance to run auto [count, result] = future.get(); ensure_equals("killed Lua script terminated normally", count, -1); - ensure_equals("unexpected killed Lua script error", - result.asString(), "viewer is stopping"); + ensure_contains("unexpected killed Lua script error", + result.asString(), "viewer is stopping"); } template<> template<> -- cgit v1.2.3 From 5319d314206c7c1c21b2bbd3a661c0c520373dcc Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 4 Sep 2024 16:24:42 -0400 Subject: Windows build fixes --- indra/newview/tests/llluamanager_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index 4b143b52db..8ce5c357e0 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -287,7 +287,7 @@ namespace tut while (expect_array.size() > 0 && send_array[expect_array.size() - 1].isUndefined()) { - expect_array.erase(expect_array.size() - 1); + expect_array.erase(LLSD::Integer(expect_array.size() - 1)); } round_trip("array", send_array, expect_array); -- cgit v1.2.3 From 89992713218dba9f1a15973decad897127e90545 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 5 Sep 2024 17:31:14 -0400 Subject: Fix typo in cppfeatures_test.cpp --- indra/newview/tests/cppfeatures_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/cppfeatures_test.cpp b/indra/newview/tests/cppfeatures_test.cpp index f5ea3a522b..ca94dcfc95 100644 --- a/indra/newview/tests/cppfeatures_test.cpp +++ b/indra/newview/tests/cppfeatures_test.cpp @@ -283,7 +283,7 @@ void cpp_features_test_object_t::test<8>() ensure("init member inline 1", ii.mFoo==10); InitInlineWithConstructor iici; - ensure("init member inline 2", iici.mFoo=10); + ensure("init member inline 2", iici.mFoo==10); ensure("init member inline 3", iici.mBar==25); } -- cgit v1.2.3 From 26efc7e376ef52284a6281f36cf45eb03bc13507 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 10 Sep 2024 15:25:07 -0400 Subject: Pass std::string_view by value, not by const reference. Consensus seems to be that (a) string_view is, in effect, already a reference, (b) it's small enough to make pass-by-value reasonable and (c) the optimizer can reason about values way better than it can about references. --- indra/newview/tests/llluamanager_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index 8d1333815b..f0a1b32eed 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -123,7 +123,7 @@ namespace tut } } - void from_lua(const std::string& desc, const std::string_view& construct, const LLSD& expect) + void from_lua(const std::string& desc, std::string_view construct, const LLSD& expect) { LLSD fromlua; LLStreamListener pump("testpump", -- cgit v1.2.3