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