diff options
Diffstat (limited to 'indra/llcommon/tests')
| -rw-r--r-- | indra/llcommon/tests/threadsafeschedule_test.cpp | 4 | ||||
| -rw-r--r-- | indra/llcommon/tests/workqueue_test.cpp | 72 | 
2 files changed, 73 insertions, 3 deletions
diff --git a/indra/llcommon/tests/threadsafeschedule_test.cpp b/indra/llcommon/tests/threadsafeschedule_test.cpp index af67b9f492..c421cc7b1c 100644 --- a/indra/llcommon/tests/threadsafeschedule_test.cpp +++ b/indra/llcommon/tests/threadsafeschedule_test.cpp @@ -46,11 +46,11 @@ namespace tut          // the real time required for each push() call. Explicitly increment          // the timestamp for each one -- but since we're passing explicit          // timestamps, make the queue reorder them. -        queue.push(Queue::TimeTuple(Queue::Clock::now() + 20ms, "ghi")); +        queue.push(Queue::TimeTuple(Queue::Clock::now() + 200ms, "ghi"));          // Given the various push() overloads, you have to match the type          // exactly: conversions are ambiguous.          queue.push("abc"s); -        queue.push(Queue::Clock::now() + 10ms, "def"); +        queue.push(Queue::Clock::now() + 100ms, "def");          queue.close();          auto entry = queue.pop();          ensure_equals("failed to pop first", std::get<0>(entry), "abc"s); diff --git a/indra/llcommon/tests/workqueue_test.cpp b/indra/llcommon/tests/workqueue_test.cpp index d5405400fd..bea3ad911b 100644 --- a/indra/llcommon/tests/workqueue_test.cpp +++ b/indra/llcommon/tests/workqueue_test.cpp @@ -20,7 +20,10 @@  // external library headers  // other Linden headers  #include "../test/lltut.h" +#include "../test/catch_and_store_what_in.h"  #include "llcond.h" +#include "llcoros.h" +#include "lleventcoro.h"  #include "llstring.h"  #include "stringize.h" @@ -138,7 +141,8 @@ namespace tut              [](){ return 17; },              // Note that a postTo() *callback* can safely bind a reference to              // a variable on the invoking thread, because the callback is run -            // on the invoking thread. +            // on the invoking thread. (Of course the bound variable must +            // survive until the callback is called.)              [&result](int i){ result = i; });          // this should post the callback to main          qptr->runOne(); @@ -156,4 +160,70 @@ namespace tut          main.runPending();          ensure_equals("failed to run string callback", alpha, "abc");      } + +    template<> template<> +    void object::test<5>() +    { +        set_test_name("postTo with void return"); +        WorkQueue main("main"); +        auto qptr = WorkQueue::getInstance("queue"); +        std::string observe; +        main.postTo( +            qptr, +            // The ONLY reason we can get away with binding a reference to +            // 'observe' in our work callable is because we're directly +            // calling qptr->runOne() on this same thread. It would be a +            // mistake to do that if some other thread were servicing 'queue'. +            [&observe](){ observe = "queue"; }, +            [&observe](){ observe.append(";main"); }); +        qptr->runOne(); +        main.runOne(); +        ensure_equals("failed to run both lambdas", observe, "queue;main"); +    } + +    template<> template<> +    void object::test<6>() +    { +        set_test_name("waitForResult"); +        std::string stored; +        // Try to call waitForResult() on this thread's main coroutine. It +        // should throw because the main coroutine must service the queue. +        auto what{ catch_what<WorkQueue::Error>( +                [this, &stored](){ stored = queue.waitForResult( +                        [](){ return "should throw"; }); }) }; +        ensure("lambda should not have run", stored.empty()); +        ensure_not("waitForResult() should have thrown", what.empty()); +        ensure(STRINGIZE("should mention waitForResult: " << what), +               what.find("waitForResult") != std::string::npos); + +        // Call waitForResult() on a coroutine, with a string result. +        LLCoros::instance().launch( +            "waitForResult string", +            [this, &stored]() +            { stored = queue.waitForResult( +                    [](){ return "string result"; }); }); +        llcoro::suspend(); +        // Nothing will have happened yet because, even if the coroutine did +        // run immediately, all it did was to queue the inner lambda on +        // 'queue'. Service it. +        queue.runOne(); +        llcoro::suspend(); +        ensure_equals("bad waitForResult return", stored, "string result"); + +        // Call waitForResult() on a coroutine, with a void callable. +        stored.clear(); +        bool done = false; +        LLCoros::instance().launch( +            "waitForResult void", +            [this, &stored, &done]() +            { +                queue.waitForResult([&stored](){ stored = "ran"; }); +                done = true; +            }); +        llcoro::suspend(); +        queue.runOne(); +        llcoro::suspend(); +        ensure_equals("didn't run coroutine", stored, "ran"); +        ensure("void waitForResult() didn't return", done); +    }  } // namespace tut  | 
