diff --git a/src/web/ng/Connection.hpp b/src/web/ng/Connection.hpp index d9696dc6..309bb7d2 100644 --- a/src/web/ng/Connection.hpp +++ b/src/web/ng/Connection.hpp @@ -143,9 +143,9 @@ public: * * @param response The response to send. * @param yield The yield context. - * @return An error if the operation failed or nullopt if it succeeded. + * @return An error if the operation fails, otherwise nothing. */ - virtual std::optional + virtual std::expected send(Response response, boost::asio::yield_context yield) = 0; /** diff --git a/src/web/ng/Server.cpp b/src/web/ng/Server.cpp index 53abd855..5726f1a8 100644 --- a/src/web/ng/Server.cpp +++ b/src/web/ng/Server.cpp @@ -147,9 +147,9 @@ makeConnection( tagDecoratorFactory ); sslConnection->setTimeout(std::chrono::seconds{10}); - auto const maybeError = sslConnection->sslHandshake(yield); - if (maybeError.has_value()) - return std::unexpected{fmt::format("SSL handshake error: {}", maybeError->message())}; + auto const expectedSuccess = sslConnection->sslHandshake(yield); + if (not expectedSuccess.has_value()) + return std::unexpected{fmt::format("SSL handshake error: {}", expectedSuccess.error().message())}; connection = std::move(sslConnection); } else { diff --git a/src/web/ng/SubscriptionContext.cpp b/src/web/ng/SubscriptionContext.cpp index 5cf07b6e..f3e76feb 100644 --- a/src/web/ng/SubscriptionContext.cpp +++ b/src/web/ng/SubscriptionContext.cpp @@ -70,8 +70,8 @@ SubscriptionContext::send(std::shared_ptr message) } tasksGroup_.spawn(yield_, [this, message = std::move(message)](boost::asio::yield_context innerYield) mutable { - auto const maybeError = connection_.get().sendShared(std::move(message), innerYield); - if (maybeError.has_value() and errorHandler_(*maybeError, connection_)) { + auto const expectedSuccess = connection_.get().sendShared(std::move(message), innerYield); + if (not expectedSuccess.has_value() and errorHandler_(expectedSuccess.error(), connection_)) { connection_.get().close(innerYield); gotError_ = true; } diff --git a/src/web/ng/impl/ConnectionHandler.cpp b/src/web/ng/impl/ConnectionHandler.cpp index c8cdc6e1..d188f963 100644 --- a/src/web/ng/impl/ConnectionHandler.cpp +++ b/src/web/ng/impl/ConnectionHandler.cpp @@ -365,9 +365,9 @@ ConnectionHandler::processRequest( auto response = handleRequest(connection, subscriptionContext, request, yield); LOG(log_.trace()) << connection.tag() << "Sending response: " << response.message(); - auto const maybeError = connection.send(std::move(response), yield); - if (maybeError.has_value()) { - return handleError(maybeError.value(), connection); + auto const expectedSuccess = connection.send(std::move(response), yield); + if (not expectedSuccess.has_value()) { + return handleError(expectedSuccess.error(), connection); } return std::nullopt; } diff --git a/src/web/ng/impl/HttpConnection.hpp b/src/web/ng/impl/HttpConnection.hpp index f64aa868..714284b2 100644 --- a/src/web/ng/impl/HttpConnection.hpp +++ b/src/web/ng/impl/HttpConnection.hpp @@ -62,7 +62,7 @@ public: virtual std::expected upgrade(util::TagDecoratorFactory const& tagDecoratorFactory, boost::asio::yield_context yield) = 0; - virtual std::optional + virtual std::expected sendRaw( boost::beast::http::response response, boost::asio::yield_context yield @@ -123,7 +123,7 @@ public: HttpConnection& operator=(HttpConnection const& other) = delete; - std::optional + std::expected sslHandshake(boost::asio::yield_context yield) requires IsSslTcpStream { @@ -132,11 +132,11 @@ public: auto const bytesUsed = stream_.async_handshake(boost::asio::ssl::stream_base::server, buffer_.cdata(), yield[error]); if (error) - return error; + return std::unexpected{error}; buffer_.consume(bytesUsed); - return std::nullopt; + return {}; } bool @@ -145,7 +145,7 @@ public: return false; } - std::optional + std::expected sendRaw( boost::beast::http::response response, boost::asio::yield_context yield @@ -160,7 +160,7 @@ public: timeout_ = newTimeout; } - std::optional + std::expected send(Response response, boost::asio::yield_context yield) override { auto httpResponse = std::move(response).intoHttpResponse(); diff --git a/src/web/ng/impl/SendingQueue.hpp b/src/web/ng/impl/SendingQueue.hpp index 4bd1a14d..2a1328c1 100644 --- a/src/web/ng/impl/SendingQueue.hpp +++ b/src/web/ng/impl/SendingQueue.hpp @@ -47,15 +47,15 @@ public: { } - std::optional + std::expected send(T message, boost::asio::yield_context yield) { if (error_) - return error_; + return std::unexpected{error_}; queue_.push(std::move(message)); if (isSending_) - return std::nullopt; + return {}; isSending_ = true; while (not queue_.empty() and not error_) { @@ -65,8 +65,8 @@ public: } isSending_ = false; if (error_) - return error_; - return std::nullopt; + return std::unexpected{error_}; + return {}; } }; diff --git a/src/web/ng/impl/WsConnection.hpp b/src/web/ng/impl/WsConnection.hpp index bf1263e2..ad28b0d0 100644 --- a/src/web/ng/impl/WsConnection.hpp +++ b/src/web/ng/impl/WsConnection.hpp @@ -59,7 +59,7 @@ class WsConnectionBase : public Connection { public: using Connection::Connection; - virtual std::optional + virtual std::expected sendShared(std::shared_ptr message, boost::asio::yield_context yield) = 0; }; @@ -108,14 +108,14 @@ public: WsConnection& operator=(WsConnection const&) = delete; - std::optional + std::expected performHandshake(boost::asio::yield_context yield) { Error error; stream_.async_accept(initialRequest_, yield[error]); if (error) - return error; - return std::nullopt; + return std::unexpected{error}; + return {}; } bool @@ -124,7 +124,7 @@ public: return true; } - std::optional + std::expected sendShared(std::shared_ptr message, boost::asio::yield_context yield) override { return sendingQueue_.send(std::move(message), yield); @@ -140,7 +140,7 @@ public: stream_.set_option(wsTimeout); } - std::optional + std::expected send(Response response, boost::asio::yield_context yield) override { return sendingQueue_.send(std::move(response), yield); @@ -206,9 +206,9 @@ makeWsConnection( auto connection = std::make_unique>( std::forward(stream), std::move(ip), std::move(buffer), std::move(request), tagDecoratorFactory ); - auto maybeError = connection->performHandshake(yield); - if (maybeError.has_value()) - return std::unexpected{maybeError.value()}; + auto const expectedSuccess = connection->performHandshake(yield); + if (not expectedSuccess.has_value()) + return std::unexpected{expectedSuccess.error()}; return connection; } diff --git a/tests/common/util/TestHttpClient.cpp b/tests/common/util/TestHttpClient.cpp index ec233b11..189d0db0 100644 --- a/tests/common/util/TestHttpClient.cpp +++ b/tests/common/util/TestHttpClient.cpp @@ -186,7 +186,7 @@ HttpAsyncClient::HttpAsyncClient(boost::asio::io_context& ioContext) : stream_{i { } -std::optional +std::expected HttpAsyncClient::connect( std::string_view host, std::string_view port, @@ -198,18 +198,18 @@ HttpAsyncClient::connect( boost::asio::ip::tcp::resolver resolver{stream_.get_executor()}; auto const resolverResults = resolver.resolve(host, port, error); if (error) - return error; + return std::unexpected{error}; ASSERT(!resolverResults.empty(), "No results from resolver"); boost::beast::get_lowest_layer(stream_).expires_after(timeout); stream_.async_connect(resolverResults.begin()->endpoint(), yield[error]); if (error) - return error; - return std::nullopt; + return std::unexpected{error}; + return {}; } -std::optional +std::expected HttpAsyncClient::send( boost::beast::http::request request, boost::asio::yield_context yield, @@ -221,8 +221,8 @@ HttpAsyncClient::send( boost::beast::get_lowest_layer(stream_).expires_after(timeout); http::async_write(stream_, request, yield[error]); if (error) - return error; - return std::nullopt; + return std::unexpected{error}; + return {}; } std::expected, boost::system::error_code> diff --git a/tests/common/util/TestHttpClient.hpp b/tests/common/util/TestHttpClient.hpp index 1816a8af..1079ed3b 100644 --- a/tests/common/util/TestHttpClient.hpp +++ b/tests/common/util/TestHttpClient.hpp @@ -78,7 +78,7 @@ class HttpAsyncClient { public: HttpAsyncClient(boost::asio::io_context& ioContext); - std::optional + std::expected connect( std::string_view host, std::string_view port, @@ -86,7 +86,7 @@ public: std::chrono::steady_clock::duration timeout ); - std::optional + std::expected send( boost::beast::http::request request, boost::asio::yield_context yield, @@ -98,6 +98,7 @@ public: void gracefulShutdown(); + void disconnect(); }; diff --git a/tests/common/util/TestWebSocketClient.cpp b/tests/common/util/TestWebSocketClient.cpp index 690c0a80..9985f787 100644 --- a/tests/common/util/TestWebSocketClient.cpp +++ b/tests/common/util/TestWebSocketClient.cpp @@ -137,7 +137,7 @@ WebSocketAsyncClient::WebSocketAsyncClient(boost::asio::io_context& ioContext) : { } -std::optional +std::expected WebSocketAsyncClient::connect( std::string const& host, std::string const& port, @@ -153,7 +153,7 @@ WebSocketAsyncClient::connect( boost::beast::get_lowest_layer(stream_).expires_after(timeout); stream_.next_layer().async_connect(results, yield[error]); if (error) - return error; + return std::unexpected{error}; boost::beast::websocket::stream_base::timeout wsTimeout = boost::beast::websocket::stream_base::timeout::suggested(boost::beast::role_type::client); @@ -173,12 +173,12 @@ WebSocketAsyncClient::connect( stream_.async_handshake(fmt::format("{}:{}", host, port), "/", yield[error]); if (error) - return error; + return std::unexpected{error}; - return std::nullopt; + return {}; } -std::optional +std::expected WebSocketAsyncClient::send( boost::asio::yield_context yield, std::string_view message, @@ -190,8 +190,8 @@ WebSocketAsyncClient::send( ); if (error) - return error; - return std::nullopt; + return std::unexpected{error}; + return {}; } std::expected diff --git a/tests/common/util/TestWebSocketClient.hpp b/tests/common/util/TestWebSocketClient.hpp index c8ba064a..726574de 100644 --- a/tests/common/util/TestWebSocketClient.hpp +++ b/tests/common/util/TestWebSocketClient.hpp @@ -56,7 +56,7 @@ class WebSocketAsyncClient { public: WebSocketAsyncClient(boost::asio::io_context& ioContext); - std::optional + std::expected connect( std::string const& host, std::string const& port, @@ -65,7 +65,7 @@ public: std::vector additionalHeaders = {} ); - std::optional + std::expected send(boost::asio::yield_context yield, std::string_view message, std::chrono::steady_clock::duration timeout); std::expected diff --git a/tests/common/web/ng/MockConnection.hpp b/tests/common/web/ng/MockConnection.hpp index 193e0922..85b1dbce 100644 --- a/tests/common/web/ng/MockConnection.hpp +++ b/tests/common/web/ng/MockConnection.hpp @@ -48,7 +48,7 @@ struct MockConnectionImpl : web::ng::Connection { MOCK_METHOD(void, setTimeout, (std::chrono::steady_clock::duration), (override)); - using SendReturnType = std::optional; + using SendReturnType = std::expected; MOCK_METHOD(SendReturnType, send, (web::ng::Response, boost::asio::yield_context), (override)); using ReceiveReturnType = std::expected; diff --git a/tests/common/web/ng/impl/MockHttpConnection.hpp b/tests/common/web/ng/impl/MockHttpConnection.hpp index 7288a5f8..0d200ff4 100644 --- a/tests/common/web/ng/impl/MockHttpConnection.hpp +++ b/tests/common/web/ng/impl/MockHttpConnection.hpp @@ -44,7 +44,7 @@ struct MockHttpConnectionImpl : web::ng::impl::UpgradableConnection { MOCK_METHOD(void, setTimeout, (std::chrono::steady_clock::duration), (override)); - using SendReturnType = std::optional; + using SendReturnType = std::expected; MOCK_METHOD(SendReturnType, send, (web::ng::Response, boost::asio::yield_context), (override)); MOCK_METHOD( diff --git a/tests/common/web/ng/impl/MockWsConnection.hpp b/tests/common/web/ng/impl/MockWsConnection.hpp index 94445773..ee73158c 100644 --- a/tests/common/web/ng/impl/MockWsConnection.hpp +++ b/tests/common/web/ng/impl/MockWsConnection.hpp @@ -42,7 +42,7 @@ struct MockWsConnectionImpl : web::ng::impl::WsConnectionBase { MOCK_METHOD(void, setTimeout, (std::chrono::steady_clock::duration), (override)); - using SendReturnType = std::optional; + using SendReturnType = std::expected; MOCK_METHOD(SendReturnType, send, (web::ng::Response, boost::asio::yield_context), (override)); using ReceiveReturnType = std::expected; @@ -50,13 +50,7 @@ struct MockWsConnectionImpl : web::ng::impl::WsConnectionBase { MOCK_METHOD(void, close, (boost::asio::yield_context), (override)); - using SendBufferReturnType = std::optional; - MOCK_METHOD( - SendBufferReturnType, - sendShared, - (std::shared_ptr, boost::asio::yield_context), - (override) - ); + MOCK_METHOD(SendReturnType, sendShared, (std::shared_ptr, boost::asio::yield_context), (override)); }; using MockWsConnection = testing::NiceMock; diff --git a/tests/unit/web/ng/ServerTests.cpp b/tests/unit/web/ng/ServerTests.cpp index af83b3d9..2221c66c 100644 --- a/tests/unit/web/ng/ServerTests.cpp +++ b/tests/unit/web/ng/ServerTests.cpp @@ -261,9 +261,9 @@ TEST_F(ServerHttpTest, ClientDisconnects) { HttpAsyncClient client{ctx_}; util::spawn(ctx_, [&](boost::asio::yield_context yield) { - auto maybeError = + auto expectedSuccess = client.connect("127.0.0.1", std::to_string(serverPort_), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); client.disconnect(); server_->stop(yield); @@ -312,16 +312,17 @@ TEST_F(ServerHttpTest, OnConnectCheck) return {}; }); - auto maybeError = + auto expectedSuccess = client.connect("127.0.0.1", std::to_string(serverPort), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); // Have to send a request here because the server does async_detect_ssl() which waits for some data to appear - client.send( + expectedSuccess = client.send( http::request{http::verb::get, "/", 11, requestMessage_}, yield, std::chrono::milliseconds{100} ); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); // Wait for the onConnectCheck to be called timer.expires_after(std::chrono::milliseconds{100}); @@ -374,16 +375,17 @@ TEST_F(ServerHttpTest, OnConnectCheckFailed) }); util::spawn(ctx_, [&](boost::asio::yield_context yield) { - auto maybeError = + auto expectedSuccess = client.connect("127.0.0.1", std::to_string(serverPort), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); // Have to send a request here because the server does async_detect_ssl() which waits for some data to appear - client.send( + expectedSuccess = client.send( http::request{http::verb::get, "/", 11, requestMessage_}, yield, std::chrono::milliseconds{100} ); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); auto const response = client.receive(yield, std::chrono::milliseconds{100}); [&]() { ASSERT_TRUE(response.has_value()) << response.error().message(); }(); @@ -434,15 +436,17 @@ TEST_F(ServerHttpTest, OnDisconnectHook) EXPECT_CALL(onDisconnectHookMock, Call).WillOnce([&timer](auto&&) { timer.cancel(); }); - auto maybeError = + auto expectedSuccess = client.connect("127.0.0.1", std::to_string(serverPort), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); - client.send( + // Have to send a request here because the server does async_detect_ssl() which waits for some data to appear + expectedSuccess = client.send( http::request{http::verb::get, "/", 11, requestMessage_}, yield, std::chrono::milliseconds{100} ); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); client.gracefulShutdown(); @@ -463,17 +467,17 @@ TEST_F(ServerHttpTest, ClientIsDisconnectedIfServerStopped) { HttpAsyncClient client{ctx_}; util::spawn(ctx_, [&](boost::asio::yield_context yield) { - auto maybeError = + auto expectedSuccess = client.connect("127.0.0.1", std::to_string(serverPort_), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); // Have to send a request here because the server does async_detect_ssl() which waits for some data to appear - maybeError = client.send( + expectedSuccess = client.send( http::request{http::verb::get, "/", 11, requestMessage_}, yield, std::chrono::milliseconds{100} ); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); auto message = client.receive(yield, std::chrono::milliseconds{100}); EXPECT_TRUE(message.has_value()) << message.error().message(); @@ -498,13 +502,13 @@ TEST_P(ServerHttpTest, RequestResponse) Response const response{http::status::ok, "some response", Request{request}}; util::spawn(ctx_, [&](boost::asio::yield_context yield) { - auto maybeError = + auto expectedSuccess = client.connect("127.0.0.1", std::to_string(serverPort_), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); for ([[maybe_unused]] auto i : std::ranges::iota_view{0, 3}) { - maybeError = client.send(request, yield, std::chrono::milliseconds{100}); - EXPECT_FALSE(maybeError.has_value()) << maybeError->message(); + expectedSuccess = client.send(request, yield, std::chrono::milliseconds{100}); + EXPECT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); auto const expectedResponse = client.receive(yield, std::chrono::milliseconds{100}); [&]() { ASSERT_TRUE(expectedResponse.has_value()) << expectedResponse.error().message(); }(); @@ -548,9 +552,9 @@ TEST_F(ServerTest, WsClientDisconnects) WebSocketAsyncClient client{ctx_}; util::spawn(ctx_, [&](boost::asio::yield_context yield) { - auto maybeError = + auto expectedSuccess = client.connect("127.0.0.1", std::to_string(serverPort_), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); client.close(); server_->stop(yield); @@ -570,13 +574,13 @@ TEST_F(ServerTest, WsRequestResponse) Response const response{http::status::ok, "some response", Request{requestMessage_, headers}}; util::spawn(ctx_, [&](boost::asio::yield_context yield) { - auto maybeError = + auto expectedSuccess = client.connect("127.0.0.1", std::to_string(serverPort_), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); for ([[maybe_unused]] auto i : std::ranges::iota_view{0, 3}) { - maybeError = client.send(yield, requestMessage_, std::chrono::milliseconds{100}); - EXPECT_FALSE(maybeError.has_value()) << maybeError->message(); + expectedSuccess = client.send(yield, requestMessage_, std::chrono::milliseconds{100}); + EXPECT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); auto const expectedResponse = client.receive(yield, std::chrono::milliseconds{100}); [&]() { ASSERT_TRUE(expectedResponse.has_value()) << expectedResponse.error().message(); }(); @@ -608,10 +612,10 @@ TEST_F(ServerTest, WsClientIsDisconnectedIfServerStopped) { WebSocketAsyncClient client{ctx_}; util::spawn(ctx_, [&](boost::asio::yield_context yield) { - auto maybeError = + auto expectedSuccess = client.connect("127.0.0.1", std::to_string(serverPort_), yield, std::chrono::milliseconds{100}); - EXPECT_TRUE(maybeError.has_value()); - EXPECT_EQ(maybeError.value().value(), static_cast(boost::beast::websocket::error::upgrade_declined)); + EXPECT_FALSE(expectedSuccess.has_value()); + EXPECT_EQ(expectedSuccess.error().value(), static_cast(boost::beast::websocket::error::upgrade_declined)); ctx_.stop(); }); diff --git a/tests/unit/web/ng/SubscriptionContextTests.cpp b/tests/unit/web/ng/SubscriptionContextTests.cpp index 8d1061e1..285bce45 100644 --- a/tests/unit/web/ng/SubscriptionContextTests.cpp +++ b/tests/unit/web/ng/SubscriptionContextTests.cpp @@ -65,10 +65,13 @@ TEST_F(NgSubscriptionContextTests, Send) auto subscriptionContext = makeSubscriptionContext(yield); auto const message = std::make_shared("some message"); - EXPECT_CALL(connection_, sendShared).WillOnce([&message](std::shared_ptr sendingMessage, auto&&) { - EXPECT_EQ(sendingMessage, message); - return std::nullopt; - }); + EXPECT_CALL(connection_, sendShared) + .WillOnce( + [&message](std::shared_ptr sendingMessage, auto&&) -> std::expected { + EXPECT_EQ(sendingMessage, message); + return {}; + } + ); subscriptionContext.send(message); subscriptionContext.disconnect(yield); }); @@ -84,16 +87,24 @@ TEST_F(NgSubscriptionContextTests, SendOrder) testing::Sequence const sequence; EXPECT_CALL(connection_, sendShared) .InSequence(sequence) - .WillOnce([&message1](std::shared_ptr sendingMessage, auto&&) { - EXPECT_EQ(sendingMessage, message1); - return std::nullopt; - }); + .WillOnce( + [&message1]( + std::shared_ptr sendingMessage, auto&& + ) -> std::expected { + EXPECT_EQ(sendingMessage, message1); + return {}; + } + ); EXPECT_CALL(connection_, sendShared) .InSequence(sequence) - .WillOnce([&message2](std::shared_ptr sendingMessage, auto&&) { - EXPECT_EQ(sendingMessage, message2); - return std::nullopt; - }); + .WillOnce( + [&message2]( + std::shared_ptr sendingMessage, auto&& + ) -> std::expected { + EXPECT_EQ(sendingMessage, message2); + return {}; + } + ); subscriptionContext.send(message1); subscriptionContext.send(message2); @@ -109,7 +120,7 @@ TEST_F(NgSubscriptionContextTests, SendFailed) EXPECT_CALL(connection_, sendShared).WillOnce([&message](std::shared_ptr sendingMessage, auto&&) { EXPECT_EQ(sendingMessage, message); - return boost::system::errc::make_error_code(boost::system::errc::not_supported); + return std::unexpected{boost::system::errc::make_error_code(boost::system::errc::not_supported)}; }); EXPECT_CALL(errorHandler_, Call).WillOnce(testing::Return(true)); EXPECT_CALL(connection_, close); @@ -125,11 +136,15 @@ TEST_F(NgSubscriptionContextTests, SendTooManySubscriptions) auto const message = std::make_shared("message1"); EXPECT_CALL(connection_, sendShared) - .WillOnce([&message](std::shared_ptr sendingMessage, boost::asio::yield_context innerYield) { - boost::asio::post(innerYield); // simulate send is slow by switching to another coroutine - EXPECT_EQ(sendingMessage, message); - return std::nullopt; - }); + .WillOnce( + [&message]( + std::shared_ptr sendingMessage, boost::asio::yield_context innerYield + ) -> std::expected { + boost::asio::post(innerYield); // simulate send is slow by switching to another coroutine + EXPECT_EQ(sendingMessage, message); + return {}; + } + ); EXPECT_CALL(connection_, close); subscriptionContext.send(message); diff --git a/tests/unit/web/ng/impl/ConnectionHandlerTests.cpp b/tests/unit/web/ng/impl/ConnectionHandlerTests.cpp index 2dfcce9e..f944abc5 100644 --- a/tests/unit/web/ng/impl/ConnectionHandlerTests.cpp +++ b/tests/unit/web/ng/impl/ConnectionHandlerTests.cpp @@ -173,10 +173,11 @@ TEST_F(ConnectionHandlerSequentialProcessingTest, Receive_Handle_NoHandler_Send) .WillOnce(Return(makeRequest("some_request", headers))) .WillOnce(Return(makeError(websocket::error::closed))); - EXPECT_CALL(*mockHttpConnection, send).WillOnce([](Response response, auto&&) { - EXPECT_EQ(response.message(), "WebSocket is not supported by this server"); - return std::nullopt; - }); + EXPECT_CALL(*mockHttpConnection, send) + .WillOnce([](Response response, auto&&) -> std::expected { + EXPECT_EQ(response.message(), "WebSocket is not supported by this server"); + return {}; + }); EXPECT_CALL(onDisconnectMock, Call).WillOnce([connectionPtr = mockHttpConnection.get()](Connection const& c) { EXPECT_EQ(&c, connectionPtr); @@ -197,13 +198,14 @@ TEST_F(ConnectionHandlerSequentialProcessingTest, Receive_Handle_BadTarget_Send) .WillOnce(Return(makeRequest(http::request{http::verb::get, target, 11, requestMessage}))) .WillOnce(Return(makeError(http::error::end_of_stream))); - EXPECT_CALL(*mockHttpConnection, send).WillOnce([](Response response, auto&&) { - EXPECT_EQ(response.message(), "Bad target"); - auto const httpResponse = std::move(response).intoHttpResponse(); - EXPECT_EQ(httpResponse.result(), http::status::bad_request); - EXPECT_EQ(httpResponse.version(), 11); - return std::nullopt; - }); + EXPECT_CALL(*mockHttpConnection, send) + .WillOnce([](Response response, auto&&) -> std::expected { + EXPECT_EQ(response.message(), "Bad target"); + auto const httpResponse = std::move(response).intoHttpResponse(); + EXPECT_EQ(httpResponse.result(), http::status::bad_request); + EXPECT_EQ(httpResponse.version(), 11); + return {}; + }); EXPECT_CALL(onDisconnectMock, Call).WillOnce([connectionPtr = mockHttpConnection.get()](Connection const& c) { EXPECT_EQ(&c, connectionPtr); @@ -221,10 +223,11 @@ TEST_F(ConnectionHandlerSequentialProcessingTest, Receive_Handle_BadMethod_Send) .WillOnce(Return(makeRequest(http::request{http::verb::acl, "/", 11}))) .WillOnce(Return(makeError(http::error::end_of_stream))); - EXPECT_CALL(*mockHttpConnection, send).WillOnce([](Response response, auto&&) { - EXPECT_EQ(response.message(), "Unsupported http method"); - return std::nullopt; - }); + EXPECT_CALL(*mockHttpConnection, send) + .WillOnce([](Response response, auto&&) -> std::expected { + EXPECT_EQ(response.message(), "Unsupported http method"); + return {}; + }); EXPECT_CALL(onDisconnectMock, Call).WillOnce([connectionPtr = mockHttpConnection.get()](Connection const& c) { EXPECT_EQ(&c, connectionPtr); @@ -255,10 +258,11 @@ TEST_F(ConnectionHandlerSequentialProcessingTest, Receive_Handle_Send) return Response(http::status::ok, responseMessage, request); }); - EXPECT_CALL(*mockWsConnection, send).WillOnce([&responseMessage](Response response, auto&&) { - EXPECT_EQ(response.message(), responseMessage); - return std::nullopt; - }); + EXPECT_CALL(*mockWsConnection, send) + .WillOnce([&responseMessage](Response response, auto&&) -> std::expected { + EXPECT_EQ(response.message(), responseMessage); + return {}; + }); EXPECT_CALL(onDisconnectMock, Call).WillOnce([connectionPtr = mockWsConnection.get()](Connection const& c) { EXPECT_EQ(&c, connectionPtr); @@ -290,13 +294,17 @@ TEST_F(ConnectionHandlerSequentialProcessingTest, SendSubscriptionMessage) return Response(http::status::ok, "", request); }); - EXPECT_CALL(*mockWsConnection, send).WillOnce(Return(std::nullopt)); + EXPECT_CALL(*mockWsConnection, send).WillOnce(Return(std::expected{})); EXPECT_CALL(*mockWsConnection, sendShared) - .WillOnce([&subscriptionMessage](std::shared_ptr sendingMessage, auto&&) { - EXPECT_EQ(*sendingMessage, subscriptionMessage); - return std::nullopt; - }); + .WillOnce( + [&subscriptionMessage]( + std::shared_ptr sendingMessage, auto&& + ) -> std::expected { + EXPECT_EQ(*sendingMessage, subscriptionMessage); + return {}; + } + ); EXPECT_CALL(onDisconnectMock, Call).WillOnce([connectionPtr = mockWsConnection.get()](Connection const& c) { EXPECT_EQ(&c, connectionPtr); @@ -328,7 +336,7 @@ TEST_F(ConnectionHandlerSequentialProcessingTest, SubscriptionContextIsDisconnec return Response(http::status::ok, "", request); }); - EXPECT_CALL(*mockWsConnection, send).WillOnce(Return(std::nullopt)); + EXPECT_CALL(*mockWsConnection, send).WillOnce(Return(std::expected{})); EXPECT_CALL(onDisconnectHook, Call).After(expectationReceiveCalled); @@ -367,10 +375,11 @@ TEST_F(ConnectionHandlerSequentialProcessingTest, SubscriptionContextIsNullForHt return Response(http::status::ok, responseMessage, request); }); - EXPECT_CALL(*mockHttpConnection, send).WillOnce([&responseMessage](Response response, auto&&) { - EXPECT_EQ(response.message(), responseMessage); - return std::nullopt; - }); + EXPECT_CALL(*mockHttpConnection, send) + .WillOnce([&responseMessage](Response response, auto&&) -> std::expected { + EXPECT_EQ(response.message(), responseMessage); + return {}; + }); EXPECT_CALL( *mockHttpConnection, @@ -413,10 +422,12 @@ TEST_F(ConnectionHandlerSequentialProcessingTest, Receive_Handle_Send_Loop) return Response(http::status::ok, responseMessage, request); }); - EXPECT_CALL(*mockHttpConnection, send).Times(3).WillRepeatedly([&responseMessage](Response response, auto&&) { - EXPECT_EQ(response.message(), responseMessage); - return std::nullopt; - }); + EXPECT_CALL(*mockHttpConnection, send) + .Times(3) + .WillRepeatedly([&responseMessage](Response response, auto&&) -> std::expected { + EXPECT_EQ(response.message(), responseMessage); + return {}; + }); EXPECT_CALL( *mockHttpConnection, @@ -456,7 +467,7 @@ TEST_F(ConnectionHandlerSequentialProcessingTest, Receive_Handle_SendError) EXPECT_CALL(*mockHttpConnection, send).WillOnce([&responseMessage](Response response, auto&&) { EXPECT_EQ(response.message(), responseMessage); - return makeError(http::error::end_of_stream).error(); + return makeError(http::error::end_of_stream); }); EXPECT_CALL(onDisconnectMock, Call).WillOnce([connectionPtr = mockHttpConnection.get()](Connection const& c) { @@ -498,7 +509,7 @@ TEST_F(ConnectionHandlerSequentialProcessingTest, OnIpChangeHookCalledWhenSentFr EXPECT_CALL(*mockHttpConnectionFromProxy, send).WillOnce([&responseMessage](Response response, auto&&) { EXPECT_EQ(response.message(), responseMessage); - return makeError(http::error::end_of_stream).error(); + return makeError(http::error::end_of_stream); }); EXPECT_CALL(onDisconnectMock, Call) @@ -542,12 +553,12 @@ TEST_F(ConnectionHandlerSequentialProcessingTest, Stop) send(testing::ResultOf([](Response const& r) { return r.message(); }, responseMessage), testing::_) ) .Times(3) - .WillRepeatedly([&](auto&&, auto&&) { + .WillRepeatedly([&](auto&&, auto&&) -> std::expected { ++numCalls; if (numCalls == 3) util::spawn(ctx_, [this](auto yield) { connectionHandler.stop(yield); }); - return std::nullopt; + return {}; }); EXPECT_CALL( @@ -659,10 +670,11 @@ TEST_F(ConnectionHandlerParallelProcessingTest, Receive_Handle_Send) return Response(http::status::ok, responseMessage, request); }); - EXPECT_CALL(*mockWsConnection, send).WillOnce([&responseMessage](Response response, auto&&) { - EXPECT_EQ(response.message(), responseMessage); - return std::nullopt; - }); + EXPECT_CALL(*mockWsConnection, send) + .WillOnce([&responseMessage](Response response, auto&&) -> std::expected { + EXPECT_EQ(response.message(), responseMessage); + return {}; + }); EXPECT_CALL(onDisconnectMock, Call).WillOnce([connectionPtr = mockWsConnection.get()](Connection const& c) { EXPECT_EQ(&c, connectionPtr); @@ -699,10 +711,11 @@ TEST_F(ConnectionHandlerParallelProcessingTest, OnIpChangeHookCalledWhenSentFrom return Response(http::status::ok, responseMessage, request); }); - EXPECT_CALL(*mockWsConnectionFromProxy, send).WillOnce([&responseMessage](Response response, auto&&) { - EXPECT_EQ(response.message(), responseMessage); - return std::nullopt; - }); + EXPECT_CALL(*mockWsConnectionFromProxy, send) + .WillOnce([&responseMessage](Response response, auto&&) -> std::expected { + EXPECT_EQ(response.message(), responseMessage); + return {}; + }); EXPECT_CALL(onDisconnectMock, Call) .WillOnce([this, connectionPtr = mockWsConnectionFromProxy.get()](Connection const& c) { @@ -738,10 +751,12 @@ TEST_F(ConnectionHandlerParallelProcessingTest, Receive_Handle_Send_Loop) return Response(http::status::ok, responseMessage, request); }); - EXPECT_CALL(*mockWsConnection, send).Times(2).WillRepeatedly([&responseMessage](Response response, auto&&) { - EXPECT_EQ(response.message(), responseMessage); - return std::nullopt; - }); + EXPECT_CALL(*mockWsConnection, send) + .Times(2) + .WillRepeatedly([&responseMessage](Response response, auto&&) -> std::expected { + EXPECT_EQ(response.message(), responseMessage); + return {}; + }); EXPECT_CALL(onDisconnectMock, Call).WillOnce([connectionPtr = mockWsConnection.get()](Connection const& c) { EXPECT_EQ(&c, connectionPtr); @@ -787,7 +802,7 @@ TEST_F(ConnectionHandlerParallelProcessingTest, Receive_Handle_Send_Loop_TooMany send(testing::ResultOf([](Response response) { return response.message(); }, responseMessage), testing::_) ) .Times(3) - .WillRepeatedly(Return(std::nullopt)); + .WillRepeatedly(Return(std::expected{})); EXPECT_CALL( *mockWsConnection, @@ -799,7 +814,7 @@ TEST_F(ConnectionHandlerParallelProcessingTest, Receive_Handle_Send_Loop_TooMany ) ) .Times(2) - .WillRepeatedly(Return(std::nullopt)); + .WillRepeatedly(Return(std::expected{})); EXPECT_CALL(onDisconnectMock, Call).WillOnce([connectionPtr = mockWsConnection.get()](Connection const& c) { EXPECT_EQ(&c, connectionPtr); diff --git a/tests/unit/web/ng/impl/HttpConnectionTests.cpp b/tests/unit/web/ng/impl/HttpConnectionTests.cpp index 1b5eae38..ee2f24a0 100644 --- a/tests/unit/web/ng/impl/HttpConnectionTests.cpp +++ b/tests/unit/web/ng/impl/HttpConnectionTests.cpp @@ -80,8 +80,9 @@ protected: TEST_F(HttpConnectionTests, wasUpgraded) { util::spawn(ctx_, [this](boost::asio::yield_context yield) { - auto maybeError = httpClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + auto expectedSuccess = + httpClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); }); runSpawn([this](boost::asio::yield_context yield) { @@ -95,11 +96,12 @@ TEST_F(HttpConnectionTests, Receive) request_.set(boost::beast::http::field::user_agent, "test_client"); util::spawn(ctx_, [this](boost::asio::yield_context yield) { - auto maybeError = httpClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + auto expectedSuccess = + httpClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); - maybeError = httpClient_.send(request_, yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + expectedSuccess = httpClient_.send(request_, yield, std::chrono::milliseconds{100}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); }); runSpawn([this](boost::asio::yield_context yield) { @@ -123,8 +125,9 @@ TEST_F(HttpConnectionTests, Receive) TEST_F(HttpConnectionTests, ReceiveTimeout) { util::spawn(ctx_, [this](boost::asio::yield_context yield) { - auto maybeError = httpClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{1}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + auto expectedSuccess = + httpClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{1}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); }); runSpawn([this](boost::asio::yield_context yield) { @@ -138,8 +141,9 @@ TEST_F(HttpConnectionTests, ReceiveTimeout) TEST_F(HttpConnectionTests, ReceiveClientDisconnected) { util::spawn(ctx_, [this](boost::asio::yield_context yield) { - auto maybeError = httpClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{1}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + auto expectedSuccess = + httpClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{1}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); httpClient_.disconnect(); }); @@ -157,11 +161,12 @@ TEST_F(HttpConnectionTests, Send) Response const response{http::status::ok, "some response data", request}; util::spawn(ctx_, [this, response = response](boost::asio::yield_context yield) mutable { - auto maybeError = httpClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + auto expectedSuccess = + httpClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); auto const expectedResponse = httpClient_.receive(yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_TRUE(expectedResponse.has_value()) << maybeError->message(); }(); + [&]() { ASSERT_TRUE(expectedResponse.has_value()) << expectedResponse.error().message(); }(); auto const receivedResponse = expectedResponse.value(); auto const sentResponse = std::move(response).intoHttpResponse(); @@ -173,8 +178,8 @@ TEST_F(HttpConnectionTests, Send) runSpawn([this, &response](boost::asio::yield_context yield) { auto connection = acceptConnection(yield); - auto maybeError = connection->send(response, yield); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + auto expectedSuccess = connection->send(response, yield); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); }); } @@ -184,8 +189,9 @@ TEST_F(HttpConnectionTests, SendMultipleTimes) Response const response{http::status::ok, "some response data", request}; util::spawn(ctx_, [this, response = response](boost::asio::yield_context yield) mutable { - auto maybeError = httpClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + auto expectedSuccess = + httpClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); for ([[maybe_unused]] auto i : std::ranges::iota_view{0, 3}) { auto const expectedResponse = httpClient_.receive(yield, std::chrono::milliseconds{100}); @@ -204,8 +210,8 @@ TEST_F(HttpConnectionTests, SendMultipleTimes) auto connection = acceptConnection(yield); for ([[maybe_unused]] auto i : std::ranges::iota_view{0, 3}) { - auto maybeError = connection->send(response, yield); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + auto expectedSuccess = connection->send(response, yield); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); } }); } @@ -216,9 +222,9 @@ TEST_F(HttpConnectionTests, SendMultipleTimesFromMultipleCoroutines) Response const response{http::status::ok, "some response data", request}; util::spawn(ctx_, [this, response = response](boost::asio::yield_context yield) mutable { - auto const maybeError = + auto const expectedSuccess = httpClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); for ([[maybe_unused]] auto i : std::ranges::iota_view{0, 3}) { auto const expectedResponse = httpClient_.receive(yield, std::chrono::milliseconds{100}); @@ -239,8 +245,8 @@ TEST_F(HttpConnectionTests, SendMultipleTimesFromMultipleCoroutines) util::CoroutineGroup group{yield}; for ([[maybe_unused]] auto i : std::ranges::iota_view{0, 3}) { group.spawn(yield, [&response, &connection](boost::asio::yield_context innerYield) { - auto const maybeError = connection->send(response, innerYield); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + auto const expectedSuccess = connection->send(response, innerYield); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); }); } group.asyncWait(yield); @@ -251,9 +257,9 @@ TEST_F(HttpConnectionTests, SendMultipleTimesClientDisconnected) { Response const response{http::status::ok, "some response data", Request{request_}}; util::spawn(ctx_, [this, response = response](boost::asio::yield_context yield) mutable { - auto const maybeError = + auto const expectedSuccess = httpClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{1}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); auto const expectedResponse = httpClient_.receive(yield, std::chrono::milliseconds{100}); [&]() { ASSERT_TRUE(expectedResponse.has_value()) << expectedResponse.error().message(); }(); httpClient_.disconnect(); @@ -262,15 +268,15 @@ TEST_F(HttpConnectionTests, SendMultipleTimesClientDisconnected) runSpawn([this, &response](boost::asio::yield_context yield) { auto connection = acceptConnection(yield); connection->setTimeout(std::chrono::milliseconds{1}); - auto maybeError = connection->send(response, yield); + auto expectedSuccess = connection->send(response, yield); size_t counter{1}; - while (not maybeError.has_value() and counter < 100) { + while (expectedSuccess.has_value() and counter < 100) { ++counter; - maybeError = connection->send(response, yield); + expectedSuccess = connection->send(response, yield); } // Sending after getting an error should be safe - maybeError = connection->send(response, yield); - EXPECT_TRUE(maybeError.has_value()); + expectedSuccess = connection->send(response, yield); + EXPECT_FALSE(expectedSuccess.has_value()); EXPECT_LT(counter, 100); }); } @@ -279,20 +285,21 @@ TEST_F(HttpConnectionTests, SendClientDisconnected) { Response const response{http::status::ok, "some response data", Request{request_}}; util::spawn(ctx_, [this, response = response](boost::asio::yield_context yield) mutable { - auto maybeError = httpClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{1}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + auto expectedSuccess = + httpClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{1}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); httpClient_.disconnect(); }); runSpawn([this, &response](boost::asio::yield_context yield) { auto connection = acceptConnection(yield); connection->setTimeout(std::chrono::milliseconds{1}); - auto maybeError = connection->send(response, yield); + auto expectedSuccess = connection->send(response, yield); size_t counter{1}; - while (not maybeError.has_value() and counter < 100) { + while (expectedSuccess.has_value() and counter < 100) { ++counter; - maybeError = connection->send(response, yield); + expectedSuccess = connection->send(response, yield); } - EXPECT_TRUE(maybeError.has_value()); + EXPECT_FALSE(expectedSuccess.has_value()); EXPECT_LT(counter, 100); }); } @@ -300,15 +307,16 @@ TEST_F(HttpConnectionTests, SendClientDisconnected) TEST_F(HttpConnectionTests, Close) { util::spawn(ctx_, [this](boost::asio::yield_context yield) { - auto maybeError = httpClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + auto expectedSuccess = + httpClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); size_t counter{0}; - while (not maybeError.has_value() and counter < 100) { + while (expectedSuccess.has_value() and counter < 100) { ++counter; - maybeError = httpClient_.send(request_, yield, std::chrono::milliseconds{1}); + expectedSuccess = httpClient_.send(request_, yield, std::chrono::milliseconds{1}); } - EXPECT_TRUE(maybeError.has_value()); + EXPECT_FALSE(expectedSuccess.has_value()); EXPECT_LT(counter, 100); }); @@ -322,11 +330,12 @@ TEST_F(HttpConnectionTests, Close) TEST_F(HttpConnectionTests, IsUpgradeRequested_GotHttpRequest) { util::spawn(ctx_, [this](boost::asio::yield_context yield) { - auto maybeError = httpClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + auto expectedSuccess = + httpClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); - maybeError = httpClient_.send(request_, yield, std::chrono::milliseconds{1}); - EXPECT_FALSE(maybeError.has_value()) << maybeError->message(); + expectedSuccess = httpClient_.send(request_, yield, std::chrono::milliseconds{1}); + EXPECT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }); runSpawn([this](boost::asio::yield_context yield) { @@ -340,8 +349,9 @@ TEST_F(HttpConnectionTests, IsUpgradeRequested_GotHttpRequest) TEST_F(HttpConnectionTests, IsUpgradeRequested_FailedToFetch) { util::spawn(ctx_, [this](boost::asio::yield_context yield) { - auto maybeError = httpClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + auto expectedSuccess = + httpClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); }); runSpawn([this](boost::asio::yield_context yield) { @@ -357,8 +367,8 @@ TEST_F(HttpConnectionTests, Upgrade) WebSocketAsyncClient wsClient{ctx_}; util::spawn(ctx_, [this, &wsClient](boost::asio::yield_context yield) { - auto maybeError = wsClient.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + auto expectedSuccess = wsClient.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); }); runSpawn([this](boost::asio::yield_context yield) { @@ -375,8 +385,9 @@ TEST_F(HttpConnectionTests, Upgrade) TEST_F(HttpConnectionTests, Ip) { util::spawn(ctx_, [this](boost::asio::yield_context yield) mutable { - auto maybeError = httpClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + auto expectedSuccess = + httpClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); }); runSpawn([this](boost::asio::yield_context yield) { @@ -391,8 +402,9 @@ TEST_F(HttpConnectionTests, isAdminSetAdmin) EXPECT_CALL(adminSetter, Call).WillOnce(testing::Return(true)); util::spawn(ctx_, [this](boost::asio::yield_context yield) mutable { - auto maybeError = httpClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError->message(); }(); + auto expectedSuccess = + httpClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); }); runSpawn([&](boost::asio::yield_context yield) { diff --git a/tests/unit/web/ng/impl/WsConnectionTests.cpp b/tests/unit/web/ng/impl/WsConnectionTests.cpp index b66d8343..23959001 100644 --- a/tests/unit/web/ng/impl/WsConnectionTests.cpp +++ b/tests/unit/web/ng/impl/WsConnectionTests.cpp @@ -99,8 +99,9 @@ protected: TEST_F(WebWsConnectionTests, WasUpgraded) { util::spawn(ctx_, [this](boost::asio::yield_context yield) { - auto maybeError = wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError.value().message(); }(); + auto expectedSuccess = + wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); }); runSpawn([this](boost::asio::yield_context yield) { auto wsConnection = acceptConnection(yield); @@ -115,8 +116,9 @@ TEST_F(WebWsConnectionTests, DisconnectClientOnInactivity) std::thread clientThread{[&clientCtx]() { clientCtx.run(); }}; util::spawn(clientCtx, [&work, this](boost::asio::yield_context yield) { - auto maybeError = wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError.value().message(); }(); + auto expectedSuccess = + wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); boost::asio::steady_timer timer{yield.get_executor(), std::chrono::milliseconds{5}}; timer.async_wait(yield); work.reset(); @@ -143,8 +145,9 @@ TEST_F(WebWsConnectionTests, Send) Response const response{boost::beast::http::status::ok, "some response", request_}; util::spawn(ctx_, [this, &response](boost::asio::yield_context yield) { - auto maybeError = wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError.value().message(); }(); + auto expectedSuccess = + wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); auto const expectedMessage = wsClient_.receive(yield, std::chrono::milliseconds{100}); [&]() { ASSERT_TRUE(expectedMessage.has_value()) << expectedMessage.error().message(); }(); EXPECT_EQ(expectedMessage.value(), response.message()); @@ -152,8 +155,8 @@ TEST_F(WebWsConnectionTests, Send) runSpawn([this, &response](boost::asio::yield_context yield) { auto wsConnection = acceptConnection(yield); - auto maybeError = wsConnection->send(response, yield); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError.value().message(); }(); + auto expectedSuccess = wsConnection->send(response, yield); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); }); } @@ -162,8 +165,9 @@ TEST_F(WebWsConnectionTests, SendShared) auto const response = std::make_shared("some response"); util::spawn(ctx_, [this, &response](boost::asio::yield_context yield) { - auto maybeError = wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError.value().message(); }(); + auto expectedSuccess = + wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); auto const expectedMessage = wsClient_.receive(yield, std::chrono::milliseconds{100}); [&]() { ASSERT_TRUE(expectedMessage.has_value()) << expectedMessage.error().message(); }(); EXPECT_EQ(expectedMessage.value(), *response); @@ -171,8 +175,8 @@ TEST_F(WebWsConnectionTests, SendShared) runSpawn([this, &response](boost::asio::yield_context yield) { auto wsConnection = acceptConnection(yield); - auto maybeError = wsConnection->sendShared(response, yield); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError.value().message(); }(); + auto expectedSuccess = wsConnection->sendShared(response, yield); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); }); } @@ -181,8 +185,9 @@ TEST_F(WebWsConnectionTests, MultipleSend) Response const response{boost::beast::http::status::ok, "some response", request_}; util::spawn(ctx_, [this, &response](boost::asio::yield_context yield) { - auto maybeError = wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError.value().message(); }(); + auto expectedSuccess = + wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); for ([[maybe_unused]] auto i : std::ranges::iota_view{0, 3}) { auto const expectedMessage = wsClient_.receive(yield, std::chrono::milliseconds{100}); @@ -195,8 +200,8 @@ TEST_F(WebWsConnectionTests, MultipleSend) auto wsConnection = acceptConnection(yield); for ([[maybe_unused]] auto i : std::ranges::iota_view{0, 3}) { - auto maybeError = wsConnection->send(response, yield); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError.value().message(); }(); + auto expectedSuccess = wsConnection->send(response, yield); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); } }); } @@ -206,8 +211,9 @@ TEST_F(WebWsConnectionTests, MultipleSendFromMultipleCoroutines) Response const response{boost::beast::http::status::ok, "some response", request_}; util::spawn(ctx_, [this, &response](boost::asio::yield_context yield) { - auto maybeError = wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError.value().message(); }(); + auto expectedSuccess = + wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); for ([[maybe_unused]] auto i : std::ranges::iota_view{0, 3}) { auto const expectedMessage = wsClient_.receive(yield, std::chrono::milliseconds{100}); @@ -222,8 +228,8 @@ TEST_F(WebWsConnectionTests, MultipleSendFromMultipleCoroutines) util::CoroutineGroup group{yield}; for ([[maybe_unused]] auto i : std::ranges::iota_view{0, 3}) { group.spawn(yield, [&wsConnection, &response](boost::asio::yield_context innerYield) { - auto maybeError = wsConnection->send(response, innerYield); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError.value().message(); }(); + auto expectedSuccess = wsConnection->send(response, innerYield); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); }); } group.asyncWait(yield); @@ -235,21 +241,22 @@ TEST_F(WebWsConnectionTests, SendFailed) Response const response{boost::beast::http::status::ok, "some response", request_}; util::spawn(ctx_, [this](boost::asio::yield_context yield) { - auto maybeError = wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError.value().message(); }(); + auto expectedSuccess = + wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); wsClient_.close(); }); runSpawn([this, &response](boost::asio::yield_context yield) { auto wsConnection = acceptConnection(yield); wsConnection->setTimeout(std::chrono::milliseconds{1}); - std::optional maybeError; + std::expected expectedSuccess; size_t counter = 0; - while (not maybeError.has_value() and counter < 100) { - maybeError = wsConnection->send(response, yield); + while (expectedSuccess.has_value() and counter < 100) { + expectedSuccess = wsConnection->send(response, yield); ++counter; } - EXPECT_TRUE(maybeError.has_value()); + EXPECT_FALSE(expectedSuccess.has_value()); EXPECT_LT(counter, 100); }); } @@ -259,8 +266,9 @@ TEST_F(WebWsConnectionTests, SendFailedSendingFromMultipleCoroutines) Response const response{boost::beast::http::status::ok, "some response", request_}; util::spawn(ctx_, [this, &response](boost::asio::yield_context yield) { - auto maybeError = wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError.value().message(); }(); + auto expectedSuccess = + wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); auto const expectedMessage = wsClient_.receive(yield, std::chrono::milliseconds{100}); [&]() { ASSERT_TRUE(expectedMessage.has_value()) << expectedMessage.error().message(); }(); @@ -271,15 +279,15 @@ TEST_F(WebWsConnectionTests, SendFailedSendingFromMultipleCoroutines) runSpawn([this, &response](boost::asio::yield_context yield) { auto wsConnection = acceptConnection(yield); wsConnection->setTimeout(std::chrono::milliseconds{1}); - std::optional maybeError; + std::expected expectedSuccess; size_t counter = 0; - while (not maybeError.has_value() and counter < 100) { - maybeError = wsConnection->send(response, yield); + while (expectedSuccess.has_value() and counter < 100) { + expectedSuccess = wsConnection->send(response, yield); ++counter; } // Sending after getting an error should be safe - maybeError = wsConnection->send(response, yield); - EXPECT_TRUE(maybeError.has_value()); + expectedSuccess = wsConnection->send(response, yield); + EXPECT_FALSE(expectedSuccess.has_value()); EXPECT_LT(counter, 100); }); } @@ -287,11 +295,12 @@ TEST_F(WebWsConnectionTests, SendFailedSendingFromMultipleCoroutines) TEST_F(WebWsConnectionTests, Receive) { util::spawn(ctx_, [this](boost::asio::yield_context yield) { - auto maybeError = wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError.value().message(); }(); + auto expectedSuccess = + wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); - maybeError = wsClient_.send(yield, request_.message(), std::chrono::milliseconds{100}); - EXPECT_FALSE(maybeError.has_value()) << maybeError->message(); + expectedSuccess = wsClient_.send(yield, request_.message(), std::chrono::milliseconds{100}); + EXPECT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }); runSpawn([this](boost::asio::yield_context yield) { @@ -306,12 +315,13 @@ TEST_F(WebWsConnectionTests, Receive) TEST_F(WebWsConnectionTests, MultipleReceive) { util::spawn(ctx_, [this](boost::asio::yield_context yield) { - auto maybeError = wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError.value().message(); }(); + auto expectedSuccess = + wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); for ([[maybe_unused]] auto i : std::ranges::iota_view{0, 3}) { - maybeError = wsClient_.send(yield, request_.message(), std::chrono::milliseconds{100}); - EXPECT_FALSE(maybeError.has_value()) << maybeError->message(); + expectedSuccess = wsClient_.send(yield, request_.message(), std::chrono::milliseconds{100}); + EXPECT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); } }); @@ -329,8 +339,9 @@ TEST_F(WebWsConnectionTests, MultipleReceive) TEST_F(WebWsConnectionTests, ReceiveTimeout) { util::spawn(ctx_, [this](boost::asio::yield_context yield) { - auto maybeError = wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError.value().message(); }(); + auto expectedSuccess = + wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); }); runSpawn([this](boost::asio::yield_context yield) { @@ -345,8 +356,9 @@ TEST_F(WebWsConnectionTests, ReceiveTimeout) TEST_F(WebWsConnectionTests, ReceiveFailed) { util::spawn(ctx_, [this](boost::asio::yield_context yield) { - auto maybeError = wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError.value().message(); }(); + auto expectedSuccess = + wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); wsClient_.close(); }); @@ -361,8 +373,9 @@ TEST_F(WebWsConnectionTests, ReceiveFailed) TEST_F(WebWsConnectionTests, Close) { util::spawn(ctx_, [this](boost::asio::yield_context yield) { - auto maybeError = wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError.value().message(); }(); + auto expectedSuccess = + wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); auto const maybeMessage = wsClient_.receive(yield, std::chrono::milliseconds{100}); EXPECT_FALSE(maybeMessage.has_value()); EXPECT_THAT(maybeMessage.error().message(), testing::HasSubstr("was gracefully closed")); @@ -377,8 +390,9 @@ TEST_F(WebWsConnectionTests, Close) TEST_F(WebWsConnectionTests, CloseWhenConnectionIsAlreadyClosed) { util::spawn(ctx_, [this](boost::asio::yield_context yield) { - auto maybeError = wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError.value().message(); }(); + auto expectedSuccess = + wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); wsClient_.close(); }); @@ -393,8 +407,9 @@ TEST_F(WebWsConnectionTests, CloseWhenConnectionIsAlreadyClosed) TEST_F(WebWsConnectionTests, CloseCalledFromMultipleSubCoroutines) { util::spawn(ctx_, [this](boost::asio::yield_context yield) { - auto maybeError = wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); - [&]() { ASSERT_FALSE(maybeError.has_value()) << maybeError.value().message(); }(); + auto expectedSuccess = + wsClient_.connect("localhost", httpServer_.port(), yield, std::chrono::milliseconds{100}); + [&]() { ASSERT_TRUE(expectedSuccess.has_value()) << expectedSuccess.error().message(); }(); }); testing::StrictMock> closeCalled;