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 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 std::string path = makeFile("sample text"); 87 res.openFile(path); 88 89 verifyHeaders(res); 90 std::filesystem::remove(path); 91 } 92 TEST(HttpResponse, HttpBodyWithFd) 93 { 94 crow::Response res; 95 addHeaders(res); 96 std::string path = makeFile("sample text"); 97 FILE* fd = fopen(path.c_str(), "r+"); 98 res.openFd(fileno(fd)); 99 verifyHeaders(res); 100 fclose(fd); 101 std::filesystem::remove(path); 102 } 103 104 TEST(HttpResponse, Base64HttpBodyWithFd) 105 { 106 crow::Response res; 107 addHeaders(res); 108 std::string path = makeFile("sample text"); 109 FILE* fd = fopen(path.c_str(), "r+"); 110 res.openFd(fileno(fd), bmcweb::EncodingType::Base64); 111 verifyHeaders(res); 112 fclose(fd); 113 std::filesystem::remove(path); 114 } 115 116 TEST(HttpResponse, BodyTransitions) 117 { 118 crow::Response res; 119 addHeaders(res); 120 std::string path = makeFile("sample text"); 121 res.openFile(path); 122 123 verifyHeaders(res); 124 res.write("body text"); 125 126 verifyHeaders(res); 127 std::filesystem::remove(path); 128 } 129 130 void testFileData(crow::Response& res, const std::string& data) 131 { 132 auto& fb = res.response; 133 EXPECT_EQ(getData(fb), data); 134 } 135 136 std::string generateBigdata() 137 { 138 std::string result; 139 while (result.size() < 10000) 140 { 141 result += "sample text"; 142 } 143 return result; 144 } 145 146 TEST(HttpResponse, StringBodyWriterLarge) 147 { 148 crow::Response res; 149 std::string data = generateBigdata(); 150 res.write(std::string(data)); 151 testFileData(res, data); 152 } 153 154 TEST(HttpResponse, Base64HttpBodyWriter) 155 { 156 crow::Response res; 157 std::string data = "sample text"; 158 std::string path = makeFile(data); 159 FILE* f = fopen(path.c_str(), "r+"); 160 res.openFd(fileno(f), bmcweb::EncodingType::Base64); 161 testFileData(res, crow::utility::base64encode(data)); 162 fclose(f); 163 std::filesystem::remove(path); 164 } 165 166 TEST(HttpResponse, Base64HttpBodyWriterLarge) 167 { 168 crow::Response res; 169 std::string data = generateBigdata(); 170 std::string path = makeFile(data); 171 { 172 boost::beast::file_posix file; 173 boost::system::error_code ec; 174 file.open(path.c_str(), boost::beast::file_mode::read, ec); 175 EXPECT_EQ(ec.value(), 0); 176 res.openFd(file.native_handle(), bmcweb::EncodingType::Base64); 177 testFileData(res, crow::utility::base64encode(data)); 178 } 179 180 std::filesystem::remove(path); 181 } 182 183 TEST(HttpResponse, HttpBodyWriterLarge) 184 { 185 crow::Response res; 186 std::string data = generateBigdata(); 187 std::string path = makeFile(data); 188 { 189 boost::beast::file_posix file; 190 boost::system::error_code ec; 191 file.open(path.c_str(), boost::beast::file_mode::read, ec); 192 EXPECT_EQ(ec.value(), 0); 193 res.openFd(file.native_handle()); 194 testFileData(res, data); 195 } 196 std::filesystem::remove(path); 197 } 198 199 } // namespace 200