1 // 2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) 3 // 4 // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 // 7 // Official repository: https://github.com/boostorg/beast 8 // 9 10 // Test that header file is self-contained. 11 #include <boost/beast/http/message.hpp> 12 13 #include <boost/beast/http/empty_body.hpp> 14 #include <boost/beast/http/string_body.hpp> 15 #include <boost/beast/http/fields.hpp> 16 #include <boost/beast/http/string_body.hpp> 17 #include <boost/beast/_experimental/unit_test/suite.hpp> 18 #include <type_traits> 19 20 namespace boost { 21 namespace beast { 22 namespace http { 23 24 class message_test : public beast::unit_test::suite 25 { 26 public: 27 struct Arg1 28 { 29 bool moved = false; 30 31 Arg1(Arg1 const&) = default; 32 Arg1boost::beast::http::message_test::Arg133 Arg1() 34 { 35 } 36 Arg1boost::beast::http::message_test::Arg137 Arg1(Arg1&& other) 38 { 39 other.moved = true; 40 } 41 }; 42 43 struct Arg2 { }; 44 struct Arg3 { }; 45 46 // default constructible Body 47 struct default_body 48 { 49 using value_type = std::string; 50 }; 51 52 // 1-arg constructible Body 53 struct one_arg_body 54 { 55 struct value_type 56 { 57 explicit value_typeboost::beast::http::message_test::one_arg_body::value_type58 value_type(Arg1 const&) 59 { 60 } 61 62 explicit value_typeboost::beast::http::message_test::one_arg_body::value_type63 value_type(Arg1&& arg) 64 { 65 Arg1 arg_(std::move(arg)); 66 } 67 }; 68 }; 69 70 // 2-arg constructible Body 71 struct two_arg_body 72 { 73 struct value_type 74 { value_typeboost::beast::http::message_test::two_arg_body::value_type75 value_type(Arg1 const&, Arg2 const&) 76 { 77 } 78 }; 79 }; 80 81 // 0-arg 82 BOOST_STATIC_ASSERT(std::is_constructible< 83 request<default_body>>::value); 84 85 // 1-arg 86 BOOST_STATIC_ASSERT(! std::is_constructible<request<one_arg_body> 87 >::value); 88 89 //BOOST_STATIC_ASSERT(! std::is_constructible<request<one_arg_body>, 90 // verb, string_view, unsigned>::value); 91 92 BOOST_STATIC_ASSERT(std::is_constructible<request<one_arg_body>, 93 verb, string_view, unsigned, Arg1>::value); 94 95 BOOST_STATIC_ASSERT(std::is_constructible<request<one_arg_body>, 96 verb, string_view, unsigned, Arg1&&>::value); 97 98 BOOST_STATIC_ASSERT(std::is_constructible<request<one_arg_body>, 99 verb, string_view, unsigned, Arg1 const>::value); 100 101 BOOST_STATIC_ASSERT(std::is_constructible<request<one_arg_body>, 102 verb, string_view, unsigned, Arg1 const&>::value); 103 104 // 1-arg + fields 105 BOOST_STATIC_ASSERT(std::is_constructible<request<one_arg_body>, 106 verb, string_view, unsigned, Arg1, fields::allocator_type>::value); 107 108 BOOST_STATIC_ASSERT(std::is_constructible<request<one_arg_body>, std::piecewise_construct_t, 109 std::tuple<Arg1>>::value); 110 111 BOOST_STATIC_ASSERT(std::is_constructible<request<two_arg_body>, std::piecewise_construct_t, 112 std::tuple<Arg1, Arg2>>::value); 113 114 BOOST_STATIC_ASSERT(std::is_constructible<request<two_arg_body>, std::piecewise_construct_t, 115 std::tuple<Arg1, Arg2>, std::tuple<fields::allocator_type>>::value); 116 117 // special members 118 BOOST_STATIC_ASSERT(std::is_copy_constructible<header<true>>::value); 119 BOOST_STATIC_ASSERT(std::is_move_constructible<header<true>>::value); 120 BOOST_STATIC_ASSERT(std::is_copy_assignable<header<true>>::value); 121 BOOST_STATIC_ASSERT(std::is_move_assignable<header<true>>::value); 122 BOOST_STATIC_ASSERT(std::is_copy_constructible<header<false>>::value); 123 BOOST_STATIC_ASSERT(std::is_move_constructible<header<false>>::value); 124 BOOST_STATIC_ASSERT(std::is_copy_assignable<header<false>>::value); 125 BOOST_STATIC_ASSERT(std::is_move_assignable<header<false>>::value); 126 127 void testMessage()128 testMessage() 129 { 130 { 131 Arg1 arg1; 132 request<one_arg_body>{verb::get, "/", 11, std::move(arg1)}; 133 BEAST_EXPECT(arg1.moved); 134 } 135 136 { 137 header<true> h; 138 h.set(field::user_agent, "test"); 139 BEAST_EXPECT(h[field::user_agent] == "test"); 140 request<default_body> m{std::move(h)}; 141 BEAST_EXPECT(m[field::user_agent] == "test"); 142 BEAST_EXPECT(h.count(field::user_agent) == 0); 143 } 144 { 145 request<empty_body> h{verb::get, "/", 10}; 146 h.set(field::user_agent, "test"); 147 request<one_arg_body> m{std::move(h.base()), Arg1{}}; 148 BEAST_EXPECT(m["User-Agent"] == "test"); 149 BEAST_EXPECT(h.count(http::field::user_agent) == 0); 150 BEAST_EXPECT(m.method() == verb::get); 151 BEAST_EXPECT(m.target() == "/"); 152 BEAST_EXPECT(m.version() == 10); 153 } 154 155 // swap 156 request<string_body> m1; 157 request<string_body> m2; 158 m1.target("u"); 159 m1.body() = "1"; 160 m1.insert("h", "v"); 161 m2.method_string("G"); 162 m2.body() = "2"; 163 swap(m1, m2); 164 BEAST_EXPECT(m1.method_string() == "G"); 165 BEAST_EXPECT(m2.method_string().empty()); 166 BEAST_EXPECT(m1.target().empty()); 167 BEAST_EXPECT(m2.target() == "u"); 168 BEAST_EXPECT(m1.body() == "2"); 169 BEAST_EXPECT(m2.body() == "1"); 170 BEAST_EXPECT(! m1.count("h")); 171 BEAST_EXPECT(m2.count("h")); 172 } 173 174 struct MoveFields : fields 175 { 176 bool moved_to = false; 177 bool moved_from = false; 178 179 MoveFields() = default; 180 MoveFieldsboost::beast::http::message_test::MoveFields181 MoveFields(MoveFields&& other) 182 : moved_to(true) 183 { 184 other.moved_from = true; 185 } 186 operator =boost::beast::http::message_test::MoveFields187 MoveFields& operator=(MoveFields&&) 188 { 189 return *this; 190 } 191 }; 192 193 struct token {}; 194 195 struct test_fields 196 { 197 std::string target; 198 199 test_fields() = delete; test_fieldsboost::beast::http::message_test::test_fields200 test_fields(token) {} get_method_implboost::beast::http::message_test::test_fields201 string_view get_method_impl() const { return {}; } get_target_implboost::beast::http::message_test::test_fields202 string_view get_target_impl() const { return target; } get_reason_implboost::beast::http::message_test::test_fields203 string_view get_reason_impl() const { return {}; } get_chunked_implboost::beast::http::message_test::test_fields204 bool get_chunked_impl() const { return false; } get_keep_alive_implboost::beast::http::message_test::test_fields205 bool get_keep_alive_impl(unsigned) const { return true; } has_content_length_implboost::beast::http::message_test::test_fields206 bool has_content_length_impl() const { return false; } set_method_implboost::beast::http::message_test::test_fields207 void set_method_impl(string_view) {} set_target_implboost::beast::http::message_test::test_fields208 void set_target_impl(string_view s) { target = std::string(s); } set_reason_implboost::beast::http::message_test::test_fields209 void set_reason_impl(string_view) {} set_chunked_implboost::beast::http::message_test::test_fields210 void set_chunked_impl(bool) {} set_content_length_implboost::beast::http::message_test::test_fields211 void set_content_length_impl(boost::optional<std::uint64_t>) {} set_keep_alive_implboost::beast::http::message_test::test_fields212 void set_keep_alive_impl(unsigned, bool) {} 213 }; 214 215 void testMessageCtors()216 testMessageCtors() 217 { 218 { 219 request<empty_body> req; 220 BEAST_EXPECT(req.version() == 11); 221 BEAST_EXPECT(req.method() == verb::unknown); 222 BEAST_EXPECT(req.target() == ""); 223 } 224 { 225 request<empty_body> req{verb::get, "/", 11}; 226 BEAST_EXPECT(req.version() == 11); 227 BEAST_EXPECT(req.method() == verb::get); 228 BEAST_EXPECT(req.target() == "/"); 229 } 230 { 231 request<string_body> req{verb::get, "/", 11, "Hello"}; 232 BEAST_EXPECT(req.version() == 11); 233 BEAST_EXPECT(req.method() == verb::get); 234 BEAST_EXPECT(req.target() == "/"); 235 BEAST_EXPECT(req.body() == "Hello"); 236 } 237 { 238 request<string_body, test_fields> req{ 239 verb::get, "/", 11, "Hello", token{}}; 240 BEAST_EXPECT(req.version() == 11); 241 BEAST_EXPECT(req.method() == verb::get); 242 BEAST_EXPECT(req.target() == "/"); 243 BEAST_EXPECT(req.body() == "Hello"); 244 BEAST_EXPECT(! req.has_content_length()); 245 } 246 { 247 response<string_body> res; 248 BEAST_EXPECT(res.version() == 11); 249 BEAST_EXPECT(res.result() == status::ok); 250 BEAST_EXPECT(res.reason() == "OK"); 251 } 252 { 253 response<string_body> res{status::bad_request, 10}; 254 BEAST_EXPECT(res.version() == 10); 255 BEAST_EXPECT(res.result() == status::bad_request); 256 BEAST_EXPECT(res.reason() == "Bad Request"); 257 } 258 { 259 response<string_body> res{status::bad_request, 10, "Hello"}; 260 BEAST_EXPECT(res.version() == 10); 261 BEAST_EXPECT(res.result() == status::bad_request); 262 BEAST_EXPECT(res.reason() == "Bad Request"); 263 BEAST_EXPECT(res.body() == "Hello"); 264 } 265 { 266 response<string_body, test_fields> res{ 267 status::bad_request, 10, "Hello", token{}}; 268 BEAST_EXPECT(res.version() == 10); 269 BEAST_EXPECT(res.result() == status::bad_request); 270 BEAST_EXPECT(res.reason() == "Bad Request"); 271 BEAST_EXPECT(res.body() == "Hello"); 272 BEAST_EXPECT(! res.has_content_length()); 273 } 274 } 275 276 void testBody()277 testBody() 278 { 279 { 280 auto f = [](empty_body::value_type&){}; 281 request<empty_body> m; 282 f(m.body()); 283 } 284 { 285 auto f = [](empty_body::value_type const&){}; 286 request<empty_body> const m{}; 287 f(m.body()); 288 f(std::move(m.body())); 289 } 290 { 291 auto f = [](empty_body::value_type&&){}; 292 request<empty_body> m; 293 f(std::move(m).body()); 294 f(std::move(m.body())); 295 } 296 { 297 auto f = [](empty_body::value_type const&&){}; 298 request<empty_body> const m{}; 299 f(std::move(m.body())); 300 } 301 } 302 303 void testSwap()304 testSwap() 305 { 306 response<string_body> m1; 307 response<string_body> m2; 308 m1.result(status::ok); 309 m1.version(10); 310 m1.body() = "1"; 311 m1.insert("h", "v"); 312 m2.result(status::not_found); 313 m2.body() = "2"; 314 m2.version(11); 315 swap(m1, m2); 316 BEAST_EXPECT(m1.result() == status::not_found); 317 BEAST_EXPECT(m1.result_int() == 404); 318 BEAST_EXPECT(m2.result() == status::ok); 319 BEAST_EXPECT(m2.result_int() == 200); 320 BEAST_EXPECT(m1.reason() == "Not Found"); 321 BEAST_EXPECT(m2.reason() == "OK"); 322 BEAST_EXPECT(m1.version() == 11); 323 BEAST_EXPECT(m2.version() == 10); 324 BEAST_EXPECT(m1.body() == "2"); 325 BEAST_EXPECT(m2.body() == "1"); 326 BEAST_EXPECT(! m1.count("h")); 327 BEAST_EXPECT(m2.count("h")); 328 } 329 330 void testSpecialMembers()331 testSpecialMembers() 332 { 333 response<string_body> r1; 334 response<string_body> r2{r1}; 335 response<string_body> r3{std::move(r2)}; 336 r2 = r3; 337 r1 = std::move(r2); 338 [r1]() 339 { 340 }(); 341 } 342 343 void testMethod()344 testMethod() 345 { 346 header<true> h; 347 auto const vcheck = 348 [&](verb v) 349 { 350 h.method(v); 351 BEAST_EXPECT(h.method() == v); 352 BEAST_EXPECT(h.method_string() == to_string(v)); 353 }; 354 auto const scheck = 355 [&](string_view s) 356 { 357 h.method_string(s); 358 BEAST_EXPECT(h.method() == string_to_verb(s)); 359 BEAST_EXPECT(h.method_string() == s); 360 }; 361 vcheck(verb::get); 362 vcheck(verb::head); 363 scheck("GET"); 364 scheck("HEAD"); 365 scheck("XYZ"); 366 } 367 368 void testStatus()369 testStatus() 370 { 371 header<false> h; 372 h.result(200); 373 BEAST_EXPECT(h.result_int() == 200); 374 BEAST_EXPECT(h.result() == status::ok); 375 h.result(status::switching_protocols); 376 BEAST_EXPECT(h.result_int() == 101); 377 BEAST_EXPECT(h.result() == status::switching_protocols); 378 h.result(1); 379 BEAST_EXPECT(h.result_int() == 1); 380 BEAST_EXPECT(h.result() == status::unknown); 381 } 382 383 void testReason()384 testReason() 385 { 386 header<false> h; 387 h.result(status::ok); 388 BEAST_EXPECT(h.reason() == "OK"); 389 h.reason("Pepe"); 390 BEAST_EXPECT(h.reason() == "Pepe"); 391 h.result(status::not_found); 392 BEAST_EXPECT(h.reason() == "Pepe"); 393 h.reason({}); 394 BEAST_EXPECT(h.reason() == "Not Found"); 395 } 396 397 void testNeedEof()398 testNeedEof() 399 { 400 { 401 request<empty_body> m; 402 403 m.version(10); 404 m.keep_alive(false); 405 BEAST_EXPECT(m.need_eof()); 406 m.keep_alive(true); 407 BEAST_EXPECT(! m.need_eof()); 408 409 m.version(11); 410 m.keep_alive(false); 411 BEAST_EXPECT(m.need_eof()); 412 m.keep_alive(true); 413 BEAST_EXPECT(! m.need_eof()); 414 } 415 416 { 417 response<empty_body> m; 418 m.result(status::ok); 419 420 m.version(10); 421 m.keep_alive(false); 422 BEAST_EXPECT(! m.has_content_length()); 423 BEAST_EXPECT(! m.chunked()); 424 m.result(status::no_content); 425 BEAST_EXPECT(m.need_eof()); 426 m.result(status::not_modified); 427 BEAST_EXPECT(m.need_eof()); 428 m.result(status::continue_); 429 BEAST_EXPECT(m.need_eof()); 430 m.result(status::switching_protocols); 431 BEAST_EXPECT(m.need_eof()); 432 m.result(status::ok); 433 BEAST_EXPECT(m.need_eof()); 434 435 m.version(10); 436 m.keep_alive(true); 437 BEAST_EXPECT(! m.has_content_length()); 438 BEAST_EXPECT(! m.chunked()); 439 m.result(status::no_content); 440 BEAST_EXPECT(! m.need_eof()); 441 m.result(status::not_modified); 442 BEAST_EXPECT(! m.need_eof()); 443 m.result(status::continue_); 444 BEAST_EXPECT(! m.need_eof()); 445 m.result(status::switching_protocols); 446 BEAST_EXPECT(! m.need_eof()); 447 m.result(status::ok); 448 BEAST_EXPECT(m.need_eof()); 449 m.set(field::content_length, "1"); 450 BEAST_EXPECT(! m.need_eof()); 451 } 452 453 { 454 response<empty_body> m; 455 m.result(status::ok); 456 457 m.version(11); 458 m.keep_alive(false); 459 BEAST_EXPECT(! m.has_content_length()); 460 BEAST_EXPECT(! m.chunked()); 461 m.result(status::no_content); 462 BEAST_EXPECT(m.need_eof()); 463 m.result(status::not_modified); 464 BEAST_EXPECT(m.need_eof()); 465 m.result(status::continue_); 466 BEAST_EXPECT(m.need_eof()); 467 m.result(status::switching_protocols); 468 BEAST_EXPECT(m.need_eof()); 469 m.result(status::ok); 470 BEAST_EXPECT(m.need_eof()); 471 m.chunked(true); 472 BEAST_EXPECT(m.need_eof()); 473 m.content_length(1); 474 BEAST_EXPECT(m.need_eof()); 475 } 476 477 { 478 response<empty_body> m; 479 m.result(status::ok); 480 481 m.version(11); 482 m.keep_alive(true); 483 BEAST_EXPECT(! m.has_content_length()); 484 BEAST_EXPECT(! m.chunked()); 485 m.result(status::no_content); 486 BEAST_EXPECT(! m.need_eof()); 487 m.result(status::not_modified); 488 BEAST_EXPECT(! m.need_eof()); 489 m.result(status::continue_); 490 BEAST_EXPECT(! m.need_eof()); 491 m.result(status::switching_protocols); 492 BEAST_EXPECT(! m.need_eof()); 493 m.result(status::ok); 494 BEAST_EXPECT(m.need_eof()); 495 m.chunked(true); 496 BEAST_EXPECT(! m.need_eof()); 497 m.content_length(1); 498 BEAST_EXPECT(! m.need_eof()); 499 } 500 } 501 502 void run()503 run() override 504 { 505 testMessage(); 506 testMessageCtors(); 507 testBody(); 508 testSwap(); 509 testSpecialMembers(); 510 testMethod(); 511 testStatus(); 512 testReason(); 513 testNeedEof(); 514 } 515 }; 516 517 BEAST_DEFINE_TESTSUITE(beast,http,message); 518 519 } // http 520 } // beast 521 } // boost 522