#include "util/MockAssert.hpp" #include "util/MockOperation.hpp" #include "util/async/AnyOperation.hpp" #include "util/async/Error.hpp" #include #include #include #include #include #include using namespace util::async; using namespace ::testing; struct AnyOperationTests : virtual Test { using OperationType = MockOperation>; using StoppableOperationType = MockStoppableOperation>; using ScheduledOperationType = MockScheduledOperation>; using RepeatingOperationType = MockRepeatingOperation>; NaggyMock mockOp; NaggyMock mockStoppableOp; NaggyMock mockScheduledOp; NaggyMock mockRepeatingOp; AnyOperation voidOp{impl::ErasedOperation(static_cast(mockOp))}; AnyOperation voidStoppableOp{ impl::ErasedOperation(static_cast(mockStoppableOp)) }; AnyOperation intOp{impl::ErasedOperation(static_cast(mockOp))}; AnyOperation scheduledVoidOp{ impl::ErasedOperation(static_cast(mockScheduledOp)) }; AnyOperation repeatingOp{ impl::ErasedOperation(static_cast(mockRepeatingOp)) }; }; TEST_F(AnyOperationTests, Move) { EXPECT_CALL(mockOp, get()).WillOnce(Return(std::any{})); auto yoink = std::move(voidOp); auto res = yoink.get(); ASSERT_TRUE(res); } TEST_F(AnyOperationTests, VoidDataYieldsNoError) { EXPECT_CALL(mockOp, get()).WillOnce(Return(std::any{})); auto res = voidOp.get(); ASSERT_TRUE(res); } TEST_F(AnyOperationTests, GetIntData) { EXPECT_CALL(mockOp, get()).WillOnce(Return(std::make_any(42))); auto res = intOp.get(); EXPECT_EQ(res.value(), 42); } TEST_F(AnyOperationTests, WaitCallPropagated) { StrictMock> callback; EXPECT_CALL(callback, Call()); EXPECT_CALL(mockOp, wait()).WillOnce([&] { callback.Call(); }); voidOp.wait(); } TEST_F(AnyOperationTests, CancelAndRequestStopCallPropagated) { StrictMock> callback; EXPECT_CALL(callback, Call()).Times(2); EXPECT_CALL(mockScheduledOp, cancel()).WillOnce([&] { callback.Call(); }); EXPECT_CALL(mockScheduledOp, requestStop()).WillOnce([&] { callback.Call(); }); scheduledVoidOp.abort(); } TEST_F(AnyOperationTests, RequestStopCallPropagatedOnStoppableOperation) { StrictMock> callback; EXPECT_CALL(callback, Call()); EXPECT_CALL(mockStoppableOp, requestStop()).WillOnce([&] { callback.Call(); }); voidStoppableOp.abort(); } TEST_F(AnyOperationTests, GetPropagatesError) { EXPECT_CALL(mockOp, get()).WillOnce(Return(std::unexpected(ExecutionError{"tid", "Not good"}))); auto res = intOp.get(); ASSERT_FALSE(res); EXPECT_TRUE(res.error().message.ends_with("Not good")); } TEST_F(AnyOperationTests, GetIncorrectDataReturnsError) { EXPECT_CALL(mockOp, get()).WillOnce(Return(std::make_any(4.2))); auto res = intOp.get(); ASSERT_FALSE(res); EXPECT_TRUE(res.error().message.ends_with("Bad any cast")); EXPECT_TRUE(std::string{res.error()}.ends_with("Bad any cast")); } TEST_F(AnyOperationTests, RepeatingOpWaitPropagated) { EXPECT_CALL(mockRepeatingOp, wait()); repeatingOp.wait(); } TEST_F(AnyOperationTests, RepeatingOpRequestStopCallPropagated) { EXPECT_CALL(mockRepeatingOp, requestStop()); repeatingOp.abort(); } TEST_F(AnyOperationTests, RepeatingOpInvokeCallPropagated) { EXPECT_CALL(mockRepeatingOp, invoke()); repeatingOp.invoke(); } struct AnyOperationAssertTest : common::util::WithMockAssert, AnyOperationTests {}; TEST_F(AnyOperationAssertTest, CallAbortOnNonStoppableOrCancellableOperation) { EXPECT_CLIO_ASSERT_FAIL(voidOp.abort()); } TEST_F(AnyOperationAssertTest, CallInvokeOnNonForceInvocableOperation) { EXPECT_CLIO_ASSERT_FAIL(voidOp.invoke()); }