blob: 1ee3853f780a5ddacf63ab0b700c9d8e2a0abd63 [file] [log] [blame]
Abhilash Raju8e3f7032023-07-17 08:53:11 -05001#include "boost/beast/core/flat_buffer.hpp"
2#include "boost/beast/http/serializer.hpp"
3#include "http/http_response.hpp"
4
5#include <filesystem>
6#include <fstream>
7#include <thread>
8
9#include "gtest/gtest.h"
10namespace
11{
12void addHeaders(crow::Response& res)
13{
14 res.addHeader("myheader", "myvalue");
15 res.keepAlive(true);
16 res.result(boost::beast::http::status::ok);
17}
18void verifyHeaders(crow::Response& res)
19{
20 EXPECT_EQ(res.getHeaderValue("myheader"), "myvalue");
21 EXPECT_EQ(res.keepAlive(), true);
22 EXPECT_EQ(res.result(), boost::beast::http::status::ok);
23}
24
Abhilash Rajub5f288d2023-11-08 22:32:44 -060025std::string makeFile(std::string_view sampleData)
Abhilash Raju8e3f7032023-07-17 08:53:11 -050026{
27 std::filesystem::path path = std::filesystem::temp_directory_path();
28 path /= "bmcweb_http_response_test_XXXXXXXXXXX";
29 std::string stringPath = path.string();
30 int fd = mkstemp(stringPath.data());
31 EXPECT_GT(fd, 0);
Abhilash Rajub5f288d2023-11-08 22:32:44 -060032 EXPECT_EQ(write(fd, sampleData.data(), sampleData.size()),
33 sampleData.size());
34 close(fd);
Abhilash Raju8e3f7032023-07-17 08:53:11 -050035 return stringPath;
36}
Abhilash Rajub5f288d2023-11-08 22:32:44 -060037
38void readHeader(boost::beast::http::serializer<false, bmcweb::FileBody>& sr)
39{
40 while (!sr.is_header_done())
41 {
42 boost::system::error_code ec;
43 sr.next(ec, [&sr](const boost::system::error_code& ec2,
44 const auto& buffer) {
45 ASSERT_FALSE(ec2);
46 sr.consume(boost::beast::buffer_bytes(buffer));
47 });
48 ASSERT_FALSE(ec);
49 }
50}
51
52std::string collectFromBuffers(
53 const auto& buffer,
54 boost::beast::http::serializer<false, bmcweb::FileBody>& sr)
55{
56 std::string ret;
57
58 for (auto iter = boost::asio::buffer_sequence_begin(buffer);
59 iter != boost::asio::buffer_sequence_end(buffer); ++iter)
60 {
61 const auto& innerBuf = *iter;
62 auto view = std::string_view(static_cast<const char*>(innerBuf.data()),
63 innerBuf.size());
64 ret += view;
65 sr.consume(innerBuf.size());
66 }
67 return ret;
68}
69
70std::string
71 readBody(boost::beast::http::serializer<false, bmcweb::FileBody>& sr)
72{
73 std::string ret;
74 while (!sr.is_done())
75 {
76 boost::system::error_code ec;
77 sr.next(ec, [&sr, &ret](const boost::system::error_code& ec2,
78 const auto& buffer) {
79 ASSERT_FALSE(ec2);
80 ret += collectFromBuffers(buffer, sr);
81 });
82 EXPECT_FALSE(ec);
83 }
84
85 return ret;
86}
87std::string getData(crow::Response::file_response& m)
88{
89 boost::beast::http::serializer<false, bmcweb::FileBody> sr{m};
90 std::stringstream ret;
91 sr.split(true);
92 readHeader(sr);
93 return readBody(sr);
94}
Abhilash Raju8e3f7032023-07-17 08:53:11 -050095TEST(HttpResponse, Defaults)
96{
97 crow::Response res;
98 EXPECT_EQ(
99 boost::variant2::holds_alternative<crow::Response::string_response>(
100 res.response),
101 true);
102}
103TEST(HttpResponse, Headers)
104{
105 crow::Response res;
106 addHeaders(res);
107 verifyHeaders(res);
108}
109TEST(HttpResponse, StringBody)
110{
111 crow::Response res;
112 addHeaders(res);
113 std::string_view bodyvalue = "this is my new body";
114 res.write({bodyvalue.data(), bodyvalue.length()});
115 EXPECT_EQ(*res.body(), bodyvalue);
116 verifyHeaders(res);
117}
118TEST(HttpResponse, FileBody)
119{
120 crow::Response res;
121 addHeaders(res);
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600122 std::string path = makeFile("sample text");
Abhilash Raju8e3f7032023-07-17 08:53:11 -0500123 res.openFile(path);
124
125 verifyHeaders(res);
126 std::filesystem::remove(path);
127}
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600128TEST(HttpResponse, FileBodyWithFd)
129{
130 crow::Response res;
131 addHeaders(res);
132 std::string path = makeFile("sample text");
133 FILE* fd = fopen(path.c_str(), "r+");
134 res.openFd(fileno(fd));
135 verifyHeaders(res);
136 fclose(fd);
137 std::filesystem::remove(path);
138}
139
140TEST(HttpResponse, Base64FileBodyWithFd)
141{
142 crow::Response res;
143 addHeaders(res);
144 std::string path = makeFile("sample text");
145 FILE* fd = fopen(path.c_str(), "r+");
146 res.openFd(fileno(fd), bmcweb::EncodingType::Base64);
147 verifyHeaders(res);
148 fclose(fd);
149 std::filesystem::remove(path);
150}
151
Abhilash Raju8e3f7032023-07-17 08:53:11 -0500152TEST(HttpResponse, BodyTransitions)
153{
154 crow::Response res;
155 addHeaders(res);
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600156 std::string path = makeFile("sample text");
Abhilash Raju8e3f7032023-07-17 08:53:11 -0500157 res.openFile(path);
158
159 EXPECT_EQ(boost::variant2::holds_alternative<crow::Response::file_response>(
160 res.response),
161 true);
162
163 verifyHeaders(res);
164 res.write("body text");
165
166 EXPECT_EQ(
167 boost::variant2::holds_alternative<crow::Response::string_response>(
168 res.response),
169 true);
170
171 verifyHeaders(res);
172 std::filesystem::remove(path);
173}
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600174
175void testFileData(crow::Response& res, const std::string& data)
176{
177 auto& fb =
178 boost::variant2::get<crow::Response::file_response>(res.response);
179 EXPECT_EQ(getData(fb), data);
180}
181
182TEST(HttpResponse, Base64FileBodyWriter)
183{
184 crow::Response res;
185 std::string data = "sample text";
186 std::string path = makeFile(data);
187 FILE* f = fopen(path.c_str(), "r+");
188 res.openFd(fileno(f), bmcweb::EncodingType::Base64);
189 testFileData(res, crow::utility::base64encode(data));
190 fclose(f);
191 std::filesystem::remove(path);
192}
193
194std::string generateBigdata()
195{
196 std::string result;
197 while (result.size() < 10000)
198 {
199 result += "sample text";
200 }
201 return result;
202}
203
204TEST(HttpResponse, Base64FileBodyWriterLarge)
205{
206 crow::Response res;
207 std::string data = generateBigdata();
208 std::string path = makeFile(data);
209 {
210 boost::beast::file_posix file;
211 boost::system::error_code ec;
212 file.open(path.c_str(), boost::beast::file_mode::read, ec);
213 EXPECT_EQ(ec.value(), 0);
214 res.openFd(file.native_handle(), bmcweb::EncodingType::Base64);
215 testFileData(res, crow::utility::base64encode(data));
216 }
217
218 std::filesystem::remove(path);
219}
220
221TEST(HttpResponse, FileBodyWriterLarge)
222{
223 crow::Response res;
224 std::string data = generateBigdata();
225 std::string path = makeFile(data);
226 {
227 boost::beast::file_posix file;
228 boost::system::error_code ec;
229 file.open(path.c_str(), boost::beast::file_mode::read, ec);
230 EXPECT_EQ(ec.value(), 0);
231 res.openFd(file.native_handle());
232 testFileData(res, data);
233 }
234 std::filesystem::remove(path);
235}
236
Abhilash Raju8e3f7032023-07-17 08:53:11 -0500237} // namespace