summaryrefslogtreecommitdiff
path: root/indra/newview/tests/llluamanager_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/tests/llluamanager_test.cpp')
-rw-r--r--indra/newview/tests/llluamanager_test.cpp110
1 files changed, 99 insertions, 11 deletions
diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp
index 81ec186cf4..069e10e9cf 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
@@ -94,9 +95,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 +118,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 +174,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 +194,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 +303,93 @@ 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"
+ "\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"
+ "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"
+ " -- 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"
+ "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();
+ ensure_equals("leap.lua: " + result.asString(), count, 0);
+ }
} // namespace tut