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