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