1 #include "boost_formatters.hpp" 2 #include "http/server_sent_event.hpp" 3 4 #include <boost/asio/buffer.hpp> 5 #include <boost/asio/io_context.hpp> 6 #include <boost/asio/read.hpp> 7 #include <boost/beast/_experimental/test/stream.hpp> 8 9 #include <chrono> 10 #include <memory> 11 #include <string> 12 #include <string_view> 13 #include <utility> 14 15 #include "gtest/gtest.h" 16 namespace crow 17 { 18 namespace sse_socket 19 { 20 21 namespace 22 { 23 24 TEST(ServerSentEvent, SseWorks) 25 { 26 boost::asio::io_context io; 27 boost::beast::test::stream stream(io); 28 boost::beast::test::stream out(io); 29 stream.connect(out); 30 31 bool openCalled = false; 32 auto openHandler = [&openCalled](Connection&) { openCalled = true; }; 33 bool closeCalled = false; 34 auto closeHandler = [&closeCalled](Connection&) { closeCalled = true; }; 35 36 std::shared_ptr<ConnectionImpl<boost::beast::test::stream>> conn = 37 std::make_shared<ConnectionImpl<boost::beast::test::stream>>( 38 std::move(stream), openHandler, closeHandler); 39 conn->start(); 40 // Connect 41 { 42 constexpr std::string_view expected = 43 "HTTP/1.1 200 OK\r\n" 44 "Content-Type: text/event-stream\r\n" 45 "\r\n"; 46 47 while (out.str().size() != expected.size()) 48 { 49 io.run_for(std::chrono::milliseconds(1)); 50 } 51 52 std::string eventContent; 53 eventContent.resize(expected.size()); 54 boost::asio::read(out, boost::asio::buffer(eventContent)); 55 56 EXPECT_EQ(eventContent, expected); 57 EXPECT_TRUE(openCalled); 58 EXPECT_FALSE(closeCalled); 59 EXPECT_TRUE(out.str().empty()); 60 } 61 // Send one event 62 { 63 conn->sendEvent("TestEventId", "TestEventContent"); 64 std::string_view expected = "id: TestEventId\n" 65 "data: TestEventContent\n" 66 "\n"; 67 68 while (out.str().size() < expected.size()) 69 { 70 io.run_for(std::chrono::milliseconds(1)); 71 } 72 EXPECT_EQ(out.str(), expected); 73 74 std::string eventContent; 75 eventContent.resize(expected.size()); 76 boost::asio::read(out, boost::asio::buffer(eventContent)); 77 78 EXPECT_EQ(eventContent, expected); 79 EXPECT_TRUE(out.str().empty()); 80 } 81 // Send second event 82 { 83 conn->sendEvent("TestEventId2", "TestEvent\nContent2"); 84 constexpr std::string_view expected = "id: TestEventId2\n" 85 "data: TestEvent\n" 86 "data: Content2\n" 87 "\n"; 88 89 while (out.str().size() < expected.size()) 90 { 91 io.run_for(std::chrono::milliseconds(1)); 92 } 93 94 std::string eventContent; 95 eventContent.resize(expected.size()); 96 boost::asio::read(out, boost::asio::buffer(eventContent)); 97 EXPECT_EQ(eventContent, expected); 98 EXPECT_TRUE(out.str().empty()); 99 } 100 // close the remote 101 { 102 out.close(); 103 while (!closeCalled) 104 { 105 io.run_for(std::chrono::milliseconds(1)); 106 } 107 } 108 } 109 } // namespace 110 111 } // namespace sse_socket 112 } // namespace crow 113