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