#ifndef COROUTINES_INCLUDE_CORO_INTERNAL_COTEST_CRF_CORE_H_ #define COROUTINES_INCLUDE_CORO_INTERNAL_COTEST_CRF_CORE_H_ #include #include #include #include #include "cotest-coro-common.h" #include "cotest-coro-thread.h" #include "cotest-crf-payloads.h" #include "cotest-util-logging.h" #include "cotest-util-types.h" namespace testing { namespace crf { // Select the thread-based coroutine impl for all the CRF coroutines. using CoroImplType = coro_impl::CoroOnThread; // ------------------ Classes ------------------ class MockRoutingSession; class InteriorEventSession; template class InteriorSignatureMockCS; class InteriorLaunchSessionBase; template class InteriorLaunchSession; class TestCoroutine; using coro_impl::MakePayload; using coro_impl::PeekPayload; using coro_impl::SpecialisePayload; class MessageNode { public: // Reply payload, reply destination using ReplyPair = std::pair, MessageNode *>; MessageNode() = default; MessageNode(const MessageNode &i) = delete; MessageNode(MessageNode &&i) = delete; MessageNode &operator=(const MessageNode &) = delete; MessageNode &operator=(MessageNode &&) = delete; virtual ~MessageNode() = default; virtual ReplyPair ReceiveMessage(std::unique_ptr &&to_node) = 0; virtual std::string DebugString() const = 0; static std::unique_ptr SendMessageFromMain(MessageNode *dest, std::unique_ptr &&to_node); private: static std::unique_ptr MessageLoop(MessageNode *dest, std::unique_ptr &&to_node); }; inline std::ostream &operator<<(std::ostream &os, const MessageNode *payload) { if (payload) os << payload->DebugString(); os << coro_impl::PtrToString(payload); return os; } class CoroutineBase : public virtual MessageNode { public: CoroutineBase(const CoroutineBase &i) = delete; CoroutineBase(CoroutineBase &&i) = delete; CoroutineBase &operator=(const CoroutineBase &) = delete; CoroutineBase &operator=(CoroutineBase &&) = delete; virtual ~CoroutineBase(); CoroutineBase(coro_impl::BodyFunction cofn_, std::string name_); std::unique_ptr Iterate(std::unique_ptr &&to_coro); void Cancel(); bool IsCoroutineExited() const; std::unique_ptr Yield(std::unique_ptr &&from_coro); coro_impl::InteriorInterface *GetImpl(); void SetName(std::string name_); std::string GetName() const; std::string ActiveStr() const; private: std::string name; std::unique_ptr impl; bool initial = true; }; class MockSource : public virtual MessageNode { public: MockSource() = default; MockSource(const MockSource &i) = delete; MockSource(MockSource &&i) = delete; MockSource &operator=(const MockSource &) = delete; MockSource &operator=(MockSource &&) = delete; virtual ~MockSource() = default; virtual std::shared_ptr CreateMockRoutingSession(UntypedMockerPointer mocker_, UntypedMockObjectPointer mock_obj_, const char *name_) = 0; void SetCurrentMockRS(std::shared_ptr current_mock_call_); std::shared_ptr GetCurrentMockRS() const; virtual LaunchCoroutine *GetAsCoroutine() = 0; virtual const LaunchCoroutine *GetAsCoroutine() const = 0; private: std::shared_ptr current_mock_rs; }; class ProxyForMain : public MockSource, public std::enable_shared_from_this { public: ReplyPair ReceiveMessage(std::unique_ptr &&to_node) final; std::shared_ptr CreateMockRoutingSession(UntypedMockerPointer mocker_, UntypedMockObjectPointer mock_obj_, const char *name_) final; std::string DebugString() const final; LaunchCoroutine *GetAsCoroutine() final; const LaunchCoroutine *GetAsCoroutine() const final; static std::shared_ptr GetInstance(); }; } // namespace crf } // namespace testing #endif