• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/fields.hpp>
12 
13 #include <boost/beast/core/static_string.hpp>
14 #include <boost/beast/http/empty_body.hpp>
15 #include <boost/beast/http/message.hpp>
16 #include <boost/beast/http/type_traits.hpp>
17 #include <boost/beast/test/test_allocator.hpp>
18 #include <boost/beast/_experimental/unit_test/suite.hpp>
19 #include <string>
20 
21 namespace boost {
22 namespace beast {
23 namespace http {
24 
25 class fields_test : public beast::unit_test::suite
26 {
27 public:
28     static constexpr std::size_t max_static_buffer =
29         sizeof(beast::detail::temporary_buffer);
30 
31     template<class T>
32     class test_allocator
33     {
34     public:
35         using value_type = T;
36 
test_allocator()37         test_allocator() noexcept(false) {}
38 
39         template<class U, class = typename
40             std::enable_if<!std::is_same<test_allocator, U>::value>::type>
test_allocator(test_allocator<U> const &)41         test_allocator(test_allocator<U> const&) noexcept {}
42 
43         value_type*
allocate(std::size_t n)44         allocate(std::size_t n)
45         {
46             return static_cast<value_type*>(::operator new (n*sizeof(value_type)));
47         }
48 
49         void
deallocate(value_type * p,std::size_t)50         deallocate(value_type* p, std::size_t) noexcept
51         {
52             ::operator delete(p);
53         }
54 
55         template<class U>
56         friend
57         bool
operator ==(test_allocator<T> const &,test_allocator<U> const &)58         operator==(test_allocator<T> const&, test_allocator<U> const&) noexcept
59         {
60             return true;
61         }
62 
63         template<class U>
64         friend
65         bool
operator !=(test_allocator<T> const & x,test_allocator<U> const & y)66         operator!=(test_allocator<T> const& x, test_allocator<U> const& y) noexcept
67         {
68             return !(x == y);
69         }
70     };
71 
72     using test_fields = basic_fields<test_allocator<char>>;
73 
74     BOOST_STATIC_ASSERT(is_fields<fields>::value);
75     BOOST_STATIC_ASSERT(is_fields<test_fields>::value);
76 
77     // std::allocator is noexcept movable, fields should satisfy
78     // these constraints as well.
79     BOOST_STATIC_ASSERT(std::is_nothrow_move_constructible<fields>::value);
80     BOOST_STATIC_ASSERT(std::is_nothrow_move_assignable<fields>::value);
81 
82     // Check if basic_fields respects throw-constructibility and
83     // propagate_on_container_move_assignment of the allocator.
84     BOOST_STATIC_ASSERT(std::is_nothrow_move_constructible<test_fields>::value);
85     BOOST_STATIC_ASSERT(!std::is_nothrow_move_assignable<test_fields>::value);
86 
87     template<class Allocator>
88     using fa_t = basic_fields<Allocator>;
89 
90     using f_t = fa_t<std::allocator<char>>;
91 
92     template<class Allocator>
93     static
94     void
fill(std::size_t n,basic_fields<Allocator> & f)95     fill(std::size_t n, basic_fields<Allocator>& f)
96     {
97         for(std::size_t i = 1; i<= n; ++i)
98             f.insert(std::to_string(i), to_static_string(i));
99     }
100 
101     template<class U, class V>
102     static
103     void
self_assign(U & u,V && v)104     self_assign(U& u, V&& v)
105     {
106         u = std::forward<V>(v);
107     }
108 
109     template<class Alloc>
110     static
111     bool
empty(basic_fields<Alloc> const & f)112     empty(basic_fields<Alloc> const& f)
113     {
114         return f.begin() == f.end();
115     }
116 
117     template<class Alloc>
118     static
119     std::size_t
size(basic_fields<Alloc> const & f)120     size(basic_fields<Alloc> const& f)
121     {
122         return std::distance(f.begin(), f.end());
123     }
124 
125     void
testMembers()126     testMembers()
127     {
128         using namespace test;
129 
130         // compare equal
131         using equal_t = test::test_allocator<char,
132             true, true, true, true, true>;
133 
134         // compare not equal
135         using unequal_t = test::test_allocator<char,
136             false, true, true, true, true>;
137 
138         // construction
139         {
140             {
141                 fields f;
142                 BEAST_EXPECT(f.begin() == f.end());
143             }
144             {
145                 unequal_t a1;
146                 basic_fields<unequal_t> f{a1};
147                 BEAST_EXPECT(f.get_allocator() == a1);
148                 BEAST_EXPECT(f.get_allocator() != unequal_t{});
149             }
150         }
151 
152         // move construction
153         {
154             {
155                 basic_fields<equal_t> f1;
156                 BEAST_EXPECT(f1.get_allocator()->nmove == 0);
157                 f1.insert("1", "1");
158                 BEAST_EXPECT(f1["1"] == "1");
159                 basic_fields<equal_t> f2{std::move(f1)};
160                 BEAST_EXPECT(f2.get_allocator()->nmove == 1);
161                 BEAST_EXPECT(f2["1"] == "1");
162                 BEAST_EXPECT(f1["1"] == "");
163             }
164             // allocators equal
165             {
166                 basic_fields<equal_t> f1;
167                 f1.insert("1", "1");
168                 equal_t a;
169                 basic_fields<equal_t> f2{std::move(f1), a};
170                 BEAST_EXPECT(f2["1"] == "1");
171                 BEAST_EXPECT(f1["1"] == "");
172             }
173             {
174                 // allocators unequal
175                 basic_fields<unequal_t> f1;
176                 f1.insert("1", "1");
177                 unequal_t a;
178                 basic_fields<unequal_t> f2{std::move(f1), a};
179                 BEAST_EXPECT(f2["1"] == "1");
180             }
181         }
182 
183         // copy construction
184         {
185             {
186                 basic_fields<equal_t> f1;
187                 f1.insert("1", "1");
188                 basic_fields<equal_t> f2{f1};
189                 BEAST_EXPECT(f1.get_allocator() == f2.get_allocator());
190                 BEAST_EXPECT(f1["1"] == "1");
191                 BEAST_EXPECT(f2["1"] == "1");
192             }
193             {
194                 basic_fields<unequal_t> f1;
195                 f1.insert("1", "1");
196                 unequal_t a;
197                 basic_fields<unequal_t> f2(f1, a);
198                 BEAST_EXPECT(f1.get_allocator() != f2.get_allocator());
199                 BEAST_EXPECT(f1["1"] == "1");
200                 BEAST_EXPECT(f2["1"] == "1");
201             }
202             {
203                 basic_fields<equal_t> f1;
204                 f1.insert("1", "1");
205                 basic_fields<unequal_t> f2(f1);
206                 BEAST_EXPECT(f1["1"] == "1");
207                 BEAST_EXPECT(f2["1"] == "1");
208             }
209             {
210                 basic_fields<unequal_t> f1;
211                 f1.insert("1", "1");
212                 equal_t a;
213                 basic_fields<equal_t> f2(f1, a);
214                 BEAST_EXPECT(f2.get_allocator() == a);
215                 BEAST_EXPECT(f1["1"] == "1");
216                 BEAST_EXPECT(f2["1"] == "1");
217             }
218         }
219 
220         // move assignment
221         {
222             {
223                 fields f1;
224                 f1.insert("1", "1");
225                 fields f2;
226                 f2 = std::move(f1);
227                 BEAST_EXPECT(f1.begin() == f1.end());
228                 BEAST_EXPECT(f2["1"] == "1");
229             }
230             {
231                 // propagate_on_container_move_assignment : true
232                 using pocma_t = test::test_allocator<char,
233                     true, true, true, true, true>;
234                 basic_fields<pocma_t> f1;
235                 f1.insert("1", "1");
236                 basic_fields<pocma_t> f2;
237                 f2 = std::move(f1);
238                 BEAST_EXPECT(f1.begin() == f1.end());
239                 BEAST_EXPECT(f2["1"] == "1");
240             }
241             {
242                 // propagate_on_container_move_assignment : false
243                 using pocma_t = test::test_allocator<char,
244                     true, true, false, true, true>;
245                 basic_fields<pocma_t> f1;
246                 f1.insert("1", "1");
247                 basic_fields<pocma_t> f2;
248                 f2 = std::move(f1);
249                 BEAST_EXPECT(f1.begin() == f1.end());
250                 BEAST_EXPECT(f2["1"] == "1");
251             }
252         }
253 
254         // copy assignment
255         {
256             {
257                 fields f1;
258                 f1.insert("1", "1");
259                 fields f2;
260                 f2 = f1;
261                 BEAST_EXPECT(f1["1"] == "1");
262                 BEAST_EXPECT(f2["1"] == "1");
263                 basic_fields<equal_t> f3;
264                 f3 = f2;
265                 BEAST_EXPECT(f3["1"] == "1");
266             }
267             {
268                 // propagate_on_container_copy_assignment : true
269                 using pocca_t = test::test_allocator<char,
270                     true, true, true, true, true>;
271                 basic_fields<pocca_t> f1;
272                 f1.insert("1", "1");
273                 basic_fields<pocca_t> f2;
274                 f2 = f1;
275                 BEAST_EXPECT(f2["1"] == "1");
276             }
277             {
278                 // propagate_on_container_copy_assignment : false
279                 using pocca_t = test::test_allocator<char,
280                     true, false, true, true, true>;
281                 basic_fields<pocca_t> f1;
282                 f1.insert("1", "1");
283                 basic_fields<pocca_t> f2;
284                 f2 = f1;
285                 BEAST_EXPECT(f2["1"] == "1");
286             }
287         }
288 
289         // swap
290         {
291             {
292                 // propagate_on_container_swap : true
293                 using pocs_t = test::test_allocator<char,
294                     false, true, true, true, true>;
295                 pocs_t a1, a2;
296                 BEAST_EXPECT(a1 != a2);
297                 basic_fields<pocs_t> f1{a1};
298                 f1.insert("1", "1");
299                 basic_fields<pocs_t> f2{a2};
300                 BEAST_EXPECT(f1.get_allocator() == a1);
301                 BEAST_EXPECT(f2.get_allocator() == a2);
302                 swap(f1, f2);
303                 BEAST_EXPECT(f1.get_allocator() == a2);
304                 BEAST_EXPECT(f2.get_allocator() == a1);
305                 BEAST_EXPECT(f1.begin() == f1.end());
306                 BEAST_EXPECT(f2["1"] == "1");
307                 swap(f1, f2);
308                 BEAST_EXPECT(f1.get_allocator() == a1);
309                 BEAST_EXPECT(f2.get_allocator() == a2);
310                 BEAST_EXPECT(f1["1"] == "1");
311                 BEAST_EXPECT(f2.begin() == f2.end());
312             }
313             {
314                 // propagate_on_container_swap : false
315                 using pocs_t = test::test_allocator<char,
316                     true, true, true, false, true>;
317                 pocs_t a1, a2;
318                 BEAST_EXPECT(a1 == a2);
319                 BEAST_EXPECT(a1.id() != a2.id());
320                 basic_fields<pocs_t> f1{a1};
321                 f1.insert("1", "1");
322                 basic_fields<pocs_t> f2{a2};
323                 BEAST_EXPECT(f1.get_allocator() == a1);
324                 BEAST_EXPECT(f2.get_allocator() == a2);
325                 swap(f1, f2);
326                 BEAST_EXPECT(f1.get_allocator().id() == a1.id());
327                 BEAST_EXPECT(f2.get_allocator().id() == a2.id());
328                 BEAST_EXPECT(f1.begin() == f1.end());
329                 BEAST_EXPECT(f2["1"] == "1");
330                 swap(f1, f2);
331                 BEAST_EXPECT(f1.get_allocator().id() == a1.id());
332                 BEAST_EXPECT(f2.get_allocator().id() == a2.id());
333                 BEAST_EXPECT(f1["1"] == "1");
334                 BEAST_EXPECT(f2.begin() == f2.end());
335             }
336         }
337 
338         // operations
339         {
340             fields f;
341             f.insert(field::user_agent, "x");
342             BEAST_EXPECT(f.count(field::user_agent));
343             BEAST_EXPECT(f.count(to_string(field::user_agent)));
344             BEAST_EXPECT(f.count(field::user_agent) == 1);
345             BEAST_EXPECT(f.count(to_string(field::user_agent)) == 1);
346             f.insert(field::user_agent, "y");
347             BEAST_EXPECT(f.count(field::user_agent) == 2);
348         }
349     }
350 
testHeaders()351     void testHeaders()
352     {
353         f_t f1;
354         BEAST_EXPECT(empty(f1));
355         fill(1, f1);
356         BEAST_EXPECT(size(f1) == 1);
357         f_t f2;
358         f2 = f1;
359         BEAST_EXPECT(size(f2) == 1);
360         f2.insert("2", "2");
361         BEAST_EXPECT(std::distance(f2.begin(), f2.end()) == 2);
362         f1 = std::move(f2);
363         BEAST_EXPECT(size(f1) == 2);
364         BEAST_EXPECT(size(f2) == 0);
365         f_t f3(std::move(f1));
366         BEAST_EXPECT(size(f3) == 2);
367         BEAST_EXPECT(size(f1) == 0);
368         self_assign(f3, std::move(f3));
369         BEAST_EXPECT(size(f3) == 2);
370         BEAST_EXPECT(f2.erase("Not-Present") == 0);
371     }
372 
testRFC2616()373     void testRFC2616()
374     {
375         f_t f;
376         f.insert("a", "w");
377         f.insert("a", "x");
378         f.insert("aa", "y");
379         f.insert("f", "z");
380         BEAST_EXPECT(f.count("a") == 2);
381     }
382 
testErase()383     void testErase()
384     {
385         f_t f;
386         f.insert("a", "w");
387         f.insert("a", "x");
388         f.insert("aa", "y");
389         f.insert("f", "z");
390         BEAST_EXPECT(size(f) == 4);
391         f.erase("a");
392         BEAST_EXPECT(size(f) == 2);
393     }
394 
testIteratorErase()395     void testIteratorErase()
396     {
397         f_t f;
398         f.insert("a", "x");
399         f.insert("b", "y");
400         f.insert("c", "z");
401         BEAST_EXPECT(size(f) == 3);
402         f_t::const_iterator i = std::next(f.begin());
403         f.erase(i);
404         BEAST_EXPECT(size(f) == 2);
405         BEAST_EXPECT(std::next(f.begin(), 0)->name_string() == "a");
406         BEAST_EXPECT(std::next(f.begin(), 1)->name_string() == "c");
407     }
408 
409     void
testContainer()410     testContainer()
411     {
412         {
413             // group fields
414             fields f;
415             f.insert(field::age,   to_static_string(1));
416             f.insert(field::body,  to_static_string(2));
417             f.insert(field::close, to_static_string(3));
418             f.insert(field::body,  to_static_string(4));
419             BEAST_EXPECT(std::next(f.begin(), 0)->name() == field::age);
420             BEAST_EXPECT(std::next(f.begin(), 1)->name() == field::body);
421             BEAST_EXPECT(std::next(f.begin(), 2)->name() == field::body);
422             BEAST_EXPECT(std::next(f.begin(), 3)->name() == field::close);
423             BEAST_EXPECT(std::next(f.begin(), 0)->name_string() == "Age");
424             BEAST_EXPECT(std::next(f.begin(), 1)->name_string() == "Body");
425             BEAST_EXPECT(std::next(f.begin(), 2)->name_string() == "Body");
426             BEAST_EXPECT(std::next(f.begin(), 3)->name_string() == "Close");
427             BEAST_EXPECT(std::next(f.begin(), 0)->value() == "1");
428             BEAST_EXPECT(std::next(f.begin(), 1)->value() == "2");
429             BEAST_EXPECT(std::next(f.begin(), 2)->value() == "4");
430             BEAST_EXPECT(std::next(f.begin(), 3)->value() == "3");
431             BEAST_EXPECT(f.erase(field::body) == 2);
432             BEAST_EXPECT(std::next(f.begin(), 0)->name_string() == "Age");
433             BEAST_EXPECT(std::next(f.begin(), 1)->name_string() == "Close");
434         }
435         {
436             // group fields, case insensitive
437             fields f;
438             f.insert("a",  to_static_string(1));
439             f.insert("ab", to_static_string(2));
440             f.insert("b",  to_static_string(3));
441             f.insert("AB", to_static_string(4));
442             BEAST_EXPECT(std::next(f.begin(), 0)->name() == field::unknown);
443             BEAST_EXPECT(std::next(f.begin(), 1)->name() == field::unknown);
444             BEAST_EXPECT(std::next(f.begin(), 2)->name() == field::unknown);
445             BEAST_EXPECT(std::next(f.begin(), 3)->name() == field::unknown);
446             BEAST_EXPECT(std::next(f.begin(), 0)->name_string() == "a");
447             BEAST_EXPECT(std::next(f.begin(), 1)->name_string() == "ab");
448             BEAST_EXPECT(std::next(f.begin(), 2)->name_string() == "AB");
449             BEAST_EXPECT(std::next(f.begin(), 3)->name_string() == "b");
450             BEAST_EXPECT(std::next(f.begin(), 0)->value() == "1");
451             BEAST_EXPECT(std::next(f.begin(), 1)->value() == "2");
452             BEAST_EXPECT(std::next(f.begin(), 2)->value() == "4");
453             BEAST_EXPECT(std::next(f.begin(), 3)->value() == "3");
454             BEAST_EXPECT(f.erase("Ab") == 2);
455             BEAST_EXPECT(std::next(f.begin(), 0)->name_string() == "a");
456             BEAST_EXPECT(std::next(f.begin(), 1)->name_string() == "b");
457         }
458         {
459             // verify insertion orde
460             fields f;
461             f.insert( "a", to_static_string(1));
462             f.insert("dd", to_static_string(2));
463             f.insert("b",  to_static_string(3));
464             f.insert("dD", to_static_string(4));
465             f.insert("c",  to_static_string(5));
466             f.insert("Dd", to_static_string(6));
467             f.insert("DD", to_static_string(7));
468             f.insert( "e", to_static_string(8));
469             BEAST_EXPECT(f.count("dd") == 4);
470             BEAST_EXPECT(std::next(f.begin(), 1)->name_string() == "dd");
471             BEAST_EXPECT(std::next(f.begin(), 2)->name_string() == "dD");
472             BEAST_EXPECT(std::next(f.begin(), 3)->name_string() == "Dd");
473             BEAST_EXPECT(std::next(f.begin(), 4)->name_string() == "DD");
474             f.set("dd", "-");
475             BEAST_EXPECT(f.count("dd") == 1);
476             BEAST_EXPECT(f["dd"] == "-");
477         }
478 
479         // equal_range
480         {
481             fields f;
482             f.insert("E", to_static_string(1));
483             f.insert("B", to_static_string(2));
484             f.insert("D", to_static_string(3));
485             f.insert("B", to_static_string(4));
486             f.insert("C", to_static_string(5));
487             f.insert("B", to_static_string(6));
488             f.insert("A", to_static_string(7));
489             auto const rng = f.equal_range("B");
490             BEAST_EXPECT(std::distance(rng.first, rng.second) == 3);
491             BEAST_EXPECT(std::next(rng.first, 0)->value() == "2");
492             BEAST_EXPECT(std::next(rng.first, 1)->value() == "4");
493             BEAST_EXPECT(std::next(rng.first, 2)->value() == "6");
494         }
495     }
496 
497     struct sized_body
498     {
499         using value_type = std::uint64_t;
500 
501         static
502         std::uint64_t
sizeboost::beast::http::fields_test::sized_body503         size(value_type const& v)
504         {
505             return v;
506         }
507     };
508 
509     struct unsized_body
510     {
511         struct value_type {};
512     };
513 
514     void
testPreparePayload()515     testPreparePayload()
516     {
517         // GET, empty
518         {
519             request<empty_body> req;
520             req.version(11);
521             req.method(verb::get);
522 
523             req.prepare_payload();
524             BEAST_EXPECT(req.count(field::content_length) == 0);
525             BEAST_EXPECT(req.count(field::transfer_encoding) == 0);
526 
527             req.set(field::content_length, "0");
528             req.set(field::transfer_encoding, "chunked");
529             req.prepare_payload();
530 
531             BEAST_EXPECT(req.count(field::content_length) == 0);
532             BEAST_EXPECT(req.count(field::transfer_encoding) == 0);
533 
534             req.set(field::transfer_encoding, "deflate");
535             req.prepare_payload();
536             BEAST_EXPECT(req.count(field::content_length) == 0);
537             BEAST_EXPECT(req[field::transfer_encoding] == "deflate");
538 
539             req.set(field::transfer_encoding, "deflate, chunked");
540             req.prepare_payload();
541             BEAST_EXPECT(req.count(field::content_length) == 0);
542             BEAST_EXPECT(req[field::transfer_encoding] == "deflate");
543         }
544 
545         // GET, sized
546         {
547             request<sized_body> req;
548             req.version(11);
549             req.method(verb::get);
550             req.body() = 50;
551 
552             req.prepare_payload();
553             BEAST_EXPECT(req[field::content_length] == "50");
554             BEAST_EXPECT(req[field::transfer_encoding] == "");
555 
556             req.set(field::content_length, "0");
557             req.set(field::transfer_encoding, "chunked");
558             req.prepare_payload();
559             BEAST_EXPECT(req[field::content_length] == "50");
560             BEAST_EXPECT(req.count(field::transfer_encoding) == 0);
561 
562             req.set(field::transfer_encoding, "deflate, chunked");
563             req.prepare_payload();
564             BEAST_EXPECT(req[field::content_length] == "50");
565             BEAST_EXPECT(req[field::transfer_encoding] == "deflate");
566         }
567 
568         // PUT, empty
569         {
570             request<empty_body> req;
571             req.version(11);
572             req.method(verb::put);
573 
574             req.prepare_payload();
575             BEAST_EXPECT(req[field::content_length] == "0");
576             BEAST_EXPECT(req.count(field::transfer_encoding) == 0);
577 
578             req.set(field::content_length, "50");
579             req.set(field::transfer_encoding, "deflate, chunked");
580             req.prepare_payload();
581             BEAST_EXPECT(req[field::content_length] == "0");
582             BEAST_EXPECT(req[field::transfer_encoding] == "deflate");
583         }
584 
585         // PUT, sized
586         {
587             request<sized_body> req;
588             req.version(11);
589             req.method(verb::put);
590             req.body() = 50;
591 
592             req.prepare_payload();
593             BEAST_EXPECT(req[field::content_length] == "50");
594             BEAST_EXPECT(req.count(field::transfer_encoding) == 0);
595 
596             req.set(field::content_length, "25");
597             req.set(field::transfer_encoding, "deflate, chunked");
598             req.prepare_payload();
599             BEAST_EXPECT(req[field::content_length] == "50");
600             BEAST_EXPECT(req[field::transfer_encoding] == "deflate");
601         }
602 
603         // POST, unsized
604         {
605             request<unsized_body> req;
606             req.version(11);
607             req.method(verb::post);
608 
609             req.prepare_payload();
610             BEAST_EXPECT(req.count(field::content_length) == 0);
611             BEAST_EXPECT(req[field::transfer_encoding] == "chunked");
612 
613             req.set(field::transfer_encoding, "deflate");
614             req.prepare_payload();
615             BEAST_EXPECT(req.count(field::content_length) == 0);
616             BEAST_EXPECT(req[field::transfer_encoding] == "deflate, chunked");
617         }
618 
619         // POST, unsized HTTP/1.0
620         {
621             request<unsized_body> req;
622             req.version(10);
623             req.method(verb::post);
624 
625             req.prepare_payload();
626             BEAST_EXPECT(req.count(field::content_length) == 0);
627             BEAST_EXPECT(req.count(field::transfer_encoding) == 0);
628 
629             req.set(field::transfer_encoding, "deflate");
630             req.prepare_payload();
631             BEAST_EXPECT(req.count(field::content_length) == 0);
632             BEAST_EXPECT(req[field::transfer_encoding] == "deflate");
633         }
634 
635         // OK, empty
636         {
637             response<empty_body> res;
638             res.version(11);
639 
640             res.prepare_payload();
641             BEAST_EXPECT(res[field::content_length] == "0");
642             BEAST_EXPECT(res.count(field::transfer_encoding) == 0);
643 
644             res.erase(field::content_length);
645             res.set(field::transfer_encoding, "chunked");
646             res.prepare_payload();
647             BEAST_EXPECT(res[field::content_length] == "0");
648             BEAST_EXPECT(res.count(field::transfer_encoding) == 0);
649         }
650 
651         // OK, sized
652         {
653             response<sized_body> res;
654             res.version(11);
655             res.body() = 50;
656 
657             res.prepare_payload();
658             BEAST_EXPECT(res[field::content_length] == "50");
659             BEAST_EXPECT(res.count(field::transfer_encoding) == 0);
660 
661             res.erase(field::content_length);
662             res.set(field::transfer_encoding, "chunked");
663             res.prepare_payload();
664             BEAST_EXPECT(res[field::content_length] == "50");
665             BEAST_EXPECT(res.count(field::transfer_encoding) == 0);
666         }
667 
668         // OK, unsized
669         {
670             response<unsized_body> res;
671             res.version(11);
672 
673             res.prepare_payload();
674             BEAST_EXPECT(res.count(field::content_length) == 0);
675             BEAST_EXPECT(res[field::transfer_encoding] == "chunked");
676         }
677     }
678 
679     void
testKeepAlive()680     testKeepAlive()
681     {
682         response<empty_body> res;
683         auto const keep_alive =
684             [&](bool v)
685             {
686                 res.keep_alive(v);
687                 BEAST_EXPECT(
688                     (res.keep_alive() && v) ||
689                     (! res.keep_alive() && ! v));
690             };
691 
692         std::string const big(max_static_buffer + 1, 'a');
693 
694         // HTTP/1.0
695         res.version(10);
696         res.erase(field::connection);
697 
698         keep_alive(false);
699         BEAST_EXPECT(res.count(field::connection) == 0);
700 
701         res.set(field::connection, "close");
702         keep_alive(false);
703         BEAST_EXPECT(res.count(field::connection) == 0);
704 
705         res.set(field::connection, "keep-alive");
706         keep_alive(false);
707         BEAST_EXPECT(res.count(field::connection) == 0);
708 
709         res.set(field::connection, "keep-alive, close");
710         keep_alive(false);
711         BEAST_EXPECT(res.count(field::connection) == 0);
712 
713         res.erase(field::connection);
714         keep_alive(true);
715         BEAST_EXPECT(res[field::connection] == "keep-alive");
716 
717         res.set(field::connection, "close");
718         keep_alive(true);
719         BEAST_EXPECT(res[field::connection] == "keep-alive");
720 
721         res.set(field::connection, "keep-alive");
722         keep_alive(true);
723         BEAST_EXPECT(res[field::connection] == "keep-alive");
724 
725         res.set(field::connection, "keep-alive, close");
726         keep_alive(true);
727         BEAST_EXPECT(res[field::connection] == "keep-alive");
728 
729         auto const test10 =
730             [&](std::string s)
731         {
732             res.set(field::connection, s);
733             keep_alive(false);
734             BEAST_EXPECT(res[field::connection] == s);
735 
736             res.set(field::connection, s + ", close");
737             keep_alive(false);
738             BEAST_EXPECT(res[field::connection] == s);
739 
740             res.set(field::connection, "keep-alive, " + s);
741             keep_alive(false);
742             BEAST_EXPECT(res[field::connection] == s);
743 
744             res.set(field::connection, "keep-alive, " + s + ", close");
745             keep_alive(false);
746             BEAST_EXPECT(res[field::connection] == s);
747 
748             res.set(field::connection, s);
749             keep_alive(true);
750             BEAST_EXPECT(res[field::connection] == s + ", keep-alive");
751 
752             res.set(field::connection, s + ", close");
753             keep_alive(true);
754             BEAST_EXPECT(res[field::connection] == s + ", keep-alive");
755 
756             res.set(field::connection, "keep-alive, " + s);
757             keep_alive(true);
758             BEAST_EXPECT(res[field::connection] == "keep-alive, " + s);
759 
760             res.set(field::connection, "keep-alive, " + s+ ", close");
761             keep_alive(true);
762             BEAST_EXPECT(res[field::connection] == "keep-alive, " + s);
763         };
764 
765         test10("foo");
766         test10(big);
767 
768         // HTTP/1.1
769         res.version(11);
770 
771         res.erase(field::connection);
772         keep_alive(true);
773         BEAST_EXPECT(res.count(field::connection) == 0);
774 
775         res.set(field::connection, "close");
776         keep_alive(true);
777         BEAST_EXPECT(res.count(field::connection) == 0);
778 
779         res.set(field::connection, "keep-alive");
780         keep_alive(true);
781         BEAST_EXPECT(res.count(field::connection) == 0);
782 
783         res.set(field::connection, "keep-alive, close");
784         keep_alive(true);
785         BEAST_EXPECT(res.count(field::connection) == 0);
786 
787         res.erase(field::connection);
788         keep_alive(false);
789         BEAST_EXPECT(res[field::connection] == "close");
790 
791         res.set(field::connection, "close");
792         keep_alive(false);
793         BEAST_EXPECT(res[field::connection] == "close");
794 
795         res.set(field::connection, "keep-alive");
796         keep_alive(false);
797         BEAST_EXPECT(res[field::connection] == "close");
798 
799         res.set(field::connection, "keep-alive, close");
800         keep_alive(false);
801         BEAST_EXPECT(res[field::connection] == "close");
802 
803         auto const test11 =
804             [&](std::string s)
805         {
806             res.set(field::connection, s);
807             keep_alive(true);
808             BEAST_EXPECT(res[field::connection] == s);
809 
810             res.set(field::connection, s + ", close");
811             keep_alive(true);
812             BEAST_EXPECT(res[field::connection] == s);
813 
814             res.set(field::connection, "keep-alive, " + s);
815             keep_alive(true);
816             BEAST_EXPECT(res[field::connection] == s);
817 
818             res.set(field::connection, "keep-alive, " + s + ", close");
819             keep_alive(true);
820             BEAST_EXPECT(res[field::connection] == s);
821 
822             res.set(field::connection, s);
823             keep_alive(false);
824             BEAST_EXPECT(res[field::connection] == s + ", close");
825 
826             res.set(field::connection, "close, " + s);
827             keep_alive(false);
828             BEAST_EXPECT(res[field::connection] == "close, " + s);
829 
830             res.set(field::connection, "keep-alive, " + s);
831             keep_alive(false);
832             BEAST_EXPECT(res[field::connection] == s + ", close");
833 
834             res.set(field::connection, "close, " + s + ", keep-alive");
835             keep_alive(false);
836             BEAST_EXPECT(res[field::connection] == "close, " + s);
837         };
838 
839         test11("foo");
840         test11(big);
841     }
842 
843     void
testContentLength()844     testContentLength()
845     {
846         response<empty_body> res{status::ok, 11};
847         BEAST_EXPECT(res.count(field::content_length) == 0);
848         BEAST_EXPECT(res.count(field::transfer_encoding) == 0);
849 
850         res.content_length(0);
851         BEAST_EXPECT(res[field::content_length] == "0");
852 
853         res.content_length(100);
854         BEAST_EXPECT(res[field::content_length] == "100");
855 
856         res.content_length(boost::none);
857         BEAST_EXPECT(res.count(field::content_length) == 0);
858 
859         res.set(field::transfer_encoding, "chunked");
860         res.content_length(0);
861         BEAST_EXPECT(res[field::content_length] == "0");
862         BEAST_EXPECT(res.count(field::transfer_encoding) == 0);
863 
864         res.set(field::transfer_encoding, "chunked");
865         res.content_length(100);
866         BEAST_EXPECT(res[field::content_length] == "100");
867         BEAST_EXPECT(res.count(field::transfer_encoding) == 0);
868 
869         res.set(field::transfer_encoding, "chunked");
870         res.content_length(boost::none);
871         BEAST_EXPECT(res.count(field::content_length) == 0);
872         BEAST_EXPECT(res.count(field::transfer_encoding) == 0);
873 
874         auto const check = [&](std::string s)
875         {
876             res.set(field::transfer_encoding, s);
877             res.content_length(0);
878             BEAST_EXPECT(res[field::content_length] == "0");
879             BEAST_EXPECT(res[field::transfer_encoding] == s);
880 
881             res.set(field::transfer_encoding, s);
882             res.content_length(100);
883             BEAST_EXPECT(res[field::content_length] == "100");
884             BEAST_EXPECT(res[field::transfer_encoding] == s);
885 
886             res.set(field::transfer_encoding, s);
887             res.content_length(boost::none);
888             BEAST_EXPECT(res.count(field::content_length) == 0);
889             BEAST_EXPECT(res[field::transfer_encoding] == s);
890 
891             res.set(field::transfer_encoding, s + ", chunked");
892             res.content_length(0);
893             BEAST_EXPECT(res[field::content_length] == "0");
894             BEAST_EXPECT(res[field::transfer_encoding] == s);
895 
896             res.set(field::transfer_encoding, s + ", chunked");
897             res.content_length(100);
898             BEAST_EXPECT(res[field::content_length] == "100");
899             BEAST_EXPECT(res[field::transfer_encoding] == s);
900 
901             res.set(field::transfer_encoding, s + ", chunked");
902             res.content_length(boost::none);
903             BEAST_EXPECT(res.count(field::content_length) == 0);
904             BEAST_EXPECT(res[field::transfer_encoding] == s);
905 
906             res.set(field::transfer_encoding, "chunked, " + s);
907             res.content_length(0);
908             BEAST_EXPECT(res[field::content_length] == "0");
909             BEAST_EXPECT(res[field::transfer_encoding] == "chunked, " + s);
910 
911             res.set(field::transfer_encoding, "chunked, " + s);
912             res.content_length(100);
913             BEAST_EXPECT(res[field::content_length] == "100");
914             BEAST_EXPECT(res[field::transfer_encoding] == "chunked, " + s);
915 
916             res.set(field::transfer_encoding, "chunked, " + s);
917             res.content_length(boost::none);
918             BEAST_EXPECT(res.count(field::content_length) == 0);
919             BEAST_EXPECT(res[field::transfer_encoding] == "chunked, " + s);
920         };
921 
922         check("foo");
923 
924         std::string const big(max_static_buffer + 1, 'a');
925 
926         check(big);
927     }
928 
929     void
testChunked()930     testChunked()
931     {
932         response<empty_body> res{status::ok, 11};
933         BEAST_EXPECT(res.count(field::content_length) == 0);
934         BEAST_EXPECT(res.count(field::transfer_encoding) == 0);
935 
936         auto const chunked =
937             [&](bool v)
938             {
939                 res.chunked(v);
940                 BEAST_EXPECT(
941                     (res.chunked() && v) ||
942                     (! res.chunked() && ! v));
943                 BEAST_EXPECT(res.count(
944                     field::content_length) == 0);
945             };
946 
947         res.erase(field::transfer_encoding);
948         res.set(field::content_length, to_static_string(32));
949         chunked(true);
950         BEAST_EXPECT(res[field::transfer_encoding] == "chunked");
951 
952         res.set(field::transfer_encoding, "chunked");
953         chunked(true);
954         BEAST_EXPECT(res[field::transfer_encoding] == "chunked");
955 
956         res.erase(field::transfer_encoding);
957         res.set(field::content_length, to_static_string(32));
958         chunked(false);
959         BEAST_EXPECT(res.count(field::transfer_encoding) == 0);
960 
961         res.set(field::transfer_encoding, "chunked");
962         chunked(false);
963         BEAST_EXPECT(res.count(field::transfer_encoding) == 0);
964 
965 
966 
967         res.set(field::transfer_encoding, "foo");
968         chunked(true);
969         BEAST_EXPECT(res[field::transfer_encoding] == "foo, chunked");
970 
971         res.set(field::transfer_encoding, "chunked, foo");
972         chunked(true);
973         BEAST_EXPECT(res[field::transfer_encoding] == "chunked, foo, chunked");
974 
975         res.set(field::transfer_encoding, "chunked, foo, chunked");
976         chunked(true);
977         BEAST_EXPECT(res[field::transfer_encoding] == "chunked, foo, chunked");
978 
979         res.set(field::transfer_encoding, "foo, chunked");
980         chunked(false);
981         BEAST_EXPECT(res[field::transfer_encoding] == "foo");
982 
983         res.set(field::transfer_encoding, "chunked, foo");
984         chunked(false);
985         BEAST_EXPECT(res[field::transfer_encoding] == "chunked, foo");
986 
987         res.set(field::transfer_encoding, "chunked, foo, chunked");
988         chunked(false);
989         BEAST_EXPECT(res[field::transfer_encoding] == "chunked, foo");
990     }
991 
992     void
testIssue1828()993     testIssue1828()
994     {
995         beast::http::fields req;
996         req.insert("abc", "1");
997         req.insert("abc", "2");
998         req.insert("abc", "3");
999         BEAST_EXPECT(req.count("abc") == 3);
1000         auto iter = req.find("abc");
1001         BEAST_EXPECT(iter->value() == "1");
1002         req.insert("abc", "4");
1003         req.erase(iter);
1004         BEAST_EXPECT(req.count("abc") == 3);
1005     }
1006 
1007     template<class Arg1, class InArg>
1008     struct set_test
1009     {
1010         static auto test(...) ->
1011             std::false_type;
1012 
1013         template<class U = InArg>
1014         static auto test(U arg) ->
1015             decltype(std::declval<fields>().
1016                 set(std::declval<Arg1>(),
1017                     std::declval<U>()),
1018                 std::true_type());
1019 
1020         static constexpr bool value =
1021             decltype(test(std::declval<InArg>()))::value;
1022     };
1023 
1024     template<class Arg1, class InArg>
1025     struct insert_test
1026     {
1027         static auto test(...) ->
1028             std::false_type;
1029 
1030         template<class U = InArg>
1031         static auto test(U arg) ->
1032             decltype(std::declval<fields>().
1033                 insert(std::declval<Arg1>(),
1034                     std::declval<U>()),
1035                 std::true_type());
1036 
1037         static constexpr bool value =
1038             decltype(test(std::declval<InArg>()))::value;
1039     };
1040 
1041     void
testIssue2085()1042     testIssue2085()
1043     {
1044         BOOST_STATIC_ASSERT((! set_test<field, int>::value));
1045         BOOST_STATIC_ASSERT((! set_test<field, std::nullptr_t>::value));
1046         BOOST_STATIC_ASSERT((! set_test<field, double>::value));
1047         BOOST_STATIC_ASSERT((! set_test<string_view, int>::value));
1048         BOOST_STATIC_ASSERT((! set_test<string_view, std::nullptr_t>::value));
1049         BOOST_STATIC_ASSERT((! set_test<string_view, double>::value));
1050 
1051         BOOST_STATIC_ASSERT(( set_test<field, const char*>::value));
1052         BOOST_STATIC_ASSERT(( set_test<field, string_view>::value));
1053         BOOST_STATIC_ASSERT(( set_test<field, const char(&)[10]>::value));
1054         BOOST_STATIC_ASSERT(( set_test<string_view, const char*>::value));
1055         BOOST_STATIC_ASSERT(( set_test<string_view, string_view>::value));
1056         BOOST_STATIC_ASSERT(( set_test<string_view, const char(&)[10]>::value));
1057 
1058         BOOST_STATIC_ASSERT((! insert_test<field, int>::value));
1059         BOOST_STATIC_ASSERT((! insert_test<field, std::nullptr_t>::value));
1060         BOOST_STATIC_ASSERT((! insert_test<field, double>::value));
1061         BOOST_STATIC_ASSERT((! insert_test<string_view, int>::value));
1062         BOOST_STATIC_ASSERT((! insert_test<string_view, std::nullptr_t>::value));
1063         BOOST_STATIC_ASSERT((! insert_test<string_view, double>::value));
1064 
1065         BOOST_STATIC_ASSERT(( insert_test<field, const char*>::value));
1066         BOOST_STATIC_ASSERT(( insert_test<field, string_view>::value));
1067         BOOST_STATIC_ASSERT(( insert_test<field, const char(&)[10]>::value));
1068         BOOST_STATIC_ASSERT(( insert_test<string_view, const char*>::value));
1069         BOOST_STATIC_ASSERT(( insert_test<string_view, string_view>::value));
1070         BOOST_STATIC_ASSERT(( insert_test<string_view, const char(&)[10]>::value));
1071     }
1072 
1073     void
run()1074     run() override
1075     {
1076         testMembers();
1077         testHeaders();
1078         testRFC2616();
1079         testErase();
1080         testIteratorErase();
1081         testContainer();
1082         testPreparePayload();
1083 
1084         testKeepAlive();
1085         testContentLength();
1086         testChunked();
1087 
1088         testIssue1828();
1089         boost::ignore_unused(&fields_test::testIssue2085);
1090     }
1091 };
1092 
1093 BEAST_DEFINE_TESTSUITE(beast,http,fields);
1094 
1095 } // http
1096 } // beast
1097 } // boost
1098