summaryrefslogtreecommitdiff
path: root/test/http/server_sent_event_test.cpp
blob: 43b830d92bfc2b45091ba4add6cff69c5f44591b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include "boost_formatters.hpp"
#include "http/server_sent_event.hpp"

#include <boost/asio/buffer.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/read.hpp>
#include <boost/beast/_experimental/test/stream.hpp>

#include <chrono>
#include <memory>
#include <string>
#include <string_view>
#include <utility>

#include "gtest/gtest.h"
namespace crow
{
namespace sse_socket
{

namespace
{

TEST(ServerSentEvent, SseWorks)
{
    boost::asio::io_context io;
    boost::beast::test::stream stream(io);
    boost::beast::test::stream out(io);
    stream.connect(out);

    bool openCalled = false;
    auto openHandler = [&openCalled](Connection&) { openCalled = true; };
    bool closeCalled = false;
    auto closeHandler = [&closeCalled](Connection&) { closeCalled = true; };

    std::shared_ptr<ConnectionImpl<boost::beast::test::stream>> conn =
        std::make_shared<ConnectionImpl<boost::beast::test::stream>>(
            std::move(stream), openHandler, closeHandler);
    conn->start();
    // Connect
    {
        constexpr std::string_view expected =
            "HTTP/1.1 200 OK\r\n"
            "Content-Type: text/event-stream\r\n"
            "\r\n";

        while (out.str().size() != expected.size())
        {
            io.run_for(std::chrono::milliseconds(1));
        }

        std::string eventContent;
        eventContent.resize(expected.size());
        boost::asio::read(out, boost::asio::buffer(eventContent));

        EXPECT_EQ(eventContent, expected);
        EXPECT_TRUE(openCalled);
        EXPECT_FALSE(closeCalled);
        EXPECT_TRUE(out.str().empty());
    }
    // Send one event
    {
        conn->sendEvent("TestEventId", "TestEventContent");
        std::string_view expected = "id: TestEventId\n"
                                    "data: TestEventContent\n"
                                    "\n";

        while (out.str().size() < expected.size())
        {
            io.run_for(std::chrono::milliseconds(1));
        }
        EXPECT_EQ(out.str(), expected);

        std::string eventContent;
        eventContent.resize(expected.size());
        boost::asio::read(out, boost::asio::buffer(eventContent));

        EXPECT_EQ(eventContent, expected);
        EXPECT_TRUE(out.str().empty());
    }
    // Send second event
    {
        conn->sendEvent("TestEventId2", "TestEvent\nContent2");
        constexpr std::string_view expected = "id: TestEventId2\n"
                                              "data: TestEvent\n"
                                              "data: Content2\n"
                                              "\n";

        while (out.str().size() < expected.size())
        {
            io.run_for(std::chrono::milliseconds(1));
        }

        std::string eventContent;
        eventContent.resize(expected.size());
        boost::asio::read(out, boost::asio::buffer(eventContent));
        EXPECT_EQ(eventContent, expected);
        EXPECT_TRUE(out.str().empty());
    }
    // close the remote
    {
        out.close();
        while (!closeCalled)
        {
            io.run_for(std::chrono::milliseconds(1));
        }
    }
}
} // namespace

} // namespace sse_socket
} // namespace crow