1*40e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0
2*40e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors
38f79c5b6SEd Tanous #include "http/server_sent_event.hpp"
441fe81c2SEd Tanous #include "http_request.hpp"
58f79c5b6SEd Tanous
6f0b59af4SEd Tanous #include <boost/asio/buffer.hpp>
7f0b59af4SEd Tanous #include <boost/asio/io_context.hpp>
88d45b9cbSEd Tanous #include <boost/asio/read.hpp>
98f79c5b6SEd Tanous #include <boost/beast/_experimental/test/stream.hpp>
108f79c5b6SEd Tanous
11f0b59af4SEd Tanous #include <chrono>
128f79c5b6SEd Tanous #include <memory>
138f79c5b6SEd Tanous #include <string>
148f79c5b6SEd Tanous #include <string_view>
15f0b59af4SEd Tanous #include <utility>
168f79c5b6SEd Tanous
178f79c5b6SEd Tanous #include "gtest/gtest.h"
188f79c5b6SEd Tanous namespace crow
198f79c5b6SEd Tanous {
208f79c5b6SEd Tanous namespace sse_socket
218f79c5b6SEd Tanous {
228f79c5b6SEd Tanous
238f79c5b6SEd Tanous namespace
248f79c5b6SEd Tanous {
258f79c5b6SEd Tanous
TEST(ServerSentEvent,SseWorks)268f79c5b6SEd Tanous TEST(ServerSentEvent, SseWorks)
278f79c5b6SEd Tanous {
288f79c5b6SEd Tanous boost::asio::io_context io;
298f79c5b6SEd Tanous boost::beast::test::stream stream(io);
308f79c5b6SEd Tanous boost::beast::test::stream out(io);
318f79c5b6SEd Tanous stream.connect(out);
328f79c5b6SEd Tanous
33f80a87f2SEd Tanous Request req;
34f80a87f2SEd Tanous
358f79c5b6SEd Tanous bool openCalled = false;
36bd79bce8SPatrick Williams auto openHandler =
37bd79bce8SPatrick Williams [&openCalled](Connection&, const Request& /*handedReq*/) {
38f80a87f2SEd Tanous openCalled = true;
39f80a87f2SEd Tanous };
408f79c5b6SEd Tanous bool closeCalled = false;
418f79c5b6SEd Tanous auto closeHandler = [&closeCalled](Connection&) { closeCalled = true; };
428f79c5b6SEd Tanous
438f79c5b6SEd Tanous std::shared_ptr<ConnectionImpl<boost::beast::test::stream>> conn =
448f79c5b6SEd Tanous std::make_shared<ConnectionImpl<boost::beast::test::stream>>(
4593cf0ac2SEd Tanous std::move(stream), openHandler, closeHandler);
46f80a87f2SEd Tanous conn->start(req);
478f79c5b6SEd Tanous // Connect
488f79c5b6SEd Tanous {
498f79c5b6SEd Tanous constexpr std::string_view expected =
508f79c5b6SEd Tanous "HTTP/1.1 200 OK\r\n"
518f79c5b6SEd Tanous "Content-Type: text/event-stream\r\n"
528f79c5b6SEd Tanous "\r\n";
538f79c5b6SEd Tanous
54464924caSEd Tanous while (out.str().size() != expected.size() || !openCalled)
558f79c5b6SEd Tanous {
568f79c5b6SEd Tanous io.run_for(std::chrono::milliseconds(1));
578f79c5b6SEd Tanous }
588f79c5b6SEd Tanous
598f79c5b6SEd Tanous std::string eventContent;
608f79c5b6SEd Tanous eventContent.resize(expected.size());
618f79c5b6SEd Tanous boost::asio::read(out, boost::asio::buffer(eventContent));
628f79c5b6SEd Tanous
638f79c5b6SEd Tanous EXPECT_EQ(eventContent, expected);
648f79c5b6SEd Tanous EXPECT_TRUE(openCalled);
658f79c5b6SEd Tanous EXPECT_FALSE(closeCalled);
668f79c5b6SEd Tanous EXPECT_TRUE(out.str().empty());
678f79c5b6SEd Tanous }
688f79c5b6SEd Tanous // Send one event
698f79c5b6SEd Tanous {
706d799e14SEd Tanous conn->sendSseEvent("TestEventId", "TestEventContent");
718f79c5b6SEd Tanous std::string_view expected = "id: TestEventId\n"
728f79c5b6SEd Tanous "data: TestEventContent\n"
738f79c5b6SEd Tanous "\n";
748f79c5b6SEd Tanous
758f79c5b6SEd Tanous while (out.str().size() < expected.size())
768f79c5b6SEd Tanous {
778f79c5b6SEd Tanous io.run_for(std::chrono::milliseconds(1));
788f79c5b6SEd Tanous }
798f79c5b6SEd Tanous EXPECT_EQ(out.str(), expected);
808f79c5b6SEd Tanous
818f79c5b6SEd Tanous std::string eventContent;
828f79c5b6SEd Tanous eventContent.resize(expected.size());
838f79c5b6SEd Tanous boost::asio::read(out, boost::asio::buffer(eventContent));
848f79c5b6SEd Tanous
858f79c5b6SEd Tanous EXPECT_EQ(eventContent, expected);
868f79c5b6SEd Tanous EXPECT_TRUE(out.str().empty());
878f79c5b6SEd Tanous }
888f79c5b6SEd Tanous // Send second event
898f79c5b6SEd Tanous {
906d799e14SEd Tanous conn->sendSseEvent("TestEventId2", "TestEvent\nContent2");
91bd79bce8SPatrick Williams constexpr std::string_view expected =
92bd79bce8SPatrick Williams "id: TestEventId2\n"
938f79c5b6SEd Tanous "data: TestEvent\n"
948f79c5b6SEd Tanous "data: Content2\n"
958f79c5b6SEd Tanous "\n";
968f79c5b6SEd Tanous
978f79c5b6SEd Tanous while (out.str().size() < expected.size())
988f79c5b6SEd Tanous {
998f79c5b6SEd Tanous io.run_for(std::chrono::milliseconds(1));
1008f79c5b6SEd Tanous }
1018f79c5b6SEd Tanous
1028f79c5b6SEd Tanous std::string eventContent;
1038f79c5b6SEd Tanous eventContent.resize(expected.size());
1048f79c5b6SEd Tanous boost::asio::read(out, boost::asio::buffer(eventContent));
1058f79c5b6SEd Tanous EXPECT_EQ(eventContent, expected);
1068f79c5b6SEd Tanous EXPECT_TRUE(out.str().empty());
1078f79c5b6SEd Tanous }
1088f79c5b6SEd Tanous // close the remote
1098f79c5b6SEd Tanous {
1108f79c5b6SEd Tanous out.close();
1118f79c5b6SEd Tanous while (!closeCalled)
1128f79c5b6SEd Tanous {
1138f79c5b6SEd Tanous io.run_for(std::chrono::milliseconds(1));
1148f79c5b6SEd Tanous }
1158f79c5b6SEd Tanous }
1168f79c5b6SEd Tanous }
1178f79c5b6SEd Tanous } // namespace
1188f79c5b6SEd Tanous
1198f79c5b6SEd Tanous } // namespace sse_socket
1208f79c5b6SEd Tanous } // namespace crow
121