]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/beast/test/beast/http/fields.cpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / libs / beast / test / beast / http / fields.cpp
CommitLineData
b32b8144 1//
92f5a8d4 2// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
b32b8144
FG
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
20effc67 13#include <boost/beast/core/static_string.hpp>
b32b8144
FG
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>
92f5a8d4 18#include <boost/beast/_experimental/unit_test/suite.hpp>
b32b8144
FG
19#include <string>
20
21namespace boost {
22namespace beast {
23namespace http {
24
b32b8144
FG
25class fields_test : public beast::unit_test::suite
26{
27public:
92f5a8d4
TL
28 static constexpr std::size_t max_static_buffer =
29 sizeof(beast::detail::temporary_buffer);
30
11fdf7f2
TL
31 template<class T>
32 class test_allocator
33 {
34 public:
35 using value_type = T;
36
37 test_allocator() noexcept(false) {}
38
39 template<class U, class = typename
40 std::enable_if<!std::is_same<test_allocator, U>::value>::type>
41 test_allocator(test_allocator<U> const&) noexcept {}
42
43 value_type*
44 allocate(std::size_t n)
45 {
46 return static_cast<value_type*>(::operator new (n*sizeof(value_type)));
47 }
48
49 void
50 deallocate(value_type* p, std::size_t) noexcept
51 {
52 ::operator delete(p);
53 }
54
55 template<class U>
56 friend
57 bool
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
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
b32b8144
FG
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
95 fill(std::size_t n, basic_fields<Allocator>& f)
96 {
97 for(std::size_t i = 1; i<= n; ++i)
20effc67 98 f.insert(std::to_string(i), to_static_string(i));
b32b8144
FG
99 }
100
101 template<class U, class V>
102 static
103 void
104 self_assign(U& u, V&& v)
105 {
106 u = std::forward<V>(v);
107 }
108
109 template<class Alloc>
110 static
111 bool
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
120 size(basic_fields<Alloc> const& f)
121 {
122 return std::distance(f.begin(), f.end());
123 }
124
125 void
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
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
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
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
11fdf7f2
TL
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
b32b8144
FG
409 void
410 testContainer()
411 {
412 {
413 // group fields
414 fields f;
20effc67
TL
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));
b32b8144
FG
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;
20effc67
TL
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));
b32b8144
FG
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;
20effc67
TL
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));
b32b8144
FG
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;
20effc67
TL
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));
b32b8144
FG
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
503 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
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
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
92f5a8d4 692 std::string const big(max_static_buffer + 1, 'a');
b32b8144
FG
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
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");
92f5a8d4 852
b32b8144
FG
853 res.content_length(100);
854 BEAST_EXPECT(res[field::content_length] == "100");
92f5a8d4 855
b32b8144
FG
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);
92f5a8d4 863
b32b8144
FG
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);
92f5a8d4 868
b32b8144
FG
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);
92f5a8d4 880
b32b8144
FG
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);
92f5a8d4 885
b32b8144
FG
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);
92f5a8d4 895
b32b8144
FG
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);
92f5a8d4 900
b32b8144
FG
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);
92f5a8d4 910
b32b8144
FG
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);
92f5a8d4 915
b32b8144
FG
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
92f5a8d4 924 std::string const big(max_static_buffer + 1, 'a');
b32b8144
FG
925
926 check(big);
927 }
928
929 void
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);
20effc67 948 res.set(field::content_length, to_static_string(32));
b32b8144
FG
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);
20effc67 957 res.set(field::content_length, to_static_string(32));
b32b8144
FG
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
f67539c2
TL
992 void
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
20effc67
TL
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
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
b32b8144
FG
1073 void
1074 run() override
1075 {
1076 testMembers();
1077 testHeaders();
1078 testRFC2616();
1079 testErase();
11fdf7f2 1080 testIteratorErase();
b32b8144
FG
1081 testContainer();
1082 testPreparePayload();
1083
1084 testKeepAlive();
1085 testContentLength();
1086 testChunked();
f67539c2
TL
1087
1088 testIssue1828();
20effc67 1089 boost::ignore_unused(&fields_test::testIssue2085);
b32b8144
FG
1090 }
1091};
1092
1093BEAST_DEFINE_TESTSUITE(beast,http,fields);
1094
1095} // http
1096} // beast
1097} // boost