1 #include "boost/beast/core/buffers_to_string.hpp"
2 #include "boost/beast/http/serializer.hpp"
3 #include "file_test_utilities.hpp"
4 #include "http/http_body.hpp"
5 #include "http/http_response.hpp"
6 #include "utility.hpp"
7 
8 #include <boost/beast/core/file_base.hpp>
9 #include <boost/beast/core/file_posix.hpp>
10 #include <boost/beast/http/message.hpp>
11 #include <boost/beast/http/status.hpp>
12 
13 #include <cstdio>
14 #include <filesystem>
15 #include <string>
16 
17 #include "gtest/gtest.h"
18 namespace
19 {
20 void addHeaders(crow::Response& res)
21 {
22     res.addHeader("myheader", "myvalue");
23     res.keepAlive(true);
24     res.result(boost::beast::http::status::ok);
25 }
26 void verifyHeaders(crow::Response& res)
27 {
28     EXPECT_EQ(res.getHeaderValue("myheader"), "myvalue");
29     EXPECT_EQ(res.keepAlive(), true);
30     EXPECT_EQ(res.result(), boost::beast::http::status::ok);
31 }
32 
33 std::string getData(boost::beast::http::response<bmcweb::HttpBody>& m)
34 {
35     std::string ret;
36 
37     boost::beast::http::response_serializer<bmcweb::HttpBody> sr{m};
38     sr.split(true);
39     // Reads buffers into ret
40     auto reader = [&sr, &ret](const boost::system::error_code& ec2,
41                               const auto& buffer) {
42         EXPECT_FALSE(ec2);
43         std::string ret2 = boost::beast::buffers_to_string(buffer);
44         sr.consume(ret2.size());
45         ret += ret2;
46     };
47     boost::system::error_code ec;
48 
49     // Read headers
50     while (!sr.is_header_done())
51     {
52         sr.next(ec, reader);
53         EXPECT_FALSE(ec);
54     }
55     ret.clear();
56 
57     // Read body
58     while (!sr.is_done())
59     {
60         sr.next(ec, reader);
61         EXPECT_FALSE(ec);
62     }
63 
64     return ret;
65 }
66 
67 TEST(HttpResponse, Headers)
68 {
69     crow::Response res;
70     addHeaders(res);
71     verifyHeaders(res);
72 }
73 TEST(HttpResponse, StringBody)
74 {
75     crow::Response res;
76     addHeaders(res);
77     std::string_view bodyValue = "this is my new body";
78     res.write({bodyValue.data(), bodyValue.length()});
79     EXPECT_EQ(*res.body(), bodyValue);
80     verifyHeaders(res);
81 }
82 TEST(HttpResponse, HttpBody)
83 {
84     crow::Response res;
85     addHeaders(res);
86     TemporaryFileHandle temporaryFile("sample text");
87     res.openFile(temporaryFile.stringPath);
88 
89     verifyHeaders(res);
90 }
91 TEST(HttpResponse, HttpBodyWithFd)
92 {
93     crow::Response res;
94     addHeaders(res);
95     TemporaryFileHandle temporaryFile("sample text");
96     FILE* fd = fopen(temporaryFile.stringPath.c_str(), "r+");
97     res.openFd(fileno(fd));
98     verifyHeaders(res);
99     fclose(fd);
100 }
101 
102 TEST(HttpResponse, Base64HttpBodyWithFd)
103 {
104     crow::Response res;
105     addHeaders(res);
106     TemporaryFileHandle temporaryFile("sample text");
107     FILE* fd = fopen(temporaryFile.stringPath.c_str(), "r");
108     ASSERT_NE(fd, nullptr);
109     res.openFd(fileno(fd), bmcweb::EncodingType::Base64);
110     verifyHeaders(res);
111     fclose(fd);
112 }
113 
114 TEST(HttpResponse, BodyTransitions)
115 {
116     crow::Response res;
117     addHeaders(res);
118     TemporaryFileHandle temporaryFile("sample text");
119     res.openFile(temporaryFile.stringPath);
120 
121     verifyHeaders(res);
122     res.write("body text");
123 
124     verifyHeaders(res);
125 }
126 
127 std::string generateBigdata()
128 {
129     std::string result;
130     while (result.size() < 10000)
131     {
132         result += "sample text";
133     }
134     return result;
135 }
136 
137 TEST(HttpResponse, StringBodyWriterLarge)
138 {
139     crow::Response res;
140     std::string data = generateBigdata();
141     res.write(std::string(data));
142     EXPECT_EQ(getData(res.response), data);
143 }
144 
145 TEST(HttpResponse, Base64HttpBodyWriter)
146 {
147     crow::Response res;
148     std::string data = "sample text";
149     TemporaryFileHandle temporaryFile(data);
150     FILE* f = fopen(temporaryFile.stringPath.c_str(), "r+");
151     res.openFd(fileno(f), bmcweb::EncodingType::Base64);
152     EXPECT_EQ(getData(res.response), "c2FtcGxlIHRleHQ=");
153 }
154 
155 TEST(HttpResponse, Base64HttpBodyWriterLarge)
156 {
157     crow::Response res;
158     std::string data = generateBigdata();
159     TemporaryFileHandle temporaryFile(data);
160 
161     boost::beast::file_posix file;
162     boost::system::error_code ec;
163     file.open(temporaryFile.stringPath.c_str(), boost::beast::file_mode::read,
164               ec);
165     EXPECT_EQ(ec.value(), 0);
166     res.openFd(file.native_handle(), bmcweb::EncodingType::Base64);
167     EXPECT_EQ(getData(res.response), crow::utility::base64encode(data));
168 }
169 
170 TEST(HttpResponse, HttpBodyWriterLarge)
171 {
172     crow::Response res;
173     std::string data = generateBigdata();
174     TemporaryFileHandle temporaryFile(data);
175 
176     boost::beast::file_posix file;
177     boost::system::error_code ec;
178     file.open(temporaryFile.stringPath.c_str(), boost::beast::file_mode::read,
179               ec);
180     EXPECT_EQ(ec.value(), 0);
181     res.openFd(file.native_handle());
182     EXPECT_EQ(getData(res.response), data);
183 }
184 
185 } // namespace
186