blob: 43b830d92bfc2b45091ba4add6cff69c5f44591b [file] [log] [blame]
Ed Tanous95c63072024-03-26 13:19:52 -07001#include "boost_formatters.hpp"
Ed Tanous8f79c5b2024-01-30 15:56:37 -08002#include "http/server_sent_event.hpp"
3
Ed Tanousf0b59af2024-03-20 13:38:04 -07004#include <boost/asio/buffer.hpp>
5#include <boost/asio/io_context.hpp>
Ed Tanous8d45b9c2024-04-08 17:50:10 -07006#include <boost/asio/read.hpp>
Ed Tanous8f79c5b2024-01-30 15:56:37 -08007#include <boost/beast/_experimental/test/stream.hpp>
8
Ed Tanousf0b59af2024-03-20 13:38:04 -07009#include <chrono>
Ed Tanous8f79c5b2024-01-30 15:56:37 -080010#include <memory>
11#include <string>
12#include <string_view>
Ed Tanousf0b59af2024-03-20 13:38:04 -070013#include <utility>
Ed Tanous8f79c5b2024-01-30 15:56:37 -080014
15#include "gtest/gtest.h"
16namespace crow
17{
18namespace sse_socket
19{
20
21namespace
22{
23
24TEST(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>>(
Ed Tanous93cf0ac2024-03-28 00:35:13 -070038 std::move(stream), openHandler, closeHandler);
Ed Tanous8f79c5b2024-01-30 15:56:37 -080039 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