1 // Copyright 2022 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Note that several of the BalsaHeaders functions are
6 // tested in the balsa_frame_test as the BalsaFrame and
7 // BalsaHeaders classes are fairly related.
8
9 #include "quiche/balsa/balsa_headers.h"
10
11 #include <cstring>
12 #include <limits>
13 #include <memory>
14 #include <sstream>
15 #include <string>
16 #include <tuple>
17 #include <utility>
18 #include <vector>
19
20 #include "absl/base/macros.h"
21 #include "absl/memory/memory.h"
22 #include "absl/strings/str_cat.h"
23 #include "absl/strings/str_format.h"
24 #include "absl/strings/string_view.h"
25 #include "quiche/balsa/balsa_enums.h"
26 #include "quiche/balsa/balsa_frame.h"
27 #include "quiche/balsa/simple_buffer.h"
28 #include "quiche/common/platform/api/quiche_expect_bug.h"
29 #include "quiche/common/platform/api/quiche_logging.h"
30 #include "quiche/common/platform/api/quiche_test.h"
31
32 using absl::make_unique;
33 using testing::AnyOf;
34 using testing::Combine;
35 using testing::ElementsAre;
36 using testing::Eq;
37 using testing::StrEq;
38 using testing::ValuesIn;
39
40 namespace quiche {
41
42 namespace test {
43
44 class BalsaHeadersTestPeer {
45 public:
WriteFromFramer(BalsaHeaders * headers,const char * ptr,size_t size)46 static void WriteFromFramer(BalsaHeaders* headers, const char* ptr,
47 size_t size) {
48 headers->WriteFromFramer(ptr, size);
49 }
50 };
51
52 namespace {
53
54 class BalsaBufferTest : public QuicheTest {
55 public:
CreateBuffer(size_t blocksize)56 void CreateBuffer(size_t blocksize) {
57 buffer_ = std::make_unique<BalsaBuffer>(blocksize);
58 }
CreateBuffer()59 void CreateBuffer() { buffer_ = std::make_unique<BalsaBuffer>(); }
CreateUnmanagedBuffer(size_t blocksize)60 static std::unique_ptr<BalsaBuffer> CreateUnmanagedBuffer(size_t blocksize) {
61 return std::make_unique<BalsaBuffer>(blocksize);
62 }
Write(absl::string_view sp,size_t * block_buffer_idx)63 absl::string_view Write(absl::string_view sp, size_t* block_buffer_idx) {
64 if (sp.empty()) {
65 return sp;
66 }
67 char* storage = buffer_->Reserve(sp.size(), block_buffer_idx);
68 memcpy(storage, sp.data(), sp.size());
69 return absl::string_view(storage, sp.size());
70 }
71
72 protected:
73 std::unique_ptr<BalsaBuffer> buffer_;
74 };
75
76 using BufferBlock = BalsaBuffer::BufferBlock;
77
MakeBufferBlock(const std::string & s)78 BufferBlock MakeBufferBlock(const std::string& s) {
79 // Make the buffer twice the size needed to verify that CopyFrom copies our
80 // buffer_size (as opposed to shrinking to fit or reusing an old buffer).
81 BufferBlock block{make_unique<char[]>(s.size()), s.size() * 2, s.size()};
82 std::memcpy(block.buffer.get(), s.data(), s.size());
83 return block;
84 }
85
CreateHTTPHeaders(bool request,absl::string_view s)86 BalsaHeaders CreateHTTPHeaders(bool request, absl::string_view s) {
87 BalsaHeaders headers;
88 BalsaFrame framer;
89 framer.set_is_request(request);
90 framer.set_balsa_headers(&headers);
91 QUICHE_CHECK_EQ(s.size(), framer.ProcessInput(s.data(), s.size()));
92 QUICHE_CHECK(framer.MessageFullyRead());
93 return headers;
94 }
95
96 class BufferBlockTest
97 : public QuicheTestWithParam<std::tuple<const char*, const char*>> {};
98
TEST_P(BufferBlockTest,CopyFrom)99 TEST_P(BufferBlockTest, CopyFrom) {
100 const std::string s1 = std::get<0>(GetParam());
101 const std::string s2 = std::get<1>(GetParam());
102 BufferBlock block;
103 block.CopyFrom(MakeBufferBlock(s1));
104 EXPECT_EQ(s1.size(), block.bytes_free);
105 ASSERT_EQ(2 * s1.size(), block.buffer_size);
106 EXPECT_EQ(0, memcmp(s1.data(), block.buffer.get(), s1.size()));
107 block.CopyFrom(MakeBufferBlock(s2));
108 EXPECT_EQ(s2.size(), block.bytes_free);
109 ASSERT_EQ(2 * s2.size(), block.buffer_size);
110 EXPECT_EQ(0, memcmp(s2.data(), block.buffer.get(), s2.size()));
111 }
112
113 const char* block_strings[] = {"short string", "longer than the other string"};
114 INSTANTIATE_TEST_SUITE_P(VariousSizes, BufferBlockTest,
115 Combine(ValuesIn(block_strings),
116 ValuesIn(block_strings)));
117
TEST_F(BalsaBufferTest,BlocksizeSet)118 TEST_F(BalsaBufferTest, BlocksizeSet) {
119 CreateBuffer();
120 EXPECT_EQ(BalsaBuffer::kDefaultBlocksize, buffer_->blocksize());
121 CreateBuffer(1024);
122 EXPECT_EQ(1024u, buffer_->blocksize());
123 }
124
TEST_F(BalsaBufferTest,GetMemorySize)125 TEST_F(BalsaBufferTest, GetMemorySize) {
126 CreateBuffer(10);
127 EXPECT_EQ(0u, buffer_->GetTotalBytesUsed());
128 EXPECT_EQ(0u, buffer_->GetTotalBufferBlockSize());
129 BalsaBuffer::Blocks::size_type index;
130 buffer_->Reserve(1024, &index);
131 EXPECT_EQ(10u + 1024u, buffer_->GetTotalBufferBlockSize());
132 EXPECT_EQ(1024u, buffer_->GetTotalBytesUsed());
133 }
134
TEST_F(BalsaBufferTest,ManyWritesToContiguousBuffer)135 TEST_F(BalsaBufferTest, ManyWritesToContiguousBuffer) {
136 CreateBuffer(0);
137 // The test is that the process completes. If it needs to do a resize on
138 // every write, it will timeout or run out of memory.
139 // ( 10 + 20 + 30 + ... + 1.2e6 bytes => ~1e11 bytes )
140 std::string data = "0123456789";
141 for (int i = 0; i < 120 * 1000; ++i) {
142 buffer_->WriteToContiguousBuffer(data);
143 }
144 }
145
TEST_F(BalsaBufferTest,CopyFrom)146 TEST_F(BalsaBufferTest, CopyFrom) {
147 CreateBuffer(10);
148 std::unique_ptr<BalsaBuffer> ptr = CreateUnmanagedBuffer(1024);
149 ASSERT_EQ(1024u, ptr->blocksize());
150 EXPECT_EQ(0u, ptr->num_blocks());
151
152 std::string data1 = "foobarbaz01";
153 buffer_->WriteToContiguousBuffer(data1);
154 buffer_->NoMoreWriteToContiguousBuffer();
155 std::string data2 = "12345";
156 Write(data2, nullptr);
157 std::string data3 = "6789";
158 Write(data3, nullptr);
159 std::string data4 = "123456789012345";
160 Write(data3, nullptr);
161
162 ptr->CopyFrom(*buffer_);
163
164 EXPECT_EQ(ptr->can_write_to_contiguous_buffer(),
165 buffer_->can_write_to_contiguous_buffer());
166 ASSERT_EQ(ptr->num_blocks(), buffer_->num_blocks());
167 for (size_t i = 0; i < buffer_->num_blocks(); ++i) {
168 ASSERT_EQ(ptr->bytes_used(i), buffer_->bytes_used(i));
169 ASSERT_EQ(ptr->buffer_size(i), buffer_->buffer_size(i));
170 EXPECT_EQ(0,
171 memcmp(ptr->GetPtr(i), buffer_->GetPtr(i), ptr->bytes_used(i)));
172 }
173 }
174
TEST_F(BalsaBufferTest,ClearWorks)175 TEST_F(BalsaBufferTest, ClearWorks) {
176 CreateBuffer(10);
177
178 std::string data1 = "foobarbaz01";
179 buffer_->WriteToContiguousBuffer(data1);
180 buffer_->NoMoreWriteToContiguousBuffer();
181 std::string data2 = "12345";
182 Write(data2, nullptr);
183 std::string data3 = "6789";
184 Write(data3, nullptr);
185 std::string data4 = "123456789012345";
186 Write(data3, nullptr);
187
188 buffer_->Clear();
189
190 EXPECT_TRUE(buffer_->can_write_to_contiguous_buffer());
191 EXPECT_EQ(10u, buffer_->blocksize());
192 EXPECT_EQ(0u, buffer_->num_blocks());
193 }
194
TEST_F(BalsaBufferTest,ClearWorksWhenLargerThanBlocksize)195 TEST_F(BalsaBufferTest, ClearWorksWhenLargerThanBlocksize) {
196 CreateBuffer(10);
197
198 std::string data1 = "foobarbaz01lkjasdlkjasdlkjasd";
199 buffer_->WriteToContiguousBuffer(data1);
200 buffer_->NoMoreWriteToContiguousBuffer();
201 std::string data2 = "12345";
202 Write(data2, nullptr);
203 std::string data3 = "6789";
204 Write(data3, nullptr);
205 std::string data4 = "123456789012345";
206 Write(data3, nullptr);
207
208 buffer_->Clear();
209
210 EXPECT_TRUE(buffer_->can_write_to_contiguous_buffer());
211 EXPECT_EQ(10u, buffer_->blocksize());
212 EXPECT_EQ(0u, buffer_->num_blocks());
213 }
214
TEST_F(BalsaBufferTest,ContiguousWriteSmallerThanBlocksize)215 TEST_F(BalsaBufferTest, ContiguousWriteSmallerThanBlocksize) {
216 CreateBuffer(1024);
217
218 std::string data1 = "foo";
219 buffer_->WriteToContiguousBuffer(data1);
220 std::string composite = data1;
221 const char* buf_ptr = buffer_->GetPtr(0);
222 ASSERT_LE(composite.size(), buffer_->buffer_size(0));
223 EXPECT_EQ(0, memcmp(composite.data(), buf_ptr, composite.size()));
224
225 std::string data2 = "barbaz";
226 buffer_->WriteToContiguousBuffer(data2);
227 composite += data2;
228 buf_ptr = buffer_->GetPtr(0);
229 ASSERT_LE(composite.size(), buffer_->buffer_size(0));
230 EXPECT_EQ(0, memcmp(composite.data(), buf_ptr, composite.size()));
231 }
232
TEST_F(BalsaBufferTest,SingleContiguousWriteLargerThanBlocksize)233 TEST_F(BalsaBufferTest, SingleContiguousWriteLargerThanBlocksize) {
234 CreateBuffer(10);
235
236 std::string data1 = "abracadabrawords";
237 buffer_->WriteToContiguousBuffer(data1);
238 std::string composite = data1;
239 const char* buf_ptr = buffer_->GetPtr(0);
240 ASSERT_LE(data1.size(), buffer_->buffer_size(0));
241 EXPECT_EQ(0, memcmp(composite.data(), buf_ptr, composite.size()))
242 << composite << "\n"
243 << absl::string_view(buf_ptr, buffer_->bytes_used(0));
244 }
245
TEST_F(BalsaBufferTest,ContiguousWriteLargerThanBlocksize)246 TEST_F(BalsaBufferTest, ContiguousWriteLargerThanBlocksize) {
247 CreateBuffer(10);
248
249 std::string data1 = "123456789";
250 buffer_->WriteToContiguousBuffer(data1);
251 std::string composite = data1;
252 ASSERT_LE(10u, buffer_->buffer_size(0));
253
254 std::string data2 = "0123456789";
255 buffer_->WriteToContiguousBuffer(data2);
256 composite += data2;
257
258 const char* buf_ptr = buffer_->GetPtr(0);
259 ASSERT_LE(composite.size(), buffer_->buffer_size(0));
260 EXPECT_EQ(0, memcmp(composite.data(), buf_ptr, composite.size()))
261 << "composite: " << composite << "\n"
262 << " actual: " << absl::string_view(buf_ptr, buffer_->bytes_used(0));
263 }
264
TEST_F(BalsaBufferTest,TwoContiguousWritesLargerThanBlocksize)265 TEST_F(BalsaBufferTest, TwoContiguousWritesLargerThanBlocksize) {
266 CreateBuffer(5);
267
268 std::string data1 = "123456";
269 buffer_->WriteToContiguousBuffer(data1);
270 std::string composite = data1;
271 ASSERT_LE(composite.size(), buffer_->buffer_size(0));
272
273 std::string data2 = "7890123";
274 buffer_->WriteToContiguousBuffer(data2);
275 composite += data2;
276
277 const char* buf_ptr = buffer_->GetPtr(0);
278 ASSERT_LE(composite.size(), buffer_->buffer_size(0));
279 EXPECT_EQ(0, memcmp(composite.data(), buf_ptr, composite.size()))
280 << "composite: " << composite << "\n"
281 << " actual: " << absl::string_view(buf_ptr, buffer_->bytes_used(0));
282 }
283
TEST_F(BalsaBufferTest,WriteSmallerThanBlocksize)284 TEST_F(BalsaBufferTest, WriteSmallerThanBlocksize) {
285 CreateBuffer(5);
286 std::string data1 = "1234";
287 size_t block_idx = 0;
288 absl::string_view write_result = Write(data1, &block_idx);
289 ASSERT_EQ(1u, block_idx);
290 EXPECT_THAT(write_result, StrEq(data1));
291
292 CreateBuffer(5);
293 data1 = "1234";
294 block_idx = 0;
295 write_result = Write(data1, &block_idx);
296 ASSERT_EQ(1u, block_idx);
297 EXPECT_THAT(write_result, StrEq(data1));
298 }
299
TEST_F(BalsaBufferTest,TwoWritesSmallerThanBlocksizeThenAnotherWrite)300 TEST_F(BalsaBufferTest, TwoWritesSmallerThanBlocksizeThenAnotherWrite) {
301 CreateBuffer(10);
302 std::string data1 = "12345";
303 size_t block_idx = 0;
304 absl::string_view write_result = Write(data1, &block_idx);
305 ASSERT_EQ(1u, block_idx);
306 EXPECT_THAT(write_result, StrEq(data1));
307
308 std::string data2 = "data2";
309 block_idx = 0;
310 write_result = Write(data2, &block_idx);
311 ASSERT_EQ(1u, block_idx);
312 EXPECT_THAT(write_result, StrEq(data2));
313
314 std::string data3 = "data3";
315 block_idx = 0;
316 write_result = Write(data3, &block_idx);
317 ASSERT_EQ(2u, block_idx);
318 EXPECT_THAT(write_result, StrEq(data3));
319
320 CreateBuffer(10);
321 buffer_->NoMoreWriteToContiguousBuffer();
322 data1 = "12345";
323 block_idx = 0;
324 write_result = Write(data1, &block_idx);
325 ASSERT_EQ(0u, block_idx);
326 EXPECT_THAT(write_result, StrEq(data1));
327
328 data2 = "data2";
329 block_idx = 0;
330 write_result = Write(data2, &block_idx);
331 ASSERT_EQ(0u, block_idx);
332 EXPECT_THAT(write_result, StrEq(data2));
333
334 data3 = "data3";
335 block_idx = 0;
336 write_result = Write(data3, &block_idx);
337 ASSERT_EQ(1u, block_idx);
338 EXPECT_THAT(write_result, StrEq(data3));
339 }
340
TEST_F(BalsaBufferTest,WriteLargerThanBlocksize)341 TEST_F(BalsaBufferTest, WriteLargerThanBlocksize) {
342 CreateBuffer(5);
343 std::string data1 = "123456789";
344 size_t block_idx = 0;
345 absl::string_view write_result = Write(data1, &block_idx);
346 ASSERT_EQ(1u, block_idx);
347 EXPECT_THAT(write_result, StrEq(data1));
348
349 CreateBuffer(5);
350 buffer_->NoMoreWriteToContiguousBuffer();
351 data1 = "123456789";
352 block_idx = 0;
353 write_result = Write(data1, &block_idx);
354 ASSERT_EQ(1u, block_idx);
355 EXPECT_THAT(write_result, StrEq(data1));
356 }
357
TEST_F(BalsaBufferTest,ContiguousThenTwoSmallerThanBlocksize)358 TEST_F(BalsaBufferTest, ContiguousThenTwoSmallerThanBlocksize) {
359 CreateBuffer(5);
360 std::string data1 = "1234567890";
361 buffer_->WriteToContiguousBuffer(data1);
362 size_t block_idx = 0;
363 std::string data2 = "1234";
364 absl::string_view write_result = Write(data2, &block_idx);
365 ASSERT_EQ(1u, block_idx);
366 std::string data3 = "1234";
367 write_result = Write(data3, &block_idx);
368 ASSERT_EQ(2u, block_idx);
369 }
370
TEST_F(BalsaBufferTest,AccessFirstBlockUninitialized)371 TEST_F(BalsaBufferTest, AccessFirstBlockUninitialized) {
372 CreateBuffer(5);
373 EXPECT_EQ(0u, buffer_->GetReadableBytesOfFirstBlock());
374 EXPECT_QUICHE_BUG(buffer_->StartOfFirstBlock(),
375 "First block not allocated yet!");
376 EXPECT_QUICHE_BUG(buffer_->EndOfFirstBlock(),
377 "First block not allocated yet!");
378 }
379
TEST_F(BalsaBufferTest,AccessFirstBlockInitialized)380 TEST_F(BalsaBufferTest, AccessFirstBlockInitialized) {
381 CreateBuffer(5);
382 std::string data1 = "1234567890";
383 buffer_->WriteToContiguousBuffer(data1);
384 const char* start = buffer_->StartOfFirstBlock();
385 EXPECT_TRUE(start != nullptr);
386 const char* end = buffer_->EndOfFirstBlock();
387 EXPECT_TRUE(end != nullptr);
388 EXPECT_EQ(data1.length(), static_cast<size_t>(end - start));
389 EXPECT_EQ(data1.length(), buffer_->GetReadableBytesOfFirstBlock());
390 }
391
TEST(BalsaHeaders,CanAssignBeginToIterator)392 TEST(BalsaHeaders, CanAssignBeginToIterator) {
393 {
394 BalsaHeaders header;
395 BalsaHeaders::const_header_lines_iterator chli = header.lines().begin();
396 static_cast<void>(chli);
397 }
398 {
399 const BalsaHeaders header;
400 BalsaHeaders::const_header_lines_iterator chli = header.lines().begin();
401 static_cast<void>(chli);
402 }
403 }
404
TEST(BalsaHeaders,CanAssignEndToIterator)405 TEST(BalsaHeaders, CanAssignEndToIterator) {
406 {
407 BalsaHeaders header;
408 BalsaHeaders::const_header_lines_iterator chli = header.lines().end();
409 static_cast<void>(chli);
410 }
411 {
412 const BalsaHeaders header;
413 BalsaHeaders::const_header_lines_iterator chli = header.lines().end();
414 static_cast<void>(chli);
415 }
416 }
417
TEST(BalsaHeaders,ReplaceOrAppendHeaderTestAppending)418 TEST(BalsaHeaders, ReplaceOrAppendHeaderTestAppending) {
419 BalsaHeaders header;
420 std::string key_1 = "key_1";
421 std::string value_1 = "value_1";
422 header.ReplaceOrAppendHeader(key_1, value_1);
423
424 BalsaHeaders::const_header_lines_iterator chli = header.lines().begin();
425 ASSERT_EQ(absl::string_view("key_1"), chli->first);
426 ASSERT_EQ(absl::string_view("value_1"), chli->second);
427 ++chli;
428 ASSERT_NE(header.lines().begin(), chli);
429 ASSERT_EQ(header.lines().end(), chli);
430 }
431
TEST(BalsaHeaders,ReplaceOrAppendHeaderTestReplacing)432 TEST(BalsaHeaders, ReplaceOrAppendHeaderTestReplacing) {
433 BalsaHeaders header;
434 std::string key_1 = "key_1";
435 std::string value_1 = "value_1";
436 std::string key_2 = "key_2";
437 header.ReplaceOrAppendHeader(key_1, value_1);
438 header.ReplaceOrAppendHeader(key_2, value_1);
439 std::string value_2 = "value_2_string";
440 header.ReplaceOrAppendHeader(key_1, value_2);
441
442 BalsaHeaders::const_header_lines_iterator chli = header.lines().begin();
443 ASSERT_EQ(key_1, chli->first);
444 ASSERT_EQ(value_2, chli->second);
445 ++chli;
446 ASSERT_EQ(key_2, chli->first);
447 ASSERT_EQ(value_1, chli->second);
448 ++chli;
449 ASSERT_NE(header.lines().begin(), chli);
450 ASSERT_EQ(header.lines().end(), chli);
451 }
452
TEST(BalsaHeaders,ReplaceOrAppendHeaderTestReplacingMultiple)453 TEST(BalsaHeaders, ReplaceOrAppendHeaderTestReplacingMultiple) {
454 BalsaHeaders header;
455 std::string key_1 = "key_1";
456 std::string key_2 = "key_2";
457 std::string value_1 = "val_1";
458 std::string value_2 = "val_2";
459 std::string value_3 =
460 "value_3_is_longer_than_value_1_and_value_2_and_their_keys";
461 // Set up header keys 1, 1, 2. We will replace the value of key 1 with a long
462 // enough string that it should be moved to the end. This regression tests
463 // that replacement works if we move the header to the end.
464 header.AppendHeader(key_1, value_1);
465 header.AppendHeader(key_1, value_2);
466 header.AppendHeader(key_2, value_1);
467 header.ReplaceOrAppendHeader(key_1, value_3);
468
469 BalsaHeaders::const_header_lines_iterator chli = header.lines().begin();
470 ASSERT_EQ(key_1, chli->first);
471 ASSERT_EQ(value_3, chli->second);
472 ++chli;
473 ASSERT_EQ(key_2, chli->first);
474 ASSERT_EQ(value_1, chli->second);
475 ++chli;
476 ASSERT_NE(header.lines().begin(), chli);
477 ASSERT_EQ(header.lines().end(), chli);
478
479 // Now test that replacement works with a shorter value, so that if we ever do
480 // in-place replacement it's tested.
481 header.ReplaceOrAppendHeader(key_1, value_1);
482 chli = header.lines().begin();
483 ASSERT_EQ(key_1, chli->first);
484 ASSERT_EQ(value_1, chli->second);
485 ++chli;
486 ASSERT_EQ(key_2, chli->first);
487 ASSERT_EQ(value_1, chli->second);
488 ++chli;
489 ASSERT_NE(header.lines().begin(), chli);
490 ASSERT_EQ(header.lines().end(), chli);
491 }
492
TEST(BalsaHeaders,AppendHeaderAndIteratorTest1)493 TEST(BalsaHeaders, AppendHeaderAndIteratorTest1) {
494 BalsaHeaders header;
495 ASSERT_EQ(header.lines().begin(), header.lines().end());
496 {
497 std::string key_1 = "key_1";
498 std::string value_1 = "value_1";
499 header.AppendHeader(key_1, value_1);
500 key_1 = "garbage";
501 value_1 = "garbage";
502 }
503
504 ASSERT_NE(header.lines().begin(), header.lines().end());
505 BalsaHeaders::const_header_lines_iterator chli = header.lines().begin();
506 ASSERT_EQ(header.lines().begin(), chli);
507 ASSERT_NE(header.lines().end(), chli);
508 ASSERT_EQ(absl::string_view("key_1"), chli->first);
509 ASSERT_EQ(absl::string_view("value_1"), chli->second);
510
511 ++chli;
512 ASSERT_NE(header.lines().begin(), chli);
513 ASSERT_EQ(header.lines().end(), chli);
514 }
515
TEST(BalsaHeaders,AppendHeaderAndIteratorTest2)516 TEST(BalsaHeaders, AppendHeaderAndIteratorTest2) {
517 BalsaHeaders header;
518 ASSERT_EQ(header.lines().begin(), header.lines().end());
519 {
520 std::string key_1 = "key_1";
521 std::string value_1 = "value_1";
522 header.AppendHeader(key_1, value_1);
523 key_1 = "garbage";
524 value_1 = "garbage";
525 }
526 {
527 std::string key_2 = "key_2";
528 std::string value_2 = "value_2";
529 header.AppendHeader(key_2, value_2);
530 key_2 = "garbage";
531 value_2 = "garbage";
532 }
533
534 ASSERT_NE(header.lines().begin(), header.lines().end());
535 BalsaHeaders::const_header_lines_iterator chli = header.lines().begin();
536 ASSERT_EQ(header.lines().begin(), chli);
537 ASSERT_NE(header.lines().end(), chli);
538 ASSERT_EQ(absl::string_view("key_1"), chli->first);
539 ASSERT_EQ(absl::string_view("value_1"), chli->second);
540
541 ++chli;
542 ASSERT_NE(header.lines().begin(), chli);
543 ASSERT_NE(header.lines().end(), chli);
544 ASSERT_EQ(absl::string_view("key_2"), chli->first);
545 ASSERT_EQ(absl::string_view("value_2"), chli->second);
546
547 ++chli;
548 ASSERT_NE(header.lines().begin(), chli);
549 ASSERT_EQ(header.lines().end(), chli);
550 }
551
TEST(BalsaHeaders,AppendHeaderAndIteratorTest3)552 TEST(BalsaHeaders, AppendHeaderAndIteratorTest3) {
553 BalsaHeaders header;
554 ASSERT_EQ(header.lines().begin(), header.lines().end());
555 {
556 std::string key_1 = "key_1";
557 std::string value_1 = "value_1";
558 header.AppendHeader(key_1, value_1);
559 key_1 = "garbage";
560 value_1 = "garbage";
561 }
562 {
563 std::string key_2 = "key_2";
564 std::string value_2 = "value_2";
565 header.AppendHeader(key_2, value_2);
566 key_2 = "garbage";
567 value_2 = "garbage";
568 }
569 {
570 std::string key_3 = "key_3";
571 std::string value_3 = "value_3";
572 header.AppendHeader(key_3, value_3);
573 key_3 = "garbage";
574 value_3 = "garbage";
575 }
576
577 ASSERT_NE(header.lines().begin(), header.lines().end());
578 BalsaHeaders::const_header_lines_iterator chli = header.lines().begin();
579 ASSERT_EQ(header.lines().begin(), chli);
580 ASSERT_NE(header.lines().end(), chli);
581 ASSERT_EQ(absl::string_view("key_1"), chli->first);
582 ASSERT_EQ(absl::string_view("value_1"), chli->second);
583
584 ++chli;
585 ASSERT_NE(header.lines().begin(), chli);
586 ASSERT_NE(header.lines().end(), chli);
587 ASSERT_EQ(absl::string_view("key_2"), chli->first);
588 ASSERT_EQ(absl::string_view("value_2"), chli->second);
589
590 ++chli;
591 ASSERT_NE(header.lines().begin(), chli);
592 ASSERT_NE(header.lines().end(), chli);
593 ASSERT_EQ(absl::string_view("key_3"), chli->first);
594 ASSERT_EQ(absl::string_view("value_3"), chli->second);
595
596 ++chli;
597 ASSERT_NE(header.lines().begin(), chli);
598 ASSERT_EQ(header.lines().end(), chli);
599 }
600
TEST(BalsaHeaders,AppendHeaderAndTestEraseWithIterator)601 TEST(BalsaHeaders, AppendHeaderAndTestEraseWithIterator) {
602 BalsaHeaders header;
603 ASSERT_EQ(header.lines().begin(), header.lines().end());
604 {
605 std::string key_1 = "key_1";
606 std::string value_1 = "value_1";
607 header.AppendHeader(key_1, value_1);
608 key_1 = "garbage";
609 value_1 = "garbage";
610 }
611 {
612 std::string key_2 = "key_2";
613 std::string value_2 = "value_2";
614 header.AppendHeader(key_2, value_2);
615 key_2 = "garbage";
616 value_2 = "garbage";
617 }
618 {
619 std::string key_3 = "key_3";
620 std::string value_3 = "value_3";
621 header.AppendHeader(key_3, value_3);
622 key_3 = "garbage";
623 value_3 = "garbage";
624 }
625 BalsaHeaders::const_header_lines_iterator chli = header.lines().begin();
626 ++chli; // should now point to key_2.
627 ASSERT_EQ(absl::string_view("key_2"), chli->first);
628 header.erase(chli);
629 chli = header.lines().begin();
630
631 ASSERT_NE(header.lines().begin(), header.lines().end());
632 ASSERT_EQ(header.lines().begin(), chli);
633 ASSERT_NE(header.lines().end(), chli);
634 ASSERT_EQ(absl::string_view("key_1"), chli->first);
635 ASSERT_EQ(absl::string_view("value_1"), chli->second);
636
637 ++chli;
638 ASSERT_NE(header.lines().begin(), chli);
639 ASSERT_NE(header.lines().end(), chli);
640 ASSERT_EQ(absl::string_view("key_3"), chli->first);
641 ASSERT_EQ(absl::string_view("value_3"), chli->second);
642
643 ++chli;
644 ASSERT_NE(header.lines().begin(), chli);
645 ASSERT_EQ(header.lines().end(), chli);
646 }
647
TEST(BalsaHeaders,TestSetFirstlineInAdditionalBuffer)648 TEST(BalsaHeaders, TestSetFirstlineInAdditionalBuffer) {
649 BalsaHeaders headers;
650 headers.SetRequestFirstlineFromStringPieces("GET", "/", "HTTP/1.0");
651 ASSERT_THAT(headers.first_line(), StrEq("GET / HTTP/1.0"));
652 }
653
TEST(BalsaHeaders,TestSetFirstlineInOriginalBufferAndIsShorterThanOriginal)654 TEST(BalsaHeaders, TestSetFirstlineInOriginalBufferAndIsShorterThanOriginal) {
655 BalsaHeaders headers = CreateHTTPHeaders(true,
656 "GET /foobar HTTP/1.0\r\n"
657 "\r\n");
658 ASSERT_THAT(headers.first_line(), StrEq("GET /foobar HTTP/1.0"));
659 // Note that this SetRequestFirstlineFromStringPieces should replace the
660 // original one in the -non- 'additional' buffer.
661 headers.SetRequestFirstlineFromStringPieces("GET", "/", "HTTP/1.0");
662 ASSERT_THAT(headers.first_line(), StrEq("GET / HTTP/1.0"));
663 }
664
TEST(BalsaHeaders,TestSetFirstlineInOriginalBufferAndIsLongerThanOriginal)665 TEST(BalsaHeaders, TestSetFirstlineInOriginalBufferAndIsLongerThanOriginal) {
666 // Similar to above, but this time the new firstline is larger than
667 // the original, yet it should still fit into the original -non-
668 // 'additional' buffer as the first header-line has been erased.
669 BalsaHeaders headers = CreateHTTPHeaders(true,
670 "GET / HTTP/1.0\r\n"
671 "some_key: some_value\r\n"
672 "another_key: another_value\r\n"
673 "\r\n");
674 ASSERT_THAT(headers.first_line(), StrEq("GET / HTTP/1.0"));
675 headers.erase(headers.lines().begin());
676 // Note that this SetRequestFirstlineFromStringPieces should replace the
677 // original one in the -non- 'additional' buffer.
678 headers.SetRequestFirstlineFromStringPieces("GET", "/foobar", "HTTP/1.0");
679 ASSERT_THAT(headers.first_line(), StrEq("GET /foobar HTTP/1.0"));
680 }
681
TEST(BalsaHeaders,TestSetFirstlineInAdditionalDataAndIsShorterThanOriginal)682 TEST(BalsaHeaders, TestSetFirstlineInAdditionalDataAndIsShorterThanOriginal) {
683 BalsaHeaders headers;
684 headers.SetRequestFirstlineFromStringPieces("GET", "/foobar", "HTTP/1.0");
685 ASSERT_THAT(headers.first_line(), StrEq("GET /foobar HTTP/1.0"));
686 headers.SetRequestFirstlineFromStringPieces("GET", "/", "HTTP/1.0");
687 ASSERT_THAT(headers.first_line(), StrEq("GET / HTTP/1.0"));
688 }
689
TEST(BalsaHeaders,TestSetFirstlineInAdditionalDataAndIsLongerThanOriginal)690 TEST(BalsaHeaders, TestSetFirstlineInAdditionalDataAndIsLongerThanOriginal) {
691 BalsaHeaders headers;
692 headers.SetRequestFirstlineFromStringPieces("GET", "/", "HTTP/1.0");
693 ASSERT_THAT(headers.first_line(), StrEq("GET / HTTP/1.0"));
694 headers.SetRequestFirstlineFromStringPieces("GET", "/foobar", "HTTP/1.0");
695 ASSERT_THAT(headers.first_line(), StrEq("GET /foobar HTTP/1.0"));
696 }
697
TEST(BalsaHeaders,TestDeletingSubstring)698 TEST(BalsaHeaders, TestDeletingSubstring) {
699 BalsaHeaders headers;
700 headers.SetRequestFirstlineFromStringPieces("GET", "/", "HTTP/1.0");
701 headers.AppendHeader("key1", "value1");
702 headers.AppendHeader("key2", "value2");
703 headers.AppendHeader("key", "value");
704 headers.AppendHeader("unrelated", "value");
705
706 // RemoveAllOfHeader should not delete key1 or key2 given a substring.
707 headers.RemoveAllOfHeader("key");
708 EXPECT_TRUE(headers.HasHeader("key1"));
709 EXPECT_TRUE(headers.HasHeader("key2"));
710 EXPECT_TRUE(headers.HasHeader("unrelated"));
711 EXPECT_FALSE(headers.HasHeader("key"));
712 EXPECT_TRUE(headers.HasHeadersWithPrefix("key"));
713 EXPECT_TRUE(headers.HasHeadersWithPrefix("KeY"));
714 EXPECT_TRUE(headers.HasHeadersWithPrefix("UNREL"));
715 EXPECT_FALSE(headers.HasHeadersWithPrefix("key3"));
716
717 EXPECT_FALSE(headers.GetHeader("key1").empty());
718 EXPECT_FALSE(headers.GetHeader("KEY1").empty());
719 EXPECT_FALSE(headers.GetHeader("key2").empty());
720 EXPECT_FALSE(headers.GetHeader("unrelated").empty());
721 EXPECT_TRUE(headers.GetHeader("key").empty());
722
723 // Add key back in.
724 headers.AppendHeader("key", "");
725 EXPECT_TRUE(headers.HasHeader("key"));
726 EXPECT_TRUE(headers.HasHeadersWithPrefix("key"));
727 EXPECT_TRUE(headers.GetHeader("key").empty());
728
729 // RemoveAllHeadersWithPrefix should delete everything starting with key.
730 headers.RemoveAllHeadersWithPrefix("key");
731 EXPECT_FALSE(headers.HasHeader("key1"));
732 EXPECT_FALSE(headers.HasHeader("key2"));
733 EXPECT_TRUE(headers.HasHeader("unrelated"));
734 EXPECT_FALSE(headers.HasHeader("key"));
735 EXPECT_FALSE(headers.HasHeadersWithPrefix("key"));
736 EXPECT_FALSE(headers.HasHeadersWithPrefix("key1"));
737 EXPECT_FALSE(headers.HasHeadersWithPrefix("key2"));
738 EXPECT_FALSE(headers.HasHeadersWithPrefix("kEy"));
739 EXPECT_TRUE(headers.HasHeadersWithPrefix("unrelated"));
740
741 EXPECT_TRUE(headers.GetHeader("key1").empty());
742 EXPECT_TRUE(headers.GetHeader("key2").empty());
743 EXPECT_FALSE(headers.GetHeader("unrelated").empty());
744 EXPECT_TRUE(headers.GetHeader("key").empty());
745 }
746
TEST(BalsaHeaders,TestRemovingValues)747 TEST(BalsaHeaders, TestRemovingValues) {
748 // Remove entire line from headers, twice. Ensures working line-skipping.
749 // Skip consideration of a line whose key is larger than our search key.
750 // Skip consideration of a line whose key is smaller than our search key.
751 // Skip consideration of a line that is already marked for skipping.
752 // Skip consideration of a line whose value is too small.
753 // Skip consideration of a line whose key is correct in length but doesn't
754 // match.
755 {
756 BalsaHeaders headers;
757 headers.SetRequestFirstlineFromStringPieces("GET", "/", "HTTP/1.0");
758 headers.AppendHeader("hi", "hello");
759 headers.AppendHeader("key1", "val1");
760 headers.AppendHeader("key1", "value2");
761 headers.AppendHeader("key1", "value3");
762 headers.AppendHeader("key2", "value4");
763 headers.AppendHeader("unrelated", "value");
764
765 EXPECT_EQ(0u, headers.RemoveValue("key1", ""));
766 EXPECT_EQ(1u, headers.RemoveValue("key1", "value2"));
767
768 std::string key1_vals = headers.GetAllOfHeaderAsString("key1");
769 EXPECT_THAT(key1_vals, StrEq("val1,value3"));
770
771 EXPECT_TRUE(headers.HeaderHasValue("key1", "val1"));
772 EXPECT_TRUE(headers.HeaderHasValue("key1", "value3"));
773 EXPECT_EQ("value4", headers.GetHeader("key2"));
774 EXPECT_EQ("hello", headers.GetHeader("hi"));
775 EXPECT_EQ("value", headers.GetHeader("unrelated"));
776 EXPECT_FALSE(headers.HeaderHasValue("key1", "value2"));
777
778 EXPECT_EQ(1u, headers.RemoveValue("key1", "value3"));
779
780 key1_vals = headers.GetAllOfHeaderAsString("key1");
781 EXPECT_THAT(key1_vals, StrEq("val1"));
782
783 EXPECT_TRUE(headers.HeaderHasValue("key1", "val1"));
784 EXPECT_EQ("value4", headers.GetHeader("key2"));
785 EXPECT_EQ("hello", headers.GetHeader("hi"));
786 EXPECT_EQ("value", headers.GetHeader("unrelated"));
787 EXPECT_FALSE(headers.HeaderHasValue("key1", "value3"));
788 EXPECT_FALSE(headers.HeaderHasValue("key1", "value2"));
789 }
790
791 // Remove/keep values with surrounding spaces.
792 // Remove values from in between others in multi-value line.
793 // Remove entire multi-value line.
794 // Keep value in between removed values in multi-value line.
795 // Keep trailing value that is too small to be matched after removing a match.
796 // Keep value containing matched value (partial but not complete match).
797 // Keep an empty header.
798 {
799 BalsaHeaders headers;
800 headers.SetRequestFirstlineFromStringPieces("GET", "/", "HTTP/1.0");
801 headers.AppendHeader("key1", "value1");
802 headers.AppendHeader("key1", "value2, value3,value2");
803 headers.AppendHeader("key1", "value4 ,value2,value5,val6");
804 headers.AppendHeader("key1", "value2, value2 , value2");
805 headers.AppendHeader("key1", " value2 , value2 ");
806 headers.AppendHeader("key1", " value2 a");
807 headers.AppendHeader("key1", "");
808 headers.AppendHeader("key1", ", ,,");
809 headers.AppendHeader("unrelated", "value");
810
811 EXPECT_EQ(8u, headers.RemoveValue("key1", "value2"));
812
813 std::string key1_vals = headers.GetAllOfHeaderAsString("key1");
814 EXPECT_THAT(key1_vals,
815 StrEq("value1,value3,value4 ,value5,val6,value2 a,,, ,,"));
816
817 EXPECT_EQ("value", headers.GetHeader("unrelated"));
818 EXPECT_TRUE(headers.HeaderHasValue("key1", "value1"));
819 EXPECT_TRUE(headers.HeaderHasValue("key1", "value3"));
820 EXPECT_TRUE(headers.HeaderHasValue("key1", "value4"));
821 EXPECT_TRUE(headers.HeaderHasValue("key1", "value5"));
822 EXPECT_TRUE(headers.HeaderHasValue("key1", "val6"));
823 EXPECT_FALSE(headers.HeaderHasValue("key1", "value2"));
824 }
825
826 {
827 const absl::string_view key("key");
828 const absl::string_view value1("foo\0bar", 7);
829 const absl::string_view value2("value2");
830 const std::string value = absl::StrCat(value1, ",", value2);
831
832 {
833 BalsaHeaders headers;
834 headers.AppendHeader(key, value);
835
836 EXPECT_TRUE(headers.HeaderHasValue(key, value1));
837 EXPECT_TRUE(headers.HeaderHasValue(key, value2));
838 EXPECT_EQ(value, headers.GetAllOfHeaderAsString(key));
839
840 EXPECT_EQ(1u, headers.RemoveValue(key, value2));
841
842 EXPECT_TRUE(headers.HeaderHasValue(key, value1));
843 EXPECT_FALSE(headers.HeaderHasValue(key, value2));
844 EXPECT_EQ(value1, headers.GetAllOfHeaderAsString(key));
845 }
846
847 {
848 BalsaHeaders headers;
849 headers.AppendHeader(key, value1);
850 headers.AppendHeader(key, value2);
851
852 EXPECT_TRUE(headers.HeaderHasValue(key, value1));
853 EXPECT_TRUE(headers.HeaderHasValue(key, value2));
854 EXPECT_EQ(value, headers.GetAllOfHeaderAsString(key));
855
856 EXPECT_EQ(1u, headers.RemoveValue(key, value2));
857
858 EXPECT_TRUE(headers.HeaderHasValue(key, value1));
859 EXPECT_FALSE(headers.HeaderHasValue(key, value2));
860 EXPECT_EQ(value1, headers.GetAllOfHeaderAsString(key));
861 }
862 }
863 }
864
TEST(BalsaHeaders,ZeroAppendToHeaderWithCommaAndSpace)865 TEST(BalsaHeaders, ZeroAppendToHeaderWithCommaAndSpace) {
866 // Create an initial header with zero 'X-Forwarded-For' headers.
867 BalsaHeaders headers = CreateHTTPHeaders(true,
868 "GET / HTTP/1.0\r\n"
869 "\r\n");
870
871 // Use AppendToHeaderWithCommaAndSpace to add 4 new 'X-Forwarded-For' headers.
872 // Appending these headers should preserve the order in which they are added.
873 // i.e. 1.1.1.1, 2.2.2.2, 3.3.3.3, 4.4.4.4
874 headers.AppendToHeaderWithCommaAndSpace("X-Forwarded-For", "1.1.1.1");
875 headers.AppendToHeaderWithCommaAndSpace("X-Forwarded-For", "2.2.2.2");
876 headers.AppendToHeaderWithCommaAndSpace("X-Forwarded-For", "3.3.3.3");
877 headers.AppendToHeaderWithCommaAndSpace("X-Forwarded-For", "4.4.4.4");
878
879 // Fetch the 'X-Forwarded-For' headers and compare them to the expected order.
880 EXPECT_THAT(headers.GetAllOfHeader("X-Forwarded-For"),
881 ElementsAre("1.1.1.1, 2.2.2.2, 3.3.3.3, 4.4.4.4"));
882 }
883
TEST(BalsaHeaders,SingleAppendToHeaderWithCommaAndSpace)884 TEST(BalsaHeaders, SingleAppendToHeaderWithCommaAndSpace) {
885 // Create an initial header with one 'X-Forwarded-For' header.
886 BalsaHeaders headers = CreateHTTPHeaders(true,
887 "GET / HTTP/1.0\r\n"
888 "X-Forwarded-For: 1.1.1.1\r\n"
889 "\r\n");
890
891 // Use AppendToHeaderWithCommaAndSpace to add 4 new 'X-Forwarded-For' headers.
892 // Appending these headers should preserve the order in which they are added.
893 // i.e. 1.1.1.1, 2.2.2.2, 3.3.3.3, 4.4.4.4, 5.5.5.5
894 headers.AppendToHeaderWithCommaAndSpace("X-Forwarded-For", "2.2.2.2");
895 headers.AppendToHeaderWithCommaAndSpace("X-Forwarded-For", "3.3.3.3");
896 headers.AppendToHeaderWithCommaAndSpace("X-Forwarded-For", "4.4.4.4");
897 headers.AppendToHeaderWithCommaAndSpace("X-Forwarded-For", "5.5.5.5");
898
899 // Fetch the 'X-Forwarded-For' headers and compare them to the expected order.
900 EXPECT_THAT(headers.GetAllOfHeader("X-Forwarded-For"),
901 ElementsAre("1.1.1.1, 2.2.2.2, 3.3.3.3, 4.4.4.4, 5.5.5.5"));
902 }
903
TEST(BalsaHeaders,MultipleAppendToHeaderWithCommaAndSpace)904 TEST(BalsaHeaders, MultipleAppendToHeaderWithCommaAndSpace) {
905 // Create an initial header with two 'X-Forwarded-For' headers.
906 BalsaHeaders headers = CreateHTTPHeaders(true,
907 "GET / HTTP/1.0\r\n"
908 "X-Forwarded-For: 1.1.1.1\r\n"
909 "X-Forwarded-For: 2.2.2.2\r\n"
910 "\r\n");
911
912 // Use AppendToHeaderWithCommaAndSpace to add 4 new 'X-Forwarded-For' headers.
913 // Appending these headers should preserve the order in which they are added.
914 // i.e. 1.1.1.1, 2.2.2.2, 3.3.3.3, 4.4.4.4, 5.5.5.5, 6.6.6.6
915 headers.AppendToHeaderWithCommaAndSpace("X-Forwarded-For", "3.3.3.3");
916 headers.AppendToHeaderWithCommaAndSpace("X-Forwarded-For", "4.4.4.4");
917 headers.AppendToHeaderWithCommaAndSpace("X-Forwarded-For", "5.5.5.5");
918 headers.AppendToHeaderWithCommaAndSpace("X-Forwarded-For", "6.6.6.6");
919
920 // Fetch the 'X-Forwarded-For' headers and compare them to the expected order.
921 EXPECT_THAT(
922 headers.GetAllOfHeader("X-Forwarded-For"),
923 ElementsAre("1.1.1.1", "2.2.2.2, 3.3.3.3, 4.4.4.4, 5.5.5.5, 6.6.6.6"));
924 }
925
TEST(BalsaHeaders,HeaderHasValues)926 TEST(BalsaHeaders, HeaderHasValues) {
927 BalsaHeaders headers;
928 headers.SetRequestFirstlineFromStringPieces("GET", "/", "HTTP/1.0");
929 // Make sure we find values at the beginning, middle, and end, and we handle
930 // multiple .find() calls correctly.
931 headers.AppendHeader("key", "val1,val2val2,val2,val3");
932 // Make sure we don't mess up comma/boundary checks for beginning, middle and
933 // end.
934 headers.AppendHeader("key", "val4val5val6");
935 headers.AppendHeader("key", "val11 val12");
936 headers.AppendHeader("key", "v val13");
937 // Make sure we catch the line header
938 headers.AppendHeader("key", "val7");
939 // Make sure there's no out-of-bounds indexing on an empty line.
940 headers.AppendHeader("key", "");
941 // Make sure it works when there's spaces before or after a comma.
942 headers.AppendHeader("key", "val8 , val9 , val10");
943 // Make sure it works when val is surrounded by spaces.
944 headers.AppendHeader("key", " val14 ");
945 // Make sure other keys aren't used.
946 headers.AppendHeader("key2", "val15");
947 // Mixed case.
948 headers.AppendHeader("key", "Val16");
949 headers.AppendHeader("key", "foo, Val17, bar");
950
951 // All case-sensitive.
952 EXPECT_TRUE(headers.HeaderHasValue("key", "val1"));
953 EXPECT_TRUE(headers.HeaderHasValue("key", "val2"));
954 EXPECT_TRUE(headers.HeaderHasValue("key", "val3"));
955 EXPECT_TRUE(headers.HeaderHasValue("key", "val7"));
956 EXPECT_TRUE(headers.HeaderHasValue("key", "val8"));
957 EXPECT_TRUE(headers.HeaderHasValue("key", "val9"));
958 EXPECT_TRUE(headers.HeaderHasValue("key", "val10"));
959 EXPECT_TRUE(headers.HeaderHasValue("key", "val14"));
960 EXPECT_FALSE(headers.HeaderHasValue("key", "val4"));
961 EXPECT_FALSE(headers.HeaderHasValue("key", "val5"));
962 EXPECT_FALSE(headers.HeaderHasValue("key", "val6"));
963 EXPECT_FALSE(headers.HeaderHasValue("key", "val11"));
964 EXPECT_FALSE(headers.HeaderHasValue("key", "val12"));
965 EXPECT_FALSE(headers.HeaderHasValue("key", "val13"));
966 EXPECT_FALSE(headers.HeaderHasValue("key", "val15"));
967 EXPECT_FALSE(headers.HeaderHasValue("key", "val16"));
968 EXPECT_FALSE(headers.HeaderHasValue("key", "val17"));
969
970 // All case-insensitive, only change is for val16 and val17.
971 EXPECT_TRUE(headers.HeaderHasValueIgnoreCase("key", "val1"));
972 EXPECT_TRUE(headers.HeaderHasValueIgnoreCase("key", "val2"));
973 EXPECT_TRUE(headers.HeaderHasValueIgnoreCase("key", "val3"));
974 EXPECT_TRUE(headers.HeaderHasValueIgnoreCase("key", "val7"));
975 EXPECT_TRUE(headers.HeaderHasValueIgnoreCase("key", "val8"));
976 EXPECT_TRUE(headers.HeaderHasValueIgnoreCase("key", "val9"));
977 EXPECT_TRUE(headers.HeaderHasValueIgnoreCase("key", "val10"));
978 EXPECT_TRUE(headers.HeaderHasValueIgnoreCase("key", "val14"));
979 EXPECT_FALSE(headers.HeaderHasValueIgnoreCase("key", "val4"));
980 EXPECT_FALSE(headers.HeaderHasValueIgnoreCase("key", "val5"));
981 EXPECT_FALSE(headers.HeaderHasValueIgnoreCase("key", "val6"));
982 EXPECT_FALSE(headers.HeaderHasValueIgnoreCase("key", "val11"));
983 EXPECT_FALSE(headers.HeaderHasValueIgnoreCase("key", "val12"));
984 EXPECT_FALSE(headers.HeaderHasValueIgnoreCase("key", "val13"));
985 EXPECT_FALSE(headers.HeaderHasValueIgnoreCase("key", "val15"));
986 EXPECT_TRUE(headers.HeaderHasValueIgnoreCase("key", "val16"));
987 EXPECT_TRUE(headers.HeaderHasValueIgnoreCase("key", "val17"));
988 }
989
990 // Because we're dealing with one giant buffer, make sure we don't go beyond
991 // the bounds of the key when doing compares!
TEST(BalsaHeaders,TestNotDeletingBeyondString)992 TEST(BalsaHeaders, TestNotDeletingBeyondString) {
993 BalsaHeaders headers;
994 headers.SetRequestFirstlineFromStringPieces("GET", "/", "HTTP/1.0");
995 headers.AppendHeader("key1", "value1");
996
997 headers.RemoveAllHeadersWithPrefix("key1: value1");
998 EXPECT_NE(headers.lines().begin(), headers.lines().end());
999 }
1000
TEST(BalsaHeaders,TestIteratingOverErasedHeaders)1001 TEST(BalsaHeaders, TestIteratingOverErasedHeaders) {
1002 BalsaHeaders headers;
1003 headers.SetRequestFirstlineFromStringPieces("GET", "/", "HTTP/1.0");
1004 headers.AppendHeader("key1", "value1");
1005 headers.AppendHeader("key2", "value2");
1006 headers.AppendHeader("key3", "value3");
1007 headers.AppendHeader("key4", "value4");
1008 headers.AppendHeader("key5", "value5");
1009 headers.AppendHeader("key6", "value6");
1010
1011 headers.RemoveAllOfHeader("key6");
1012 headers.RemoveAllOfHeader("key5");
1013 headers.RemoveAllOfHeader("key4");
1014
1015 BalsaHeaders::const_header_lines_iterator chli = headers.lines().begin();
1016 EXPECT_NE(headers.lines().end(), chli);
1017 EXPECT_EQ(headers.lines().begin(), chli);
1018 EXPECT_THAT(chli->first, StrEq("key1"));
1019 EXPECT_THAT(chli->second, StrEq("value1"));
1020
1021 ++chli;
1022 EXPECT_NE(headers.lines().end(), chli);
1023 EXPECT_NE(headers.lines().begin(), chli);
1024 EXPECT_THAT(chli->first, StrEq("key2"));
1025 EXPECT_THAT(chli->second, StrEq("value2"));
1026
1027 ++chli;
1028 EXPECT_NE(headers.lines().end(), chli);
1029 EXPECT_NE(headers.lines().begin(), chli);
1030 EXPECT_THAT(chli->first, StrEq("key3"));
1031 EXPECT_THAT(chli->second, StrEq("value3"));
1032
1033 ++chli;
1034 EXPECT_EQ(headers.lines().end(), chli);
1035 EXPECT_NE(headers.lines().begin(), chli);
1036
1037 headers.RemoveAllOfHeader("key1");
1038 headers.RemoveAllOfHeader("key2");
1039 chli = headers.lines().begin();
1040 EXPECT_THAT(chli->first, StrEq("key3"));
1041 EXPECT_THAT(chli->second, StrEq("value3"));
1042 EXPECT_NE(headers.lines().end(), chli);
1043 EXPECT_EQ(headers.lines().begin(), chli);
1044
1045 ++chli;
1046 EXPECT_EQ(headers.lines().end(), chli);
1047 EXPECT_NE(headers.lines().begin(), chli);
1048 }
1049
TEST(BalsaHeaders,CanCompareIterators)1050 TEST(BalsaHeaders, CanCompareIterators) {
1051 BalsaHeaders header;
1052 ASSERT_EQ(header.lines().begin(), header.lines().end());
1053 {
1054 std::string key_1 = "key_1";
1055 std::string value_1 = "value_1";
1056 header.AppendHeader(key_1, value_1);
1057 key_1 = "garbage";
1058 value_1 = "garbage";
1059 }
1060 {
1061 std::string key_2 = "key_2";
1062 std::string value_2 = "value_2";
1063 header.AppendHeader(key_2, value_2);
1064 key_2 = "garbage";
1065 value_2 = "garbage";
1066 }
1067 BalsaHeaders::const_header_lines_iterator chli = header.lines().begin();
1068 BalsaHeaders::const_header_lines_iterator chlj = header.lines().begin();
1069 EXPECT_EQ(chli, chlj);
1070 ++chlj;
1071 EXPECT_NE(chli, chlj);
1072 EXPECT_LT(chli, chlj);
1073 EXPECT_LE(chli, chlj);
1074 EXPECT_LE(chli, chli);
1075 EXPECT_GT(chlj, chli);
1076 EXPECT_GE(chlj, chli);
1077 EXPECT_GE(chlj, chlj);
1078 }
1079
TEST(BalsaHeaders,AppendHeaderAndTestThatYouCanEraseEverything)1080 TEST(BalsaHeaders, AppendHeaderAndTestThatYouCanEraseEverything) {
1081 BalsaHeaders header;
1082 ASSERT_EQ(header.lines().begin(), header.lines().end());
1083 {
1084 std::string key_1 = "key_1";
1085 std::string value_1 = "value_1";
1086 header.AppendHeader(key_1, value_1);
1087 key_1 = "garbage";
1088 value_1 = "garbage";
1089 }
1090 {
1091 std::string key_2 = "key_2";
1092 std::string value_2 = "value_2";
1093 header.AppendHeader(key_2, value_2);
1094 key_2 = "garbage";
1095 value_2 = "garbage";
1096 }
1097 {
1098 std::string key_3 = "key_3";
1099 std::string value_3 = "value_3";
1100 header.AppendHeader(key_3, value_3);
1101 key_3 = "garbage";
1102 value_3 = "garbage";
1103 }
1104 EXPECT_NE(header.lines().begin(), header.lines().end());
1105 BalsaHeaders::const_header_lines_iterator chli = header.lines().begin();
1106 while (chli != header.lines().end()) {
1107 header.erase(chli);
1108 chli = header.lines().begin();
1109 }
1110 ASSERT_EQ(header.lines().begin(), header.lines().end());
1111 }
1112
TEST(BalsaHeaders,GetHeaderPositionWorksAsExpectedWithNoHeaderLines)1113 TEST(BalsaHeaders, GetHeaderPositionWorksAsExpectedWithNoHeaderLines) {
1114 BalsaHeaders header;
1115 BalsaHeaders::const_header_lines_iterator i = header.GetHeaderPosition("foo");
1116 EXPECT_EQ(i, header.lines().end());
1117 }
1118
TEST(BalsaHeaders,GetHeaderPositionWorksAsExpectedWithBalsaFrameProcessInput)1119 TEST(BalsaHeaders, GetHeaderPositionWorksAsExpectedWithBalsaFrameProcessInput) {
1120 BalsaHeaders headers = CreateHTTPHeaders(
1121 true,
1122 "GET / HTTP/1.0\r\n"
1123 "key1: value_1\r\n"
1124 "key1: value_foo\r\n" // this one cannot be fetched via GetHeader
1125 "key2: value_2\r\n"
1126 "key3: value_3\r\n"
1127 "a: value_a\r\n"
1128 "b: value_b\r\n"
1129 "\r\n");
1130
1131 BalsaHeaders::const_header_lines_iterator header_position_b =
1132 headers.GetHeaderPosition("b");
1133 ASSERT_NE(header_position_b, headers.lines().end());
1134 absl::string_view header_key_b_value = header_position_b->second;
1135 ASSERT_FALSE(header_key_b_value.empty());
1136 EXPECT_EQ(std::string("value_b"), header_key_b_value);
1137
1138 BalsaHeaders::const_header_lines_iterator header_position_1 =
1139 headers.GetHeaderPosition("key1");
1140 ASSERT_NE(header_position_1, headers.lines().end());
1141 absl::string_view header_key_1_value = header_position_1->second;
1142 ASSERT_FALSE(header_key_1_value.empty());
1143 EXPECT_EQ(std::string("value_1"), header_key_1_value);
1144
1145 BalsaHeaders::const_header_lines_iterator header_position_3 =
1146 headers.GetHeaderPosition("key3");
1147 ASSERT_NE(header_position_3, headers.lines().end());
1148 absl::string_view header_key_3_value = header_position_3->second;
1149 ASSERT_FALSE(header_key_3_value.empty());
1150 EXPECT_EQ(std::string("value_3"), header_key_3_value);
1151
1152 BalsaHeaders::const_header_lines_iterator header_position_2 =
1153 headers.GetHeaderPosition("key2");
1154 ASSERT_NE(header_position_2, headers.lines().end());
1155 absl::string_view header_key_2_value = header_position_2->second;
1156 ASSERT_FALSE(header_key_2_value.empty());
1157 EXPECT_EQ(std::string("value_2"), header_key_2_value);
1158
1159 BalsaHeaders::const_header_lines_iterator header_position_a =
1160 headers.GetHeaderPosition("a");
1161 ASSERT_NE(header_position_a, headers.lines().end());
1162 absl::string_view header_key_a_value = header_position_a->second;
1163 ASSERT_FALSE(header_key_a_value.empty());
1164 EXPECT_EQ(std::string("value_a"), header_key_a_value);
1165 }
1166
TEST(BalsaHeaders,GetHeaderWorksAsExpectedWithNoHeaderLines)1167 TEST(BalsaHeaders, GetHeaderWorksAsExpectedWithNoHeaderLines) {
1168 BalsaHeaders header;
1169 absl::string_view value = header.GetHeader("foo");
1170 EXPECT_TRUE(value.empty());
1171 value = header.GetHeader("");
1172 EXPECT_TRUE(value.empty());
1173 }
1174
TEST(BalsaHeaders,HasHeaderWorksAsExpectedWithNoHeaderLines)1175 TEST(BalsaHeaders, HasHeaderWorksAsExpectedWithNoHeaderLines) {
1176 BalsaHeaders header;
1177 EXPECT_FALSE(header.HasHeader("foo"));
1178 EXPECT_FALSE(header.HasHeader(""));
1179 EXPECT_FALSE(header.HasHeadersWithPrefix("foo"));
1180 EXPECT_FALSE(header.HasHeadersWithPrefix(""));
1181 }
1182
TEST(BalsaHeaders,HasHeaderWorksAsExpectedWithBalsaFrameProcessInput)1183 TEST(BalsaHeaders, HasHeaderWorksAsExpectedWithBalsaFrameProcessInput) {
1184 BalsaHeaders headers = CreateHTTPHeaders(true,
1185 "GET / HTTP/1.0\r\n"
1186 "key1: value_1\r\n"
1187 "key1: value_foo\r\n"
1188 "key2:\r\n"
1189 "\r\n");
1190
1191 EXPECT_FALSE(headers.HasHeader("foo"));
1192 EXPECT_TRUE(headers.HasHeader("key1"));
1193 EXPECT_TRUE(headers.HasHeader("key2"));
1194 EXPECT_FALSE(headers.HasHeadersWithPrefix("foo"));
1195 EXPECT_TRUE(headers.HasHeadersWithPrefix("key"));
1196 EXPECT_TRUE(headers.HasHeadersWithPrefix("KEY"));
1197 }
1198
TEST(BalsaHeaders,GetHeaderWorksAsExpectedWithBalsaFrameProcessInput)1199 TEST(BalsaHeaders, GetHeaderWorksAsExpectedWithBalsaFrameProcessInput) {
1200 BalsaHeaders headers = CreateHTTPHeaders(
1201 true,
1202 "GET / HTTP/1.0\r\n"
1203 "key1: value_1\r\n"
1204 "key1: value_foo\r\n" // this one cannot be fetched via GetHeader
1205 "key2: value_2\r\n"
1206 "key3: value_3\r\n"
1207 "key4:\r\n"
1208 "a: value_a\r\n"
1209 "b: value_b\r\n"
1210 "\r\n");
1211
1212 absl::string_view header_key_b_value = headers.GetHeader("b");
1213 ASSERT_FALSE(header_key_b_value.empty());
1214 EXPECT_EQ(std::string("value_b"), header_key_b_value);
1215
1216 absl::string_view header_key_1_value = headers.GetHeader("key1");
1217 ASSERT_FALSE(header_key_1_value.empty());
1218 EXPECT_EQ(std::string("value_1"), header_key_1_value);
1219
1220 absl::string_view header_key_3_value = headers.GetHeader("key3");
1221 ASSERT_FALSE(header_key_3_value.empty());
1222 EXPECT_EQ(std::string("value_3"), header_key_3_value);
1223
1224 absl::string_view header_key_2_value = headers.GetHeader("key2");
1225 ASSERT_FALSE(header_key_2_value.empty());
1226 EXPECT_EQ(std::string("value_2"), header_key_2_value);
1227
1228 absl::string_view header_key_a_value = headers.GetHeader("a");
1229 ASSERT_FALSE(header_key_a_value.empty());
1230 EXPECT_EQ(std::string("value_a"), header_key_a_value);
1231
1232 EXPECT_TRUE(headers.GetHeader("key4").empty());
1233 }
1234
TEST(BalsaHeaders,GetHeaderWorksAsExpectedWithAppendHeader)1235 TEST(BalsaHeaders, GetHeaderWorksAsExpectedWithAppendHeader) {
1236 BalsaHeaders header;
1237
1238 header.AppendHeader("key1", "value_1");
1239 // note that this (following) one cannot be found using GetHeader.
1240 header.AppendHeader("key1", "value_2");
1241 header.AppendHeader("key2", "value_2");
1242 header.AppendHeader("key3", "value_3");
1243 header.AppendHeader("a", "value_a");
1244 header.AppendHeader("b", "value_b");
1245
1246 absl::string_view header_key_b_value = header.GetHeader("b");
1247 absl::string_view header_key_1_value = header.GetHeader("key1");
1248 absl::string_view header_key_3_value = header.GetHeader("key3");
1249 absl::string_view header_key_2_value = header.GetHeader("key2");
1250 absl::string_view header_key_a_value = header.GetHeader("a");
1251
1252 ASSERT_FALSE(header_key_1_value.empty());
1253 ASSERT_FALSE(header_key_2_value.empty());
1254 ASSERT_FALSE(header_key_3_value.empty());
1255 ASSERT_FALSE(header_key_a_value.empty());
1256 ASSERT_FALSE(header_key_b_value.empty());
1257
1258 EXPECT_TRUE(header.HasHeader("key1"));
1259 EXPECT_TRUE(header.HasHeader("key2"));
1260 EXPECT_TRUE(header.HasHeader("key3"));
1261 EXPECT_TRUE(header.HasHeader("a"));
1262 EXPECT_TRUE(header.HasHeader("b"));
1263
1264 EXPECT_TRUE(header.HasHeadersWithPrefix("key1"));
1265 EXPECT_TRUE(header.HasHeadersWithPrefix("key2"));
1266 EXPECT_TRUE(header.HasHeadersWithPrefix("key3"));
1267 EXPECT_TRUE(header.HasHeadersWithPrefix("a"));
1268 EXPECT_TRUE(header.HasHeadersWithPrefix("b"));
1269
1270 EXPECT_EQ(std::string("value_1"), header_key_1_value);
1271 EXPECT_EQ(std::string("value_2"), header_key_2_value);
1272 EXPECT_EQ(std::string("value_3"), header_key_3_value);
1273 EXPECT_EQ(std::string("value_a"), header_key_a_value);
1274 EXPECT_EQ(std::string("value_b"), header_key_b_value);
1275 }
1276
TEST(BalsaHeaders,HasHeaderWorksAsExpectedWithAppendHeader)1277 TEST(BalsaHeaders, HasHeaderWorksAsExpectedWithAppendHeader) {
1278 BalsaHeaders header;
1279
1280 ASSERT_FALSE(header.HasHeader("key1"));
1281 EXPECT_FALSE(header.HasHeadersWithPrefix("K"));
1282 EXPECT_FALSE(header.HasHeadersWithPrefix("ke"));
1283 EXPECT_FALSE(header.HasHeadersWithPrefix("key"));
1284 EXPECT_FALSE(header.HasHeadersWithPrefix("key1"));
1285 EXPECT_FALSE(header.HasHeadersWithPrefix("key2"));
1286 header.AppendHeader("key1", "value_1");
1287 EXPECT_TRUE(header.HasHeader("key1"));
1288 EXPECT_TRUE(header.HasHeadersWithPrefix("K"));
1289 EXPECT_TRUE(header.HasHeadersWithPrefix("ke"));
1290 EXPECT_TRUE(header.HasHeadersWithPrefix("key"));
1291 EXPECT_TRUE(header.HasHeadersWithPrefix("key1"));
1292 EXPECT_FALSE(header.HasHeadersWithPrefix("key2"));
1293
1294 header.AppendHeader("key1", "value_2");
1295 EXPECT_TRUE(header.HasHeader("key1"));
1296 EXPECT_FALSE(header.HasHeader("key2"));
1297 EXPECT_TRUE(header.HasHeadersWithPrefix("k"));
1298 EXPECT_TRUE(header.HasHeadersWithPrefix("ke"));
1299 EXPECT_TRUE(header.HasHeadersWithPrefix("key"));
1300 EXPECT_TRUE(header.HasHeadersWithPrefix("key1"));
1301 EXPECT_FALSE(header.HasHeadersWithPrefix("key2"));
1302 }
1303
TEST(BalsaHeaders,GetHeaderWorksAsExpectedWithHeadersErased)1304 TEST(BalsaHeaders, GetHeaderWorksAsExpectedWithHeadersErased) {
1305 BalsaHeaders header;
1306 header.AppendHeader("key1", "value_1");
1307 header.AppendHeader("key1", "value_2");
1308 header.AppendHeader("key2", "value_2");
1309 header.AppendHeader("key3", "value_3");
1310 header.AppendHeader("a", "value_a");
1311 header.AppendHeader("b", "value_b");
1312
1313 header.erase(header.GetHeaderPosition("key2"));
1314
1315 absl::string_view header_key_b_value = header.GetHeader("b");
1316 absl::string_view header_key_1_value = header.GetHeader("key1");
1317 absl::string_view header_key_3_value = header.GetHeader("key3");
1318 absl::string_view header_key_2_value = header.GetHeader("key2");
1319 absl::string_view header_key_a_value = header.GetHeader("a");
1320
1321 ASSERT_FALSE(header_key_1_value.empty());
1322 ASSERT_TRUE(header_key_2_value.empty());
1323 ASSERT_FALSE(header_key_3_value.empty());
1324 ASSERT_FALSE(header_key_a_value.empty());
1325 ASSERT_FALSE(header_key_b_value.empty());
1326
1327 EXPECT_EQ(std::string("value_1"), header_key_1_value);
1328 EXPECT_EQ(std::string("value_3"), header_key_3_value);
1329 EXPECT_EQ(std::string("value_a"), header_key_a_value);
1330 EXPECT_EQ(std::string("value_b"), header_key_b_value);
1331
1332 // Erasing one makes the next one visible:
1333 header.erase(header.GetHeaderPosition("key1"));
1334 header_key_1_value = header.GetHeader("key1");
1335 ASSERT_FALSE(header_key_1_value.empty());
1336 EXPECT_EQ(std::string("value_2"), header_key_1_value);
1337
1338 // Erase both:
1339 header.erase(header.GetHeaderPosition("key1"));
1340 ASSERT_TRUE(header.GetHeader("key1").empty());
1341 }
1342
TEST(BalsaHeaders,HasHeaderWorksAsExpectedWithHeadersErased)1343 TEST(BalsaHeaders, HasHeaderWorksAsExpectedWithHeadersErased) {
1344 BalsaHeaders header;
1345 header.AppendHeader("key1", "value_1");
1346 header.AppendHeader("key2", "value_2a");
1347 header.AppendHeader("key2", "value_2b");
1348
1349 ASSERT_TRUE(header.HasHeader("key1"));
1350 ASSERT_TRUE(header.HasHeadersWithPrefix("key1"));
1351 ASSERT_TRUE(header.HasHeadersWithPrefix("key2"));
1352 ASSERT_TRUE(header.HasHeadersWithPrefix("kEY"));
1353 header.erase(header.GetHeaderPosition("key1"));
1354 EXPECT_FALSE(header.HasHeader("key1"));
1355 EXPECT_FALSE(header.HasHeadersWithPrefix("key1"));
1356 EXPECT_TRUE(header.HasHeadersWithPrefix("key2"));
1357 EXPECT_TRUE(header.HasHeadersWithPrefix("kEY"));
1358
1359 ASSERT_TRUE(header.HasHeader("key2"));
1360 header.erase(header.GetHeaderPosition("key2"));
1361 ASSERT_TRUE(header.HasHeader("key2"));
1362 EXPECT_FALSE(header.HasHeadersWithPrefix("key1"));
1363 EXPECT_TRUE(header.HasHeadersWithPrefix("key2"));
1364 EXPECT_TRUE(header.HasHeadersWithPrefix("kEY"));
1365 header.erase(header.GetHeaderPosition("key2"));
1366 EXPECT_FALSE(header.HasHeader("key2"));
1367 EXPECT_FALSE(header.HasHeadersWithPrefix("key1"));
1368 EXPECT_FALSE(header.HasHeadersWithPrefix("key2"));
1369 EXPECT_FALSE(header.HasHeadersWithPrefix("kEY"));
1370 }
1371
TEST(BalsaHeaders,HasNonEmptyHeaderWorksAsExpectedWithNoHeaderLines)1372 TEST(BalsaHeaders, HasNonEmptyHeaderWorksAsExpectedWithNoHeaderLines) {
1373 BalsaHeaders header;
1374 EXPECT_FALSE(header.HasNonEmptyHeader("foo"));
1375 EXPECT_FALSE(header.HasNonEmptyHeader(""));
1376 }
1377
TEST(BalsaHeaders,HasNonEmptyHeaderWorksAsExpectedWithAppendHeader)1378 TEST(BalsaHeaders, HasNonEmptyHeaderWorksAsExpectedWithAppendHeader) {
1379 BalsaHeaders header;
1380
1381 EXPECT_FALSE(header.HasNonEmptyHeader("key1"));
1382 header.AppendHeader("key1", "");
1383 EXPECT_FALSE(header.HasNonEmptyHeader("key1"));
1384
1385 header.AppendHeader("key1", "value_2");
1386 EXPECT_TRUE(header.HasNonEmptyHeader("key1"));
1387 EXPECT_FALSE(header.HasNonEmptyHeader("key2"));
1388 }
1389
TEST(BalsaHeaders,HasNonEmptyHeaderWorksAsExpectedWithHeadersErased)1390 TEST(BalsaHeaders, HasNonEmptyHeaderWorksAsExpectedWithHeadersErased) {
1391 BalsaHeaders header;
1392 header.AppendHeader("key1", "value_1");
1393 header.AppendHeader("key2", "value_2a");
1394 header.AppendHeader("key2", "");
1395
1396 EXPECT_TRUE(header.HasNonEmptyHeader("key1"));
1397 header.erase(header.GetHeaderPosition("key1"));
1398 EXPECT_FALSE(header.HasNonEmptyHeader("key1"));
1399
1400 EXPECT_TRUE(header.HasNonEmptyHeader("key2"));
1401 header.erase(header.GetHeaderPosition("key2"));
1402 EXPECT_FALSE(header.HasNonEmptyHeader("key2"));
1403 header.erase(header.GetHeaderPosition("key2"));
1404 EXPECT_FALSE(header.HasNonEmptyHeader("key2"));
1405 }
1406
TEST(BalsaHeaders,HasNonEmptyHeaderWorksAsExpectedWithBalsaFrameProcessInput)1407 TEST(BalsaHeaders, HasNonEmptyHeaderWorksAsExpectedWithBalsaFrameProcessInput) {
1408 BalsaHeaders headers = CreateHTTPHeaders(true,
1409 "GET / HTTP/1.0\r\n"
1410 "key1: value_1\r\n"
1411 "key2:\r\n"
1412 "key3:\r\n"
1413 "key3: value_3\r\n"
1414 "key4:\r\n"
1415 "key4:\r\n"
1416 "key5: value_5\r\n"
1417 "key5:\r\n"
1418 "\r\n");
1419
1420 EXPECT_FALSE(headers.HasNonEmptyHeader("foo"));
1421 EXPECT_TRUE(headers.HasNonEmptyHeader("key1"));
1422 EXPECT_FALSE(headers.HasNonEmptyHeader("key2"));
1423 EXPECT_TRUE(headers.HasNonEmptyHeader("key3"));
1424 EXPECT_FALSE(headers.HasNonEmptyHeader("key4"));
1425 EXPECT_TRUE(headers.HasNonEmptyHeader("key5"));
1426
1427 headers.erase(headers.GetHeaderPosition("key5"));
1428 EXPECT_FALSE(headers.HasNonEmptyHeader("key5"));
1429 }
1430
TEST(BalsaHeaders,GetAllOfHeader)1431 TEST(BalsaHeaders, GetAllOfHeader) {
1432 BalsaHeaders header;
1433 header.AppendHeader("key", "value_1");
1434 header.AppendHeader("Key", "value_2,value_3");
1435 header.AppendHeader("key", "");
1436 header.AppendHeader("KEY", "value_4");
1437
1438 std::vector<absl::string_view> result;
1439 header.GetAllOfHeader("key", &result);
1440 ASSERT_EQ(4u, result.size());
1441 EXPECT_EQ("value_1", result[0]);
1442 EXPECT_EQ("value_2,value_3", result[1]);
1443 EXPECT_EQ("", result[2]);
1444 EXPECT_EQ("value_4", result[3]);
1445
1446 EXPECT_EQ(header.GetAllOfHeader("key"), result);
1447 }
1448
TEST(BalsaHeaders,GetAllOfHeaderDoesWhatItSays)1449 TEST(BalsaHeaders, GetAllOfHeaderDoesWhatItSays) {
1450 BalsaHeaders header;
1451 // Multiple values for a given header.
1452 // Some values appear multiple times
1453 header.AppendHeader("key", "value_1");
1454 header.AppendHeader("key", "value_2");
1455 header.AppendHeader("key", "");
1456 header.AppendHeader("key", "value_1");
1457
1458 ASSERT_NE(header.lines().begin(), header.lines().end());
1459 std::vector<absl::string_view> out;
1460
1461 header.GetAllOfHeader("key", &out);
1462 ASSERT_EQ(4u, out.size());
1463 EXPECT_EQ("value_1", out[0]);
1464 EXPECT_EQ("value_2", out[1]);
1465 EXPECT_EQ("", out[2]);
1466 EXPECT_EQ("value_1", out[3]);
1467
1468 EXPECT_EQ(header.GetAllOfHeader("key"), out);
1469 }
1470
TEST(BalsaHeaders,GetAllOfHeaderWithPrefix)1471 TEST(BalsaHeaders, GetAllOfHeaderWithPrefix) {
1472 BalsaHeaders header;
1473 header.AppendHeader("foo-Foo", "value_1");
1474 header.AppendHeader("Foo-bar", "value_2,value_3");
1475 header.AppendHeader("foo-Foo", "");
1476 header.AppendHeader("bar", "value_not");
1477 header.AppendHeader("fOO-fOO", "value_4");
1478
1479 std::vector<std::pair<absl::string_view, absl::string_view>> result;
1480 header.GetAllOfHeaderWithPrefix("abc", &result);
1481 ASSERT_EQ(0u, result.size());
1482
1483 header.GetAllOfHeaderWithPrefix("foo", &result);
1484 ASSERT_EQ(4u, result.size());
1485 EXPECT_EQ("foo-Foo", result[0].first);
1486 EXPECT_EQ("value_1", result[0].second);
1487 EXPECT_EQ("Foo-bar", result[1].first);
1488 EXPECT_EQ("value_2,value_3", result[1].second);
1489 EXPECT_EQ("", result[2].second);
1490 EXPECT_EQ("value_4", result[3].second);
1491
1492 std::vector<std::pair<absl::string_view, absl::string_view>> result2;
1493 header.GetAllOfHeaderWithPrefix("FoO", &result2);
1494 ASSERT_EQ(4u, result2.size());
1495 }
1496
TEST(BalsaHeaders,GetAllHeadersWithLimit)1497 TEST(BalsaHeaders, GetAllHeadersWithLimit) {
1498 BalsaHeaders header;
1499 header.AppendHeader("foo-Foo", "value_1");
1500 header.AppendHeader("Foo-bar", "value_2,value_3");
1501 header.AppendHeader("foo-Foo", "");
1502 header.AppendHeader("bar", "value_4");
1503 header.AppendHeader("fOO-fOO", "value_5");
1504
1505 std::vector<std::pair<absl::string_view, absl::string_view>> result;
1506 header.GetAllHeadersWithLimit(&result, 4);
1507 ASSERT_EQ(4u, result.size());
1508 EXPECT_EQ("foo-Foo", result[0].first);
1509 EXPECT_EQ("value_1", result[0].second);
1510 EXPECT_EQ("Foo-bar", result[1].first);
1511 EXPECT_EQ("value_2,value_3", result[1].second);
1512 EXPECT_EQ("", result[2].second);
1513 EXPECT_EQ("value_4", result[3].second);
1514
1515 std::vector<std::pair<absl::string_view, absl::string_view>> result2;
1516 header.GetAllHeadersWithLimit(&result2, -1);
1517 ASSERT_EQ(5u, result2.size());
1518 }
1519
TEST(BalsaHeaders,RangeFor)1520 TEST(BalsaHeaders, RangeFor) {
1521 BalsaHeaders header;
1522 // Multiple values for a given header.
1523 // Some values appear multiple times
1524 header.AppendHeader("key1", "value_1a");
1525 header.AppendHeader("key1", "value_1b");
1526 header.AppendHeader("key2", "");
1527 header.AppendHeader("key3", "value_3");
1528
1529 std::vector<std::pair<absl::string_view, absl::string_view>> out;
1530 for (const auto& line : header.lines()) {
1531 out.push_back(line);
1532 }
1533 const std::vector<std::pair<absl::string_view, absl::string_view>> expected =
1534 {{"key1", "value_1a"},
1535 {"key1", "value_1b"},
1536 {"key2", ""},
1537 {"key3", "value_3"}};
1538 EXPECT_EQ(expected, out);
1539 }
1540
TEST(BalsaHeaders,GetAllOfHeaderWithNonExistentKey)1541 TEST(BalsaHeaders, GetAllOfHeaderWithNonExistentKey) {
1542 BalsaHeaders header;
1543 header.AppendHeader("key", "value_1");
1544 header.AppendHeader("key", "value_2");
1545 std::vector<absl::string_view> out;
1546
1547 header.GetAllOfHeader("key_non_existent", &out);
1548 ASSERT_EQ(0u, out.size());
1549
1550 EXPECT_EQ(header.GetAllOfHeader("key_non_existent"), out);
1551 }
1552
TEST(BalsaHeaders,GetAllOfHeaderEmptyValVariation1)1553 TEST(BalsaHeaders, GetAllOfHeaderEmptyValVariation1) {
1554 BalsaHeaders header;
1555 header.AppendHeader("key", "");
1556 header.AppendHeader("key", "");
1557 header.AppendHeader("key", "v1");
1558 std::vector<absl::string_view> out;
1559 header.GetAllOfHeader("key", &out);
1560 ASSERT_EQ(3u, out.size());
1561 EXPECT_EQ("", out[0]);
1562 EXPECT_EQ("", out[1]);
1563 EXPECT_EQ("v1", out[2]);
1564
1565 EXPECT_EQ(header.GetAllOfHeader("key"), out);
1566 }
1567
TEST(BalsaHeaders,GetAllOfHeaderEmptyValVariation2)1568 TEST(BalsaHeaders, GetAllOfHeaderEmptyValVariation2) {
1569 BalsaHeaders header;
1570 header.AppendHeader("key", "");
1571 header.AppendHeader("key", "v1");
1572 header.AppendHeader("key", "");
1573 std::vector<absl::string_view> out;
1574 header.GetAllOfHeader("key", &out);
1575 ASSERT_EQ(3u, out.size());
1576 EXPECT_EQ("", out[0]);
1577 EXPECT_EQ("v1", out[1]);
1578 EXPECT_EQ("", out[2]);
1579
1580 EXPECT_EQ(header.GetAllOfHeader("key"), out);
1581 }
1582
TEST(BalsaHeaders,GetAllOfHeaderEmptyValVariation3)1583 TEST(BalsaHeaders, GetAllOfHeaderEmptyValVariation3) {
1584 BalsaHeaders header;
1585 header.AppendHeader("key", "");
1586 header.AppendHeader("key", "v1");
1587 std::vector<absl::string_view> out;
1588 header.GetAllOfHeader("key", &out);
1589 ASSERT_EQ(2u, out.size());
1590 EXPECT_EQ("", out[0]);
1591 EXPECT_EQ("v1", out[1]);
1592
1593 EXPECT_EQ(header.GetAllOfHeader("key"), out);
1594 }
1595
TEST(BalsaHeaders,GetAllOfHeaderEmptyValVariation4)1596 TEST(BalsaHeaders, GetAllOfHeaderEmptyValVariation4) {
1597 BalsaHeaders header;
1598 header.AppendHeader("key", "v1");
1599 header.AppendHeader("key", "");
1600 std::vector<absl::string_view> out;
1601 header.GetAllOfHeader("key", &out);
1602 ASSERT_EQ(2u, out.size());
1603 EXPECT_EQ("v1", out[0]);
1604 EXPECT_EQ("", out[1]);
1605
1606 EXPECT_EQ(header.GetAllOfHeader("key"), out);
1607 }
1608
TEST(BalsaHeaders,GetAllOfHeaderWithAppendHeaders)1609 TEST(BalsaHeaders, GetAllOfHeaderWithAppendHeaders) {
1610 BalsaHeaders header;
1611 header.AppendHeader("key", "value_1");
1612 header.AppendHeader("key", "value_2");
1613 std::vector<absl::string_view> out;
1614
1615 header.GetAllOfHeader("key_new", &out);
1616 ASSERT_EQ(0u, out.size());
1617 EXPECT_EQ(header.GetAllOfHeader("key_new"), out);
1618
1619 // Add key_new to the header
1620 header.AppendHeader("key_new", "value_3");
1621 header.GetAllOfHeader("key_new", &out);
1622 ASSERT_EQ(1u, out.size());
1623 EXPECT_EQ("value_3", out[0]);
1624 EXPECT_EQ(header.GetAllOfHeader("key_new"), out);
1625
1626 // Get the keys that are not modified
1627 header.GetAllOfHeader("key", &out);
1628 ASSERT_EQ(3u, out.size());
1629 EXPECT_EQ("value_1", out[1]);
1630 EXPECT_EQ("value_2", out[2]);
1631 EXPECT_THAT(header.GetAllOfHeader("key"), ElementsAre("value_1", "value_2"));
1632 }
1633
TEST(BalsaHeaders,GetAllOfHeaderWithRemoveHeaders)1634 TEST(BalsaHeaders, GetAllOfHeaderWithRemoveHeaders) {
1635 BalsaHeaders header;
1636 header.AppendHeader("key", "value_1");
1637 header.AppendHeader("key", "value_2");
1638 header.AppendHeader("a", "va");
1639
1640 header.RemoveAllOfHeader("key");
1641 std::vector<absl::string_view> out;
1642 header.GetAllOfHeader("key", &out);
1643 ASSERT_EQ(0u, out.size());
1644 EXPECT_EQ(header.GetAllOfHeader("key"), out);
1645
1646 header.GetAllOfHeader("a", &out);
1647 ASSERT_EQ(1u, out.size());
1648 EXPECT_EQ(header.GetAllOfHeader("a"), out);
1649
1650 out.clear();
1651 header.RemoveAllOfHeader("a");
1652 header.GetAllOfHeader("a", &out);
1653 ASSERT_EQ(0u, out.size());
1654 EXPECT_EQ(header.GetAllOfHeader("a"), out);
1655 }
1656
TEST(BalsaHeaders,GetAllOfHeaderWithRemoveNonExistentHeaders)1657 TEST(BalsaHeaders, GetAllOfHeaderWithRemoveNonExistentHeaders) {
1658 BalsaHeaders headers;
1659 headers.SetRequestFirstlineFromStringPieces("GET", "/", "HTTP/1.0");
1660 headers.AppendHeader("Accept-Encoding", "deflate,compress");
1661 EXPECT_EQ(0u, headers.RemoveValue("Accept-Encoding", "gzip(gfe)"));
1662 std::string accept_encoding_vals =
1663 headers.GetAllOfHeaderAsString("Accept-Encoding");
1664 EXPECT_EQ("deflate,compress", accept_encoding_vals);
1665 }
1666
TEST(BalsaHeaders,GetAllOfHeaderWithEraseHeaders)1667 TEST(BalsaHeaders, GetAllOfHeaderWithEraseHeaders) {
1668 BalsaHeaders header;
1669 header.AppendHeader("key", "value_1");
1670 header.AppendHeader("key", "value_2");
1671 header.AppendHeader("a", "va");
1672
1673 std::vector<absl::string_view> out;
1674
1675 header.erase(header.GetHeaderPosition("key"));
1676 header.GetAllOfHeader("key", &out);
1677 ASSERT_EQ(1u, out.size());
1678 EXPECT_EQ("value_2", out[0]);
1679 EXPECT_EQ(header.GetAllOfHeader("key"), out);
1680
1681 out.clear();
1682 header.erase(header.GetHeaderPosition("key"));
1683 header.GetAllOfHeader("key", &out);
1684 ASSERT_EQ(0u, out.size());
1685 EXPECT_EQ(header.GetAllOfHeader("key"), out);
1686
1687 out.clear();
1688 header.GetAllOfHeader("a", &out);
1689 ASSERT_EQ(1u, out.size());
1690 EXPECT_EQ(header.GetAllOfHeader("a"), out);
1691
1692 out.clear();
1693 header.erase(header.GetHeaderPosition("a"));
1694 header.GetAllOfHeader("a", &out);
1695 ASSERT_EQ(0u, out.size());
1696 EXPECT_EQ(header.GetAllOfHeader("key"), out);
1697 }
1698
TEST(BalsaHeaders,GetAllOfHeaderWithNoHeaderLines)1699 TEST(BalsaHeaders, GetAllOfHeaderWithNoHeaderLines) {
1700 BalsaHeaders header;
1701 std::vector<absl::string_view> out;
1702 header.GetAllOfHeader("key", &out);
1703 EXPECT_EQ(0u, out.size());
1704 EXPECT_EQ(header.GetAllOfHeader("key"), out);
1705 }
1706
TEST(BalsaHeaders,GetAllOfHeaderDoesWhatItSaysForVariousKeys)1707 TEST(BalsaHeaders, GetAllOfHeaderDoesWhatItSaysForVariousKeys) {
1708 BalsaHeaders header;
1709 header.AppendHeader("key1", "value_11");
1710 header.AppendHeader("key2", "value_21");
1711 header.AppendHeader("key1", "value_12");
1712 header.AppendHeader("key2", "value_22");
1713
1714 std::vector<absl::string_view> out;
1715
1716 header.GetAllOfHeader("key1", &out);
1717 EXPECT_EQ("value_11", out[0]);
1718 EXPECT_EQ("value_12", out[1]);
1719 EXPECT_EQ(header.GetAllOfHeader("key1"), out);
1720
1721 header.GetAllOfHeader("key2", &out);
1722 EXPECT_EQ("value_21", out[2]);
1723 EXPECT_EQ("value_22", out[3]);
1724 EXPECT_THAT(header.GetAllOfHeader("key2"),
1725 ElementsAre("value_21", "value_22"));
1726 }
1727
TEST(BalsaHeaders,GetAllOfHeaderWithBalsaFrameProcessInput)1728 TEST(BalsaHeaders, GetAllOfHeaderWithBalsaFrameProcessInput) {
1729 BalsaHeaders header = CreateHTTPHeaders(true,
1730 "GET / HTTP/1.0\r\n"
1731 "key1: value_1\r\n"
1732 "key1: value_foo\r\n"
1733 "key2: value_2\r\n"
1734 "a: value_a\r\n"
1735 "key2: \r\n"
1736 "b: value_b\r\n"
1737 "\r\n");
1738
1739 std::vector<absl::string_view> out;
1740 int index = 0;
1741 header.GetAllOfHeader("key1", &out);
1742 EXPECT_EQ("value_1", out[index++]);
1743 EXPECT_EQ("value_foo", out[index++]);
1744 EXPECT_EQ(header.GetAllOfHeader("key1"), out);
1745
1746 header.GetAllOfHeader("key2", &out);
1747 EXPECT_EQ("value_2", out[index++]);
1748 EXPECT_EQ("", out[index++]);
1749 EXPECT_THAT(header.GetAllOfHeader("key2"), ElementsAre("value_2", ""));
1750
1751 header.GetAllOfHeader("a", &out);
1752 EXPECT_EQ("value_a", out[index++]);
1753 EXPECT_THAT(header.GetAllOfHeader("a"), ElementsAre("value_a"));
1754
1755 header.GetAllOfHeader("b", &out);
1756 EXPECT_EQ("value_b", out[index++]);
1757 EXPECT_THAT(header.GetAllOfHeader("b"), ElementsAre("value_b"));
1758 }
1759
TEST(BalsaHeaders,GetAllOfHeaderIncludeRemovedDoesWhatItSays)1760 TEST(BalsaHeaders, GetAllOfHeaderIncludeRemovedDoesWhatItSays) {
1761 BalsaHeaders header;
1762 header.AppendHeader("key1", "value_11");
1763 header.AppendHeader("key2", "value_21");
1764 header.AppendHeader("key1", "value_12");
1765 header.AppendHeader("key2", "value_22");
1766 header.AppendHeader("key1", "");
1767
1768 std::vector<absl::string_view> out;
1769 header.GetAllOfHeaderIncludeRemoved("key1", &out);
1770 ASSERT_EQ(3u, out.size());
1771 EXPECT_EQ("value_11", out[0]);
1772 EXPECT_EQ("value_12", out[1]);
1773 EXPECT_EQ("", out[2]);
1774 header.GetAllOfHeaderIncludeRemoved("key2", &out);
1775 ASSERT_EQ(5u, out.size());
1776 EXPECT_EQ("value_21", out[3]);
1777 EXPECT_EQ("value_22", out[4]);
1778
1779 header.erase(header.GetHeaderPosition("key1"));
1780 out.clear();
1781 header.GetAllOfHeaderIncludeRemoved("key1", &out);
1782 ASSERT_EQ(3u, out.size());
1783 EXPECT_EQ("value_12", out[0]);
1784 EXPECT_EQ("", out[1]);
1785 EXPECT_EQ("value_11", out[2]);
1786 header.GetAllOfHeaderIncludeRemoved("key2", &out);
1787 ASSERT_EQ(5u, out.size());
1788 EXPECT_EQ("value_21", out[3]);
1789 EXPECT_EQ("value_22", out[4]);
1790
1791 header.RemoveAllOfHeader("key1");
1792 out.clear();
1793 header.GetAllOfHeaderIncludeRemoved("key1", &out);
1794 ASSERT_EQ(3u, out.size());
1795 EXPECT_EQ("value_11", out[0]);
1796 EXPECT_EQ("value_12", out[1]);
1797 EXPECT_EQ("", out[2]);
1798 header.GetAllOfHeaderIncludeRemoved("key2", &out);
1799 ASSERT_EQ(5u, out.size());
1800 EXPECT_EQ("value_21", out[3]);
1801 EXPECT_EQ("value_22", out[4]);
1802
1803 header.Clear();
1804 out.clear();
1805 header.GetAllOfHeaderIncludeRemoved("key1", &out);
1806 ASSERT_EQ(0u, out.size());
1807 header.GetAllOfHeaderIncludeRemoved("key2", &out);
1808 ASSERT_EQ(0u, out.size());
1809 }
1810
TEST(BalsaHeaders,GetAllOfHeaderIncludeRemovedWithNonExistentKey)1811 TEST(BalsaHeaders, GetAllOfHeaderIncludeRemovedWithNonExistentKey) {
1812 BalsaHeaders header;
1813 header.AppendHeader("key", "value_1");
1814 header.AppendHeader("key", "value_2");
1815 std::vector<absl::string_view> out;
1816 header.GetAllOfHeaderIncludeRemoved("key_non_existent", &out);
1817 ASSERT_EQ(0u, out.size());
1818 }
1819
TEST(BalsaHeaders,GetIteratorForKeyDoesWhatItSays)1820 TEST(BalsaHeaders, GetIteratorForKeyDoesWhatItSays) {
1821 BalsaHeaders header;
1822 // Multiple values for a given header.
1823 // Some values appear multiple times
1824 header.AppendHeader("key", "value_1");
1825 header.AppendHeader("Key", "value_2");
1826 header.AppendHeader("key", "");
1827 header.AppendHeader("KEY", "value_1");
1828
1829 BalsaHeaders::const_header_lines_key_iterator key_it =
1830 header.GetIteratorForKey("key");
1831 EXPECT_NE(header.lines().end(), key_it);
1832 EXPECT_NE(header.header_lines_key_end(), key_it);
1833 EXPECT_EQ("key", key_it->first);
1834 EXPECT_EQ("value_1", key_it->second);
1835 ++key_it;
1836 EXPECT_NE(header.lines().end(), key_it);
1837 EXPECT_NE(header.header_lines_key_end(), key_it);
1838 EXPECT_EQ("Key", key_it->first);
1839 EXPECT_EQ("value_2", key_it->second);
1840 ++key_it;
1841 EXPECT_NE(header.lines().end(), key_it);
1842 EXPECT_NE(header.header_lines_key_end(), key_it);
1843 EXPECT_EQ("key", key_it->first);
1844 EXPECT_EQ("", key_it->second);
1845 ++key_it;
1846 EXPECT_NE(header.lines().end(), key_it);
1847 EXPECT_NE(header.header_lines_key_end(), key_it);
1848 EXPECT_EQ("KEY", key_it->first);
1849 EXPECT_EQ("value_1", key_it->second);
1850 ++key_it;
1851 EXPECT_EQ(header.lines().end(), key_it);
1852 EXPECT_EQ(header.header_lines_key_end(), key_it);
1853 }
1854
TEST(BalsaHeaders,GetIteratorForKeyWithNonExistentKey)1855 TEST(BalsaHeaders, GetIteratorForKeyWithNonExistentKey) {
1856 BalsaHeaders header;
1857 header.AppendHeader("key", "value_1");
1858 header.AppendHeader("key", "value_2");
1859
1860 BalsaHeaders::const_header_lines_key_iterator key_it =
1861 header.GetIteratorForKey("key_non_existent");
1862 EXPECT_EQ(header.lines().end(), key_it);
1863 EXPECT_EQ(header.header_lines_key_end(), key_it);
1864 const auto lines = header.lines("key_non_existent");
1865 EXPECT_EQ(lines.begin(), header.lines().end());
1866 EXPECT_EQ(lines.end(), header.header_lines_key_end());
1867 }
1868
TEST(BalsaHeaders,GetIteratorForKeyWithAppendHeaders)1869 TEST(BalsaHeaders, GetIteratorForKeyWithAppendHeaders) {
1870 BalsaHeaders header;
1871 header.AppendHeader("key", "value_1");
1872 header.AppendHeader("key", "value_2");
1873
1874 BalsaHeaders::const_header_lines_key_iterator key_it =
1875 header.GetIteratorForKey("key_new");
1876 EXPECT_EQ(header.lines().end(), key_it);
1877 EXPECT_EQ(header.header_lines_key_end(), key_it);
1878
1879 // Add key_new to the header
1880 header.AppendHeader("key_new", "value_3");
1881 key_it = header.GetIteratorForKey("key_new");
1882 const auto lines1 = header.lines("key_new");
1883 EXPECT_EQ(lines1.begin(), key_it);
1884 EXPECT_EQ(lines1.end(), header.header_lines_key_end());
1885
1886 EXPECT_NE(header.lines().end(), key_it);
1887 EXPECT_NE(header.header_lines_key_end(), key_it);
1888 EXPECT_EQ("key_new", key_it->first);
1889 EXPECT_EQ("value_3", key_it->second);
1890 ++key_it;
1891 EXPECT_EQ(header.lines().end(), key_it);
1892 EXPECT_EQ(header.header_lines_key_end(), key_it);
1893
1894 // Get the keys that are not modified
1895 key_it = header.GetIteratorForKey("key");
1896 const auto lines2 = header.lines("key");
1897 EXPECT_EQ(lines2.begin(), key_it);
1898 EXPECT_EQ(lines2.end(), header.header_lines_key_end());
1899 EXPECT_NE(header.lines().end(), key_it);
1900 EXPECT_NE(header.header_lines_key_end(), key_it);
1901 EXPECT_EQ("key", key_it->first);
1902 EXPECT_EQ("value_1", key_it->second);
1903 ++key_it;
1904 EXPECT_NE(header.lines().end(), key_it);
1905 EXPECT_NE(header.header_lines_key_end(), key_it);
1906 EXPECT_EQ("key", key_it->first);
1907 EXPECT_EQ("value_2", key_it->second);
1908 ++key_it;
1909 EXPECT_EQ(header.lines().end(), key_it);
1910 EXPECT_EQ(header.header_lines_key_end(), key_it);
1911 }
1912
TEST(BalsaHeaders,GetIteratorForKeyWithRemoveHeaders)1913 TEST(BalsaHeaders, GetIteratorForKeyWithRemoveHeaders) {
1914 BalsaHeaders header;
1915 header.AppendHeader("key", "value_1");
1916 header.AppendHeader("key", "value_2");
1917 header.AppendHeader("a", "va");
1918
1919 header.RemoveAllOfHeader("a");
1920 BalsaHeaders::const_header_lines_key_iterator key_it =
1921 header.GetIteratorForKey("key");
1922 EXPECT_NE(header.lines().end(), key_it);
1923 const auto lines1 = header.lines("key");
1924 EXPECT_EQ(lines1.begin(), key_it);
1925 EXPECT_EQ(lines1.end(), header.header_lines_key_end());
1926 EXPECT_EQ("value_1", key_it->second);
1927 ++key_it;
1928 EXPECT_NE(header.lines().end(), key_it);
1929 EXPECT_NE(header.header_lines_key_end(), key_it);
1930 EXPECT_EQ("key", key_it->first);
1931 EXPECT_EQ("value_2", key_it->second);
1932 ++key_it;
1933 EXPECT_EQ(header.lines().end(), key_it);
1934 EXPECT_EQ(header.header_lines_key_end(), key_it);
1935
1936 // Check that a typical loop works properly.
1937 for (BalsaHeaders::const_header_lines_key_iterator it =
1938 header.GetIteratorForKey("key");
1939 it != header.lines().end(); ++it) {
1940 EXPECT_EQ("key", it->first);
1941 }
1942 }
1943
TEST(BalsaHeaders,GetIteratorForKeyWithEraseHeaders)1944 TEST(BalsaHeaders, GetIteratorForKeyWithEraseHeaders) {
1945 BalsaHeaders header;
1946 header.AppendHeader("key", "value_1");
1947 header.AppendHeader("key", "value_2");
1948 header.AppendHeader("a", "va");
1949 header.erase(header.GetHeaderPosition("key"));
1950
1951 BalsaHeaders::const_header_lines_key_iterator key_it =
1952 header.GetIteratorForKey("key");
1953 EXPECT_NE(header.lines().end(), key_it);
1954 const auto lines1 = header.lines("key");
1955 EXPECT_EQ(lines1.begin(), key_it);
1956 EXPECT_EQ(lines1.end(), header.header_lines_key_end());
1957 EXPECT_NE(header.header_lines_key_end(), key_it);
1958 EXPECT_EQ("key", key_it->first);
1959 EXPECT_EQ("value_2", key_it->second);
1960 ++key_it;
1961 EXPECT_EQ(header.lines().end(), key_it);
1962 EXPECT_EQ(header.header_lines_key_end(), key_it);
1963
1964 header.erase(header.GetHeaderPosition("key"));
1965 key_it = header.GetIteratorForKey("key");
1966 const auto lines2 = header.lines("key");
1967 EXPECT_EQ(lines2.begin(), key_it);
1968 EXPECT_EQ(lines2.end(), header.header_lines_key_end());
1969 EXPECT_EQ(header.lines().end(), key_it);
1970 EXPECT_EQ(header.header_lines_key_end(), key_it);
1971
1972 key_it = header.GetIteratorForKey("a");
1973 const auto lines3 = header.lines("a");
1974 EXPECT_EQ(lines3.begin(), key_it);
1975 EXPECT_EQ(lines3.end(), header.header_lines_key_end());
1976 EXPECT_NE(header.lines().end(), key_it);
1977 EXPECT_NE(header.header_lines_key_end(), key_it);
1978 EXPECT_EQ("a", key_it->first);
1979 EXPECT_EQ("va", key_it->second);
1980 ++key_it;
1981 EXPECT_EQ(header.lines().end(), key_it);
1982 EXPECT_EQ(header.header_lines_key_end(), key_it);
1983
1984 header.erase(header.GetHeaderPosition("a"));
1985 key_it = header.GetIteratorForKey("a");
1986 const auto lines4 = header.lines("a");
1987 EXPECT_EQ(lines4.begin(), key_it);
1988 EXPECT_EQ(lines4.end(), header.header_lines_key_end());
1989 EXPECT_EQ(header.lines().end(), key_it);
1990 EXPECT_EQ(header.header_lines_key_end(), key_it);
1991 }
1992
TEST(BalsaHeaders,GetIteratorForKeyWithNoHeaderLines)1993 TEST(BalsaHeaders, GetIteratorForKeyWithNoHeaderLines) {
1994 BalsaHeaders header;
1995 BalsaHeaders::const_header_lines_key_iterator key_it =
1996 header.GetIteratorForKey("key");
1997 const auto lines = header.lines("key");
1998 EXPECT_EQ(lines.begin(), key_it);
1999 EXPECT_EQ(lines.end(), header.header_lines_key_end());
2000 EXPECT_EQ(header.lines().end(), key_it);
2001 EXPECT_EQ(header.header_lines_key_end(), key_it);
2002 }
2003
TEST(BalsaHeaders,GetIteratorForKeyWithBalsaFrameProcessInput)2004 TEST(BalsaHeaders, GetIteratorForKeyWithBalsaFrameProcessInput) {
2005 BalsaHeaders header = CreateHTTPHeaders(true,
2006 "GET / HTTP/1.0\r\n"
2007 "key1: value_1\r\n"
2008 "Key1: value_foo\r\n"
2009 "key2: value_2\r\n"
2010 "a: value_a\r\n"
2011 "key2: \r\n"
2012 "b: value_b\r\n"
2013 "\r\n");
2014
2015 BalsaHeaders::const_header_lines_key_iterator key_it =
2016 header.GetIteratorForKey("Key1");
2017 const auto lines1 = header.lines("Key1");
2018 EXPECT_EQ(lines1.begin(), key_it);
2019 EXPECT_EQ(lines1.end(), header.header_lines_key_end());
2020 EXPECT_NE(header.lines().end(), key_it);
2021 EXPECT_NE(header.header_lines_key_end(), key_it);
2022 EXPECT_EQ("key1", key_it->first);
2023 EXPECT_EQ("value_1", key_it->second);
2024 ++key_it;
2025 EXPECT_NE(header.lines().end(), key_it);
2026 EXPECT_NE(header.header_lines_key_end(), key_it);
2027 EXPECT_EQ("Key1", key_it->first);
2028 EXPECT_EQ("value_foo", key_it->second);
2029 ++key_it;
2030 EXPECT_EQ(header.lines().end(), key_it);
2031 EXPECT_EQ(header.header_lines_key_end(), key_it);
2032
2033 key_it = header.GetIteratorForKey("key2");
2034 EXPECT_NE(header.lines().end(), key_it);
2035 const auto lines2 = header.lines("key2");
2036 EXPECT_EQ(lines2.begin(), key_it);
2037 EXPECT_EQ(lines2.end(), header.header_lines_key_end());
2038 EXPECT_NE(header.header_lines_key_end(), key_it);
2039 EXPECT_EQ("key2", key_it->first);
2040 EXPECT_EQ("value_2", key_it->second);
2041 ++key_it;
2042 EXPECT_NE(header.lines().end(), key_it);
2043 EXPECT_NE(header.header_lines_key_end(), key_it);
2044 EXPECT_EQ("key2", key_it->first);
2045 EXPECT_EQ("", key_it->second);
2046 ++key_it;
2047 EXPECT_EQ(header.lines().end(), key_it);
2048 EXPECT_EQ(header.header_lines_key_end(), key_it);
2049
2050 key_it = header.GetIteratorForKey("a");
2051 EXPECT_NE(header.lines().end(), key_it);
2052 const auto lines3 = header.lines("a");
2053 EXPECT_EQ(lines3.begin(), key_it);
2054 EXPECT_EQ(lines3.end(), header.header_lines_key_end());
2055 EXPECT_NE(header.header_lines_key_end(), key_it);
2056 EXPECT_EQ("a", key_it->first);
2057 EXPECT_EQ("value_a", key_it->second);
2058 ++key_it;
2059 EXPECT_EQ(header.lines().end(), key_it);
2060 EXPECT_EQ(header.header_lines_key_end(), key_it);
2061
2062 key_it = header.GetIteratorForKey("b");
2063 EXPECT_NE(header.lines().end(), key_it);
2064 const auto lines4 = header.lines("b");
2065 EXPECT_EQ(lines4.begin(), key_it);
2066 EXPECT_EQ(lines4.end(), header.header_lines_key_end());
2067 EXPECT_NE(header.header_lines_key_end(), key_it);
2068 EXPECT_EQ("b", key_it->first);
2069 EXPECT_EQ("value_b", key_it->second);
2070 ++key_it;
2071 EXPECT_EQ(header.lines().end(), key_it);
2072 EXPECT_EQ(header.header_lines_key_end(), key_it);
2073 }
2074
TEST(BalsaHeaders,GetAllOfHeaderAsStringDoesWhatItSays)2075 TEST(BalsaHeaders, GetAllOfHeaderAsStringDoesWhatItSays) {
2076 BalsaHeaders header;
2077 // Multiple values for a given header.
2078 // Some values appear multiple times
2079 header.AppendHeader("key", "value_1");
2080 header.AppendHeader("Key", "value_2");
2081 header.AppendHeader("key", "");
2082 header.AppendHeader("KEY", "value_1");
2083
2084 std::string result = header.GetAllOfHeaderAsString("key");
2085 EXPECT_EQ("value_1,value_2,,value_1", result);
2086 }
2087
TEST(BalsaHeaders,RemoveAllOfHeaderDoesWhatItSays)2088 TEST(BalsaHeaders, RemoveAllOfHeaderDoesWhatItSays) {
2089 BalsaHeaders header;
2090 header.AppendHeader("key", "value_1");
2091 header.AppendHeader("key", "value_2");
2092 ASSERT_NE(header.lines().begin(), header.lines().end());
2093 header.RemoveAllOfHeader("key");
2094 ASSERT_EQ(header.lines().begin(), header.lines().end());
2095 }
2096
TEST(BalsaHeaders,RemoveAllOfHeaderDoesWhatItSaysEvenWhenThingsHaveBeenErased)2097 TEST(BalsaHeaders,
2098 RemoveAllOfHeaderDoesWhatItSaysEvenWhenThingsHaveBeenErased) {
2099 BalsaHeaders header;
2100 header.AppendHeader("key1", "value_1");
2101 header.AppendHeader("key1", "value_2");
2102 header.AppendHeader("key2", "value_3");
2103 header.AppendHeader("key1", "value_4");
2104 header.AppendHeader("key2", "value_5");
2105 header.AppendHeader("key1", "value_6");
2106 ASSERT_NE(header.lines().begin(), header.lines().end());
2107
2108 BalsaHeaders::const_header_lines_iterator chli = header.lines().begin();
2109 ++chli;
2110 ++chli;
2111 ++chli;
2112 header.erase(chli);
2113
2114 chli = header.lines().begin();
2115 ++chli;
2116 header.erase(chli);
2117
2118 header.RemoveAllOfHeader("key1");
2119 for (const auto& line : header.lines()) {
2120 EXPECT_NE(std::string("key1"), line.first);
2121 }
2122 }
2123
TEST(BalsaHeaders,RemoveAllOfHeaderDoesNothingWhenNoKeyOfThatNameExists)2124 TEST(BalsaHeaders, RemoveAllOfHeaderDoesNothingWhenNoKeyOfThatNameExists) {
2125 BalsaHeaders header;
2126 header.AppendHeader("key", "value_1");
2127 header.AppendHeader("key", "value_2");
2128 ASSERT_NE(header.lines().begin(), header.lines().end());
2129 header.RemoveAllOfHeader("foo");
2130 int num_found = 0;
2131 for (const auto& line : header.lines()) {
2132 ++num_found;
2133 EXPECT_EQ(absl::string_view("key"), line.first);
2134 }
2135 EXPECT_EQ(2, num_found);
2136 EXPECT_NE(header.lines().begin(), header.lines().end());
2137 }
2138
TEST(BalsaHeaders,WriteHeaderEndingToBuffer)2139 TEST(BalsaHeaders, WriteHeaderEndingToBuffer) {
2140 BalsaHeaders header;
2141 SimpleBuffer simple_buffer;
2142 header.WriteHeaderEndingToBuffer(&simple_buffer);
2143 EXPECT_THAT(simple_buffer.GetReadableRegion(), StrEq("\r\n"));
2144 }
2145
TEST(BalsaHeaders,WriteToBufferDoesntCrashWithUninitializedHeader)2146 TEST(BalsaHeaders, WriteToBufferDoesntCrashWithUninitializedHeader) {
2147 BalsaHeaders header;
2148 SimpleBuffer simple_buffer;
2149 header.WriteHeaderAndEndingToBuffer(&simple_buffer);
2150 }
2151
TEST(BalsaHeaders,WriteToBufferWorksWithBalsaHeadersParsedByFramer)2152 TEST(BalsaHeaders, WriteToBufferWorksWithBalsaHeadersParsedByFramer) {
2153 std::string input =
2154 "GET / HTTP/1.0\r\n"
2155 "key_with_value: value\r\n"
2156 "key_with_continuation_value: \r\n"
2157 " with continuation\r\n"
2158 "key_with_two_continuation_value: \r\n"
2159 " continuation 1\r\n"
2160 " continuation 2\r\n"
2161 "a: foo \r\n"
2162 "b-s:\n"
2163 " bar\t\n"
2164 "foo: \r\n"
2165 "bazzzzzzzleriffic!: snaps\n"
2166 "\n";
2167 std::string expected =
2168 "GET / HTTP/1.0\r\n"
2169 "key_with_value: value\r\n"
2170 "key_with_continuation_value: with continuation\r\n"
2171 "key_with_two_continuation_value: continuation 1\r\n"
2172 " continuation 2\r\n"
2173 "a: foo\r\n"
2174 "b-s: bar\r\n"
2175 "foo: \r\n"
2176 "bazzzzzzzleriffic!: snaps\r\n"
2177 "\r\n";
2178
2179 BalsaHeaders headers = CreateHTTPHeaders(true, input);
2180 SimpleBuffer simple_buffer;
2181 size_t expected_write_buffer_size = headers.GetSizeForWriteBuffer();
2182 headers.WriteHeaderAndEndingToBuffer(&simple_buffer);
2183 EXPECT_THAT(simple_buffer.GetReadableRegion(), StrEq(expected));
2184 EXPECT_EQ(expected_write_buffer_size,
2185 static_cast<size_t>(simple_buffer.ReadableBytes()));
2186 }
2187
TEST(BalsaHeaders,WriteToBufferWorksWithBalsaHeadersParsedByFramerTabContinuations)2188 TEST(BalsaHeaders,
2189 WriteToBufferWorksWithBalsaHeadersParsedByFramerTabContinuations) {
2190 std::string input =
2191 "GET / HTTP/1.0\r\n"
2192 "key_with_value: value\r\n"
2193 "key_with_continuation_value: \r\n"
2194 "\twith continuation\r\n"
2195 "key_with_two_continuation_value: \r\n"
2196 "\tcontinuation 1\r\n"
2197 "\tcontinuation 2\r\n"
2198 "a: foo \r\n"
2199 "b-s:\n"
2200 "\tbar\t\n"
2201 "foo: \r\n"
2202 "bazzzzzzzleriffic!: snaps\n"
2203 "\n";
2204 std::string expected =
2205 "GET / HTTP/1.0\r\n"
2206 "key_with_value: value\r\n"
2207 "key_with_continuation_value: with continuation\r\n"
2208 "key_with_two_continuation_value: continuation 1\r\n"
2209 "\tcontinuation 2\r\n"
2210 "a: foo\r\n"
2211 "b-s: bar\r\n"
2212 "foo: \r\n"
2213 "bazzzzzzzleriffic!: snaps\r\n"
2214 "\r\n";
2215
2216 BalsaHeaders headers = CreateHTTPHeaders(true, input);
2217 SimpleBuffer simple_buffer;
2218 size_t expected_write_buffer_size = headers.GetSizeForWriteBuffer();
2219 headers.WriteHeaderAndEndingToBuffer(&simple_buffer);
2220 EXPECT_THAT(simple_buffer.GetReadableRegion(), StrEq(expected));
2221 EXPECT_EQ(expected_write_buffer_size,
2222 static_cast<size_t>(simple_buffer.ReadableBytes()));
2223 }
2224
TEST(BalsaHeaders,WriteToBufferWorksWhenFirstlineSetThroughHeaders)2225 TEST(BalsaHeaders, WriteToBufferWorksWhenFirstlineSetThroughHeaders) {
2226 BalsaHeaders headers;
2227 headers.SetRequestFirstlineFromStringPieces("GET", "/", "HTTP/1.0");
2228 std::string expected =
2229 "GET / HTTP/1.0\r\n"
2230 "\r\n";
2231 SimpleBuffer simple_buffer;
2232 size_t expected_write_buffer_size = headers.GetSizeForWriteBuffer();
2233 headers.WriteHeaderAndEndingToBuffer(&simple_buffer);
2234 EXPECT_THAT(simple_buffer.GetReadableRegion(), StrEq(expected));
2235 EXPECT_EQ(expected_write_buffer_size,
2236 static_cast<size_t>(simple_buffer.ReadableBytes()));
2237 }
2238
TEST(BalsaHeaders,WriteToBufferWorksWhenSetThroughHeaders)2239 TEST(BalsaHeaders, WriteToBufferWorksWhenSetThroughHeaders) {
2240 BalsaHeaders headers;
2241 headers.SetRequestFirstlineFromStringPieces("GET", "/", "HTTP/1.0");
2242 headers.AppendHeader("key1", "value1");
2243 headers.AppendHeader("key 2", "value\n 2");
2244 headers.AppendHeader("key\n 3", "value3");
2245 std::string expected =
2246 "GET / HTTP/1.0\r\n"
2247 "key1: value1\r\n"
2248 "key 2: value\n"
2249 " 2\r\n"
2250 "key\n"
2251 " 3: value3\r\n"
2252 "\r\n";
2253 SimpleBuffer simple_buffer;
2254 size_t expected_write_buffer_size = headers.GetSizeForWriteBuffer();
2255 headers.WriteHeaderAndEndingToBuffer(&simple_buffer);
2256 EXPECT_THAT(simple_buffer.GetReadableRegion(), StrEq(expected));
2257 EXPECT_EQ(expected_write_buffer_size,
2258 static_cast<size_t>(simple_buffer.ReadableBytes()));
2259 }
2260
TEST(BalsaHeaders,WriteToBufferWorkWhensOnlyLinesSetThroughHeaders)2261 TEST(BalsaHeaders, WriteToBufferWorkWhensOnlyLinesSetThroughHeaders) {
2262 BalsaHeaders headers;
2263 headers.AppendHeader("key1", "value1");
2264 headers.AppendHeader("key 2", "value\n 2");
2265 headers.AppendHeader("key\n 3", "value3");
2266 std::string expected =
2267 "\r\n"
2268 "key1: value1\r\n"
2269 "key 2: value\n"
2270 " 2\r\n"
2271 "key\n"
2272 " 3: value3\r\n"
2273 "\r\n";
2274 SimpleBuffer simple_buffer;
2275 size_t expected_write_buffer_size = headers.GetSizeForWriteBuffer();
2276 headers.WriteHeaderAndEndingToBuffer(&simple_buffer);
2277 EXPECT_THAT(simple_buffer.GetReadableRegion(), StrEq(expected));
2278 EXPECT_EQ(expected_write_buffer_size,
2279 static_cast<size_t>(simple_buffer.ReadableBytes()));
2280 }
2281
TEST(BalsaHeaders,WriteToBufferWorksWhenSetThroughHeadersWithElementsErased)2282 TEST(BalsaHeaders, WriteToBufferWorksWhenSetThroughHeadersWithElementsErased) {
2283 BalsaHeaders headers;
2284 headers.SetRequestFirstlineFromStringPieces("GET", "/", "HTTP/1.0");
2285 headers.AppendHeader("key1", "value1");
2286 headers.AppendHeader("key 2", "value\n 2");
2287 headers.AppendHeader("key\n 3", "value3");
2288 headers.RemoveAllOfHeader("key1");
2289 headers.RemoveAllOfHeader("key\n 3");
2290 std::string expected =
2291 "GET / HTTP/1.0\r\n"
2292 "key 2: value\n"
2293 " 2\r\n"
2294 "\r\n";
2295 SimpleBuffer simple_buffer;
2296 size_t expected_write_buffer_size = headers.GetSizeForWriteBuffer();
2297 headers.WriteHeaderAndEndingToBuffer(&simple_buffer);
2298 EXPECT_THAT(simple_buffer.GetReadableRegion(), StrEq(expected));
2299 EXPECT_EQ(expected_write_buffer_size,
2300 static_cast<size_t>(simple_buffer.ReadableBytes()));
2301 }
2302
TEST(BalsaHeaders,WriteToBufferWithManuallyAppendedHeaderLine)2303 TEST(BalsaHeaders, WriteToBufferWithManuallyAppendedHeaderLine) {
2304 BalsaHeaders headers;
2305 headers.SetRequestFirstlineFromStringPieces("GET", "/", "HTTP/1.0");
2306 headers.AppendHeader("key1", "value1");
2307 headers.AppendHeader("key 2", "value\n 2");
2308 std::string expected =
2309 "GET / HTTP/1.0\r\n"
2310 "key1: value1\r\n"
2311 "key 2: value\n"
2312 " 2\r\n"
2313 "key 3: value 3\r\n"
2314 "\r\n";
2315
2316 SimpleBuffer simple_buffer;
2317 size_t expected_write_buffer_size = headers.GetSizeForWriteBuffer();
2318 headers.WriteToBuffer(&simple_buffer);
2319 headers.WriteHeaderLineToBuffer(&simple_buffer, "key 3", "value 3",
2320 BalsaHeaders::CaseOption::kNoModification);
2321 headers.WriteHeaderEndingToBuffer(&simple_buffer);
2322 EXPECT_THAT(simple_buffer.GetReadableRegion(), StrEq(expected));
2323 EXPECT_EQ(expected_write_buffer_size + 16,
2324 static_cast<size_t>(simple_buffer.ReadableBytes()));
2325 }
2326
TEST(BalsaHeaders,DumpToStringEmptyHeaders)2327 TEST(BalsaHeaders, DumpToStringEmptyHeaders) {
2328 BalsaHeaders headers;
2329 std::string headers_str;
2330 headers.DumpToString(&headers_str);
2331 EXPECT_EQ("\n <empty header>\n", headers_str);
2332 }
2333
TEST(BalsaHeaders,DumpToStringParsedHeaders)2334 TEST(BalsaHeaders, DumpToStringParsedHeaders) {
2335 std::string input =
2336 "GET / HTTP/1.0\r\n"
2337 "Header1: value\r\n"
2338 "Header2: value\r\n"
2339 "\r\n";
2340 std::string output =
2341 "\n"
2342 " GET / HTTP/1.0\n"
2343 " Header1: value\n"
2344 " Header2: value\n";
2345
2346 BalsaHeaders headers = CreateHTTPHeaders(true, input);
2347 std::string headers_str;
2348 headers.DumpToString(&headers_str);
2349 EXPECT_EQ(output, headers_str);
2350 EXPECT_TRUE(headers.FramerIsDoneWriting());
2351 }
2352
TEST(BalsaHeaders,DumpToStringPartialHeaders)2353 TEST(BalsaHeaders, DumpToStringPartialHeaders) {
2354 BalsaHeaders headers;
2355 BalsaFrame balsa_frame;
2356 balsa_frame.set_is_request(true);
2357 balsa_frame.set_balsa_headers(&headers);
2358 std::string input =
2359 "GET / HTTP/1.0\r\n"
2360 "Header1: value\r\n"
2361 "Header2: value\r\n";
2362 std::string output = absl::StrFormat("\n <incomplete header len: %d>\n ",
2363 static_cast<int>(input.size()));
2364 output += input;
2365 output += '\n';
2366
2367 ASSERT_EQ(input.size(), balsa_frame.ProcessInput(input.data(), input.size()));
2368 ASSERT_FALSE(balsa_frame.MessageFullyRead());
2369 std::string headers_str;
2370 headers.DumpToString(&headers_str);
2371 EXPECT_EQ(output, headers_str);
2372 EXPECT_FALSE(headers.FramerIsDoneWriting());
2373 }
2374
TEST(BalsaHeaders,DumpToStringParsingNonHeadersData)2375 TEST(BalsaHeaders, DumpToStringParsingNonHeadersData) {
2376 BalsaHeaders headers;
2377 BalsaFrame balsa_frame;
2378 balsa_frame.set_is_request(true);
2379 balsa_frame.set_balsa_headers(&headers);
2380 std::string input =
2381 "This is not a header. "
2382 "Just some random data to simulate mismatch.";
2383 std::string output = absl::StrFormat("\n <incomplete header len: %d>\n ",
2384 static_cast<int>(input.size()));
2385 output += input;
2386 output += '\n';
2387
2388 ASSERT_EQ(input.size(), balsa_frame.ProcessInput(input.data(), input.size()));
2389 ASSERT_FALSE(balsa_frame.MessageFullyRead());
2390 std::string headers_str;
2391 headers.DumpToString(&headers_str);
2392 EXPECT_EQ(output, headers_str);
2393 }
2394
TEST(BalsaHeaders,Clear)2395 TEST(BalsaHeaders, Clear) {
2396 BalsaHeaders headers;
2397 headers.SetRequestFirstlineFromStringPieces("GET", "/", "HTTP/1.0");
2398 headers.AppendHeader("key1", "value1");
2399 headers.AppendHeader("key 2", "value\n 2");
2400 headers.AppendHeader("key\n 3", "value3");
2401 headers.RemoveAllOfHeader("key1");
2402 headers.RemoveAllOfHeader("key\n 3");
2403 headers.Clear();
2404 EXPECT_TRUE(headers.first_line().empty());
2405 EXPECT_EQ(headers.lines().begin(), headers.lines().end());
2406 EXPECT_TRUE(headers.IsEmpty());
2407 }
2408
TEST(BalsaHeaders,TestSetFromStringPiecesWithInitialFirstlineInHeaderStreamAndNewToo)2409 TEST(BalsaHeaders,
2410 TestSetFromStringPiecesWithInitialFirstlineInHeaderStreamAndNewToo) {
2411 BalsaHeaders headers = CreateHTTPHeaders(false,
2412 "HTTP/1.1 200 reason phrase\r\n"
2413 "content-length: 0\r\n"
2414 "\r\n");
2415 EXPECT_THAT(headers.response_version(), StrEq("HTTP/1.1"));
2416 EXPECT_THAT(headers.response_code(), StrEq("200"));
2417 EXPECT_THAT(headers.response_reason_phrase(), StrEq("reason phrase"));
2418
2419 headers.SetResponseFirstline("HTTP/1.0", 404, "a reason");
2420 EXPECT_THAT(headers.response_version(), StrEq("HTTP/1.0"));
2421 EXPECT_THAT(headers.response_code(), StrEq("404"));
2422 EXPECT_THAT(headers.parsed_response_code(), Eq(404));
2423 EXPECT_THAT(headers.response_reason_phrase(), StrEq("a reason"));
2424 EXPECT_THAT(headers.first_line(), StrEq("HTTP/1.0 404 a reason"));
2425 }
2426
TEST(BalsaHeaders,TestSetFromStringPiecesWithInitialFirstlineInHeaderStreamButNotNew)2427 TEST(BalsaHeaders,
2428 TestSetFromStringPiecesWithInitialFirstlineInHeaderStreamButNotNew) {
2429 BalsaHeaders headers = CreateHTTPHeaders(false,
2430 "HTTP/1.1 200 reason phrase\r\n"
2431 "content-length: 0\r\n"
2432 "\r\n");
2433 EXPECT_THAT(headers.response_version(), StrEq("HTTP/1.1"));
2434 EXPECT_THAT(headers.response_code(), StrEq("200"));
2435 EXPECT_THAT(headers.response_reason_phrase(), StrEq("reason phrase"));
2436
2437 headers.SetResponseFirstline("HTTP/1.000", 404000,
2438 "supercalifragilisticexpealidocious");
2439 EXPECT_THAT(headers.response_version(), StrEq("HTTP/1.000"));
2440 EXPECT_THAT(headers.response_code(), StrEq("404000"));
2441 EXPECT_THAT(headers.parsed_response_code(), Eq(404000));
2442 EXPECT_THAT(headers.response_reason_phrase(),
2443 StrEq("supercalifragilisticexpealidocious"));
2444 EXPECT_THAT(headers.first_line(),
2445 StrEq("HTTP/1.000 404000 supercalifragilisticexpealidocious"));
2446 }
2447
TEST(BalsaHeaders,TestSetFromStringPiecesWithFirstFirstlineInHeaderStreamButNotNew2)2448 TEST(BalsaHeaders,
2449 TestSetFromStringPiecesWithFirstFirstlineInHeaderStreamButNotNew2) {
2450 SCOPED_TRACE(
2451 "This test tests the codepath where the new firstline is"
2452 " too large to fit within the space used by the original"
2453 " firstline, but large enuogh to space in the free space"
2454 " available in both firstline plus the space made available"
2455 " with deleted header lines (specifically, the first one");
2456 BalsaHeaders headers = CreateHTTPHeaders(
2457 false,
2458 "HTTP/1.1 200 reason phrase\r\n"
2459 "a: 0987123409871234078130948710938471093827401983740198327401982374\r\n"
2460 "content-length: 0\r\n"
2461 "\r\n");
2462 EXPECT_THAT(headers.response_version(), StrEq("HTTP/1.1"));
2463 EXPECT_THAT(headers.response_code(), StrEq("200"));
2464 EXPECT_THAT(headers.response_reason_phrase(), StrEq("reason phrase"));
2465
2466 headers.erase(headers.lines().begin());
2467 headers.SetResponseFirstline("HTTP/1.000", 404000,
2468 "supercalifragilisticexpealidocious");
2469 EXPECT_THAT(headers.response_version(), StrEq("HTTP/1.000"));
2470 EXPECT_THAT(headers.response_code(), StrEq("404000"));
2471 EXPECT_THAT(headers.parsed_response_code(), Eq(404000));
2472 EXPECT_THAT(headers.response_reason_phrase(),
2473 StrEq("supercalifragilisticexpealidocious"));
2474 EXPECT_THAT(headers.first_line(),
2475 StrEq("HTTP/1.000 404000 supercalifragilisticexpealidocious"));
2476 }
2477
TEST(BalsaHeaders,TestSetFirstlineFromStringPiecesWithNoInitialFirstline)2478 TEST(BalsaHeaders, TestSetFirstlineFromStringPiecesWithNoInitialFirstline) {
2479 BalsaHeaders headers;
2480 headers.SetResponseFirstline("HTTP/1.1", 200, "don't need a reason");
2481 EXPECT_THAT(headers.response_version(), StrEq("HTTP/1.1"));
2482 EXPECT_THAT(headers.response_code(), StrEq("200"));
2483 EXPECT_THAT(headers.parsed_response_code(), Eq(200));
2484 EXPECT_THAT(headers.response_reason_phrase(), StrEq("don't need a reason"));
2485 EXPECT_THAT(headers.first_line(), StrEq("HTTP/1.1 200 don't need a reason"));
2486 }
2487
TEST(BalsaHeaders,TestSettingFirstlineElementsWithOtherElementsMissing)2488 TEST(BalsaHeaders, TestSettingFirstlineElementsWithOtherElementsMissing) {
2489 {
2490 BalsaHeaders headers;
2491 headers.SetRequestMethod("GET");
2492 headers.SetRequestUri("/");
2493 EXPECT_THAT(headers.first_line(), StrEq("GET / "));
2494 }
2495 {
2496 BalsaHeaders headers;
2497 headers.SetRequestMethod("GET");
2498 headers.SetRequestVersion("HTTP/1.1");
2499 EXPECT_THAT(headers.first_line(), StrEq("GET HTTP/1.1"));
2500 }
2501 {
2502 BalsaHeaders headers;
2503 headers.SetRequestUri("/");
2504 headers.SetRequestVersion("HTTP/1.1");
2505 EXPECT_THAT(headers.first_line(), StrEq(" / HTTP/1.1"));
2506 }
2507 }
2508
TEST(BalsaHeaders,TestSettingMissingFirstlineElementsAfterBalsaHeadersParsed)2509 TEST(BalsaHeaders, TestSettingMissingFirstlineElementsAfterBalsaHeadersParsed) {
2510 {
2511 BalsaHeaders headers = CreateHTTPHeaders(true, "GET /foo\r\n");
2512 ASSERT_THAT(headers.first_line(), StrEq("GET /foo"));
2513
2514 headers.SetRequestVersion("HTTP/1.1");
2515 EXPECT_THAT(headers.first_line(), StrEq("GET /foo HTTP/1.1"));
2516 }
2517 {
2518 BalsaHeaders headers = CreateHTTPHeaders(true, "GET\r\n");
2519 ASSERT_THAT(headers.first_line(), StrEq("GET"));
2520
2521 headers.SetRequestUri("/foo");
2522 EXPECT_THAT(headers.first_line(), StrEq("GET /foo "));
2523 }
2524 }
2525
2526 // Here we exersize the codepaths involved in setting a new firstine when the
2527 // previously set firstline is stored in the 'additional_data_stream_'
2528 // variable, and the new firstline is larger than the previously set firstline.
TEST(BalsaHeaders,SetFirstlineFromStringPiecesFirstInAdditionalDataAndNewLarger)2529 TEST(BalsaHeaders,
2530 SetFirstlineFromStringPiecesFirstInAdditionalDataAndNewLarger) {
2531 BalsaHeaders headers;
2532 // This one will end up being put into the additional data stream
2533 headers.SetResponseFirstline("HTTP/1.1", 200, "don't need a reason");
2534 EXPECT_THAT(headers.response_version(), StrEq("HTTP/1.1"));
2535 EXPECT_THAT(headers.response_code(), StrEq("200"));
2536 EXPECT_THAT(headers.parsed_response_code(), Eq(200));
2537 EXPECT_THAT(headers.response_reason_phrase(), StrEq("don't need a reason"));
2538 EXPECT_THAT(headers.first_line(), StrEq("HTTP/1.1 200 don't need a reason"));
2539
2540 // Now, we set it again, this time we're extending what exists
2541 // here.
2542 headers.SetResponseFirstline("HTTP/1.10", 2000, "REALLY don't need a reason");
2543 EXPECT_THAT(headers.response_version(), StrEq("HTTP/1.10"));
2544 EXPECT_THAT(headers.response_code(), StrEq("2000"));
2545 EXPECT_THAT(headers.parsed_response_code(), Eq(2000));
2546 EXPECT_THAT(headers.response_reason_phrase(),
2547 StrEq("REALLY don't need a reason"));
2548 EXPECT_THAT(headers.first_line(),
2549 StrEq("HTTP/1.10 2000 REALLY don't need a reason"));
2550 }
2551
2552 // Here we exersize the codepaths involved in setting a new firstine when the
2553 // previously set firstline is stored in the 'additional_data_stream_'
2554 // variable, and the new firstline is smaller than the previously set firstline.
TEST(BalsaHeaders,TestSetFirstlineFromStringPiecesWithPreviousInAdditionalDataNewSmaller)2555 TEST(BalsaHeaders,
2556 TestSetFirstlineFromStringPiecesWithPreviousInAdditionalDataNewSmaller) {
2557 BalsaHeaders headers;
2558 // This one will end up being put into the additional data stream
2559 //
2560 headers.SetResponseFirstline("HTTP/1.10", 2000, "REALLY don't need a reason");
2561 EXPECT_THAT(headers.response_version(), StrEq("HTTP/1.10"));
2562 EXPECT_THAT(headers.response_code(), StrEq("2000"));
2563 EXPECT_THAT(headers.parsed_response_code(), Eq(2000));
2564 EXPECT_THAT(headers.response_reason_phrase(),
2565 StrEq("REALLY don't need a reason"));
2566 EXPECT_THAT(headers.first_line(),
2567 StrEq("HTTP/1.10 2000 REALLY don't need a reason"));
2568
2569 // Now, we set it again, this time we're extending what exists
2570 // here.
2571 headers.SetResponseFirstline("HTTP/1.0", 200, "a reason");
2572 EXPECT_THAT(headers.response_version(), StrEq("HTTP/1.0"));
2573 EXPECT_THAT(headers.response_code(), StrEq("200"));
2574 EXPECT_THAT(headers.parsed_response_code(), Eq(200));
2575 EXPECT_THAT(headers.response_reason_phrase(), StrEq("a reason"));
2576 EXPECT_THAT(headers.first_line(), StrEq("HTTP/1.0 200 a reason"));
2577 }
2578
TEST(BalsaHeaders,CopyFrom)2579 TEST(BalsaHeaders, CopyFrom) {
2580 BalsaHeaders headers1, headers2;
2581 absl::string_view method("GET");
2582 absl::string_view uri("/foo");
2583 absl::string_view version("HTTP/1.0");
2584 headers1.SetRequestFirstlineFromStringPieces(method, uri, version);
2585 headers1.AppendHeader("key1", "value1");
2586 headers1.AppendHeader("key 2", "value\n 2");
2587 headers1.AppendHeader("key\n 3", "value3");
2588
2589 // "GET /foo HTTP/1.0" // 17
2590 // "key1: value1\r\n" // 14
2591 // "key 2: value\n 2\r\n" // 17
2592 // "key\n 3: value3\r\n" // 16
2593
2594 headers2.CopyFrom(headers1);
2595
2596 EXPECT_THAT(headers1.first_line(), StrEq("GET /foo HTTP/1.0"));
2597 BalsaHeaders::const_header_lines_iterator chli = headers1.lines().begin();
2598 EXPECT_THAT(chli->first, StrEq("key1"));
2599 EXPECT_THAT(chli->second, StrEq("value1"));
2600 ++chli;
2601 EXPECT_THAT(chli->first, StrEq("key 2"));
2602 EXPECT_THAT(chli->second, StrEq("value\n 2"));
2603 ++chli;
2604 EXPECT_THAT(chli->first, StrEq("key\n 3"));
2605 EXPECT_THAT(chli->second, StrEq("value3"));
2606 ++chli;
2607 EXPECT_EQ(headers1.lines().end(), chli);
2608
2609 EXPECT_THAT(headers1.request_method(),
2610 StrEq((std::string(headers2.request_method()))));
2611 EXPECT_THAT(headers1.request_uri(),
2612 StrEq((std::string(headers2.request_uri()))));
2613 EXPECT_THAT(headers1.request_version(),
2614 StrEq((std::string(headers2.request_version()))));
2615
2616 EXPECT_THAT(headers2.first_line(), StrEq("GET /foo HTTP/1.0"));
2617 chli = headers2.lines().begin();
2618 EXPECT_THAT(chli->first, StrEq("key1"));
2619 EXPECT_THAT(chli->second, StrEq("value1"));
2620 ++chli;
2621 EXPECT_THAT(chli->first, StrEq("key 2"));
2622 EXPECT_THAT(chli->second, StrEq("value\n 2"));
2623 ++chli;
2624 EXPECT_THAT(chli->first, StrEq("key\n 3"));
2625 EXPECT_THAT(chli->second, StrEq("value3"));
2626 ++chli;
2627 EXPECT_EQ(headers2.lines().end(), chli);
2628
2629 version = absl::string_view("HTTP/1.1");
2630 int code = 200;
2631 absl::string_view reason_phrase("reason phrase asdf");
2632
2633 headers1.RemoveAllOfHeader("key1");
2634 headers1.AppendHeader("key4", "value4");
2635
2636 headers1.SetResponseFirstline(version, code, reason_phrase);
2637
2638 headers2.CopyFrom(headers1);
2639
2640 // "GET /foo HTTP/1.0" // 17
2641 // "XXXXXXXXXXXXXX" // 14
2642 // "key 2: value\n 2\r\n" // 17
2643 // "key\n 3: value3\r\n" // 16
2644 // "key4: value4\r\n" // 14
2645 //
2646 // ->
2647 //
2648 // "HTTP/1.1 200 reason phrase asdf" // 31 = (17 + 14)
2649 // "key 2: value\n 2\r\n" // 17
2650 // "key\n 3: value3\r\n" // 16
2651 // "key4: value4\r\n" // 14
2652
2653 EXPECT_THAT(headers1.request_method(),
2654 StrEq((std::string(headers2.request_method()))));
2655 EXPECT_THAT(headers1.request_uri(),
2656 StrEq((std::string(headers2.request_uri()))));
2657 EXPECT_THAT(headers1.request_version(),
2658 StrEq((std::string(headers2.request_version()))));
2659
2660 EXPECT_THAT(headers2.first_line(), StrEq("HTTP/1.1 200 reason phrase asdf"));
2661 chli = headers2.lines().begin();
2662 EXPECT_THAT(chli->first, StrEq("key 2"));
2663 EXPECT_THAT(chli->second, StrEq("value\n 2"));
2664 ++chli;
2665 EXPECT_THAT(chli->first, StrEq("key\n 3"));
2666 EXPECT_THAT(chli->second, StrEq("value3"));
2667 ++chli;
2668 EXPECT_THAT(chli->first, StrEq("key4"));
2669 EXPECT_THAT(chli->second, StrEq("value4"));
2670 ++chli;
2671 EXPECT_EQ(headers2.lines().end(), chli);
2672 }
2673
2674 // Test BalsaHeaders move constructor and move assignment operator.
TEST(BalsaHeaders,Move)2675 TEST(BalsaHeaders, Move) {
2676 BalsaHeaders headers1, headers3;
2677 absl::string_view method("GET");
2678 absl::string_view uri("/foo");
2679 absl::string_view version("HTTP/1.0");
2680 headers1.SetRequestFirstlineFromStringPieces(method, uri, version);
2681 headers1.AppendHeader("key1", "value1");
2682 headers1.AppendHeader("key 2", "value\n 2");
2683 headers1.AppendHeader("key\n 3", "value3");
2684
2685 // "GET /foo HTTP/1.0" // 17
2686 // "key1: value1\r\n" // 14
2687 // "key 2: value\n 2\r\n" // 17
2688 // "key\n 3: value3\r\n" // 16
2689
2690 BalsaHeaders headers2 = std::move(headers1);
2691
2692 EXPECT_EQ("GET /foo HTTP/1.0", headers2.first_line());
2693 BalsaHeaders::const_header_lines_iterator chli = headers2.lines().begin();
2694 EXPECT_EQ("key1", chli->first);
2695 EXPECT_EQ("value1", chli->second);
2696 ++chli;
2697 EXPECT_EQ("key 2", chli->first);
2698 EXPECT_EQ("value\n 2", chli->second);
2699 ++chli;
2700 EXPECT_EQ("key\n 3", chli->first);
2701 EXPECT_EQ("value3", chli->second);
2702 ++chli;
2703 EXPECT_EQ(headers2.lines().end(), chli);
2704
2705 EXPECT_EQ("GET", headers2.request_method());
2706 EXPECT_EQ("/foo", headers2.request_uri());
2707 EXPECT_EQ("HTTP/1.0", headers2.request_version());
2708
2709 headers3 = std::move(headers2);
2710 version = absl::string_view("HTTP/1.1");
2711 int code = 200;
2712 absl::string_view reason_phrase("reason phrase asdf");
2713
2714 headers3.RemoveAllOfHeader("key1");
2715 headers3.AppendHeader("key4", "value4");
2716
2717 headers3.SetResponseFirstline(version, code, reason_phrase);
2718
2719 BalsaHeaders headers4 = std::move(headers3);
2720
2721 // "GET /foo HTTP/1.0" // 17
2722 // "XXXXXXXXXXXXXX" // 14
2723 // "key 2: value\n 2\r\n" // 17
2724 // "key\n 3: value3\r\n" // 16
2725 // "key4: value4\r\n" // 14
2726 //
2727 // ->
2728 //
2729 // "HTTP/1.1 200 reason phrase asdf" // 31 = (17 + 14)
2730 // "key 2: value\n 2\r\n" // 17
2731 // "key\n 3: value3\r\n" // 16
2732 // "key4: value4\r\n" // 14
2733
2734 EXPECT_EQ("200", headers4.response_code());
2735 EXPECT_EQ("reason phrase asdf", headers4.response_reason_phrase());
2736 EXPECT_EQ("HTTP/1.1", headers4.response_version());
2737
2738 EXPECT_EQ("HTTP/1.1 200 reason phrase asdf", headers4.first_line());
2739 chli = headers4.lines().begin();
2740 EXPECT_EQ("key 2", chli->first);
2741 EXPECT_EQ("value\n 2", chli->second);
2742 ++chli;
2743 EXPECT_EQ("key\n 3", chli->first);
2744 EXPECT_EQ("value3", chli->second);
2745 ++chli;
2746 EXPECT_EQ("key4", chli->first);
2747 EXPECT_EQ("value4", chli->second);
2748 ++chli;
2749 EXPECT_EQ(headers4.lines().end(), chli);
2750 }
2751
TEST(BalsaHeaders,IteratorWorksWithOStreamAsExpected)2752 TEST(BalsaHeaders, IteratorWorksWithOStreamAsExpected) {
2753 {
2754 std::stringstream actual;
2755 BalsaHeaders::const_header_lines_iterator chli;
2756 actual << chli;
2757 // Note that the output depends on the flavor of standard library in use.
2758 EXPECT_THAT(actual.str(), AnyOf(StrEq("[0, 0]"), // libstdc++
2759 StrEq("[(nil), 0]"), // libc++
2760 StrEq("[0x0, 0]"))); // libc++ on Mac
2761 }
2762 {
2763 BalsaHeaders headers;
2764 std::stringstream actual;
2765 BalsaHeaders::const_header_lines_iterator chli = headers.lines().begin();
2766 actual << chli;
2767 std::stringstream expected;
2768 expected << "[" << &headers << ", 0]";
2769 EXPECT_THAT(expected.str(), StrEq(actual.str()));
2770 }
2771 }
2772
TEST(BalsaHeaders,TestSetResponseReasonPhraseWithNoInitialFirstline)2773 TEST(BalsaHeaders, TestSetResponseReasonPhraseWithNoInitialFirstline) {
2774 BalsaHeaders balsa_headers;
2775 balsa_headers.SetResponseReasonPhrase("don't need a reason");
2776 EXPECT_THAT(balsa_headers.first_line(), StrEq(" don't need a reason"));
2777 EXPECT_TRUE(balsa_headers.response_version().empty());
2778 EXPECT_TRUE(balsa_headers.response_code().empty());
2779 EXPECT_THAT(balsa_headers.response_reason_phrase(),
2780 StrEq("don't need a reason"));
2781 }
2782
2783 // Testing each of 9 combinations separately was taking up way too much of this
2784 // file (not to mention the inordinate amount of stupid code duplication), thus
2785 // this test tests all 9 combinations of smaller, equal, and larger in one
2786 // place.
TEST(BalsaHeaders,TestSetResponseReasonPhrase)2787 TEST(BalsaHeaders, TestSetResponseReasonPhrase) {
2788 const char* response_reason_phrases[] = {
2789 "qwerty asdfgh",
2790 "qwerty",
2791 "qwerty asdfghjkl",
2792 };
2793 size_t arraysize_squared = (ABSL_ARRAYSIZE(response_reason_phrases) *
2794 ABSL_ARRAYSIZE(response_reason_phrases));
2795 // We go through the 9 different permutations of (response_reason_phrases
2796 // choose 2) in the loop below. For each permutation, we mutate the firstline
2797 // twice-- once from the original, and once from the previous.
2798 for (size_t iteration = 0; iteration < arraysize_squared; ++iteration) {
2799 SCOPED_TRACE("Original firstline: \"HTTP/1.0 200 reason phrase\"");
2800 BalsaHeaders headers = CreateHTTPHeaders(true,
2801 "HTTP/1.0 200 reason phrase\r\n"
2802 "content-length: 0\r\n"
2803 "\r\n");
2804 ASSERT_THAT(headers.first_line(), StrEq("HTTP/1.0 200 reason phrase"));
2805
2806 {
2807 int first = iteration / ABSL_ARRAYSIZE(response_reason_phrases);
2808 const char* response_reason_phrase_first = response_reason_phrases[first];
2809 std::string expected_new_firstline =
2810 absl::StrFormat("HTTP/1.0 200 %s", response_reason_phrase_first);
2811 SCOPED_TRACE(absl::StrFormat("Then set response_reason_phrase(\"%s\")",
2812 response_reason_phrase_first));
2813
2814 headers.SetResponseReasonPhrase(response_reason_phrase_first);
2815 EXPECT_THAT(headers.first_line(),
2816 StrEq(absl::StrFormat("HTTP/1.0 200 %s",
2817 response_reason_phrase_first)));
2818 EXPECT_THAT(headers.response_version(), StrEq("HTTP/1.0"));
2819 EXPECT_THAT(headers.response_code(), StrEq("200"));
2820 EXPECT_THAT(headers.response_reason_phrase(),
2821 StrEq(response_reason_phrase_first));
2822 }
2823
2824 // Note that each iteration of the outer loop causes the headers to be left
2825 // in a different state. Nothing wrong with that, but we should use each of
2826 // these states, and try each of our scenarios again. This inner loop does
2827 // that.
2828 {
2829 int second = iteration % ABSL_ARRAYSIZE(response_reason_phrases);
2830 const char* response_reason_phrase_second =
2831 response_reason_phrases[second];
2832 std::string expected_new_firstline =
2833 absl::StrFormat("HTTP/1.0 200 %s", response_reason_phrase_second);
2834 SCOPED_TRACE(absl::StrFormat("Then set response_reason_phrase(\"%s\")",
2835 response_reason_phrase_second));
2836
2837 headers.SetResponseReasonPhrase(response_reason_phrase_second);
2838 EXPECT_THAT(headers.first_line(),
2839 StrEq(absl::StrFormat("HTTP/1.0 200 %s",
2840 response_reason_phrase_second)));
2841 EXPECT_THAT(headers.response_version(), StrEq("HTTP/1.0"));
2842 EXPECT_THAT(headers.response_code(), StrEq("200"));
2843 EXPECT_THAT(headers.response_reason_phrase(),
2844 StrEq(response_reason_phrase_second));
2845 }
2846 }
2847 }
2848
TEST(BalsaHeaders,TestSetResponseVersionWithNoInitialFirstline)2849 TEST(BalsaHeaders, TestSetResponseVersionWithNoInitialFirstline) {
2850 BalsaHeaders balsa_headers;
2851 balsa_headers.SetResponseVersion("HTTP/1.1");
2852 EXPECT_THAT(balsa_headers.first_line(), StrEq("HTTP/1.1 "));
2853 EXPECT_THAT(balsa_headers.response_version(), StrEq("HTTP/1.1"));
2854 EXPECT_TRUE(balsa_headers.response_code().empty());
2855 EXPECT_TRUE(balsa_headers.response_reason_phrase().empty());
2856 }
2857
2858 // Testing each of 9 combinations separately was taking up way too much of this
2859 // file (not to mention the inordinate amount of stupid code duplication), thus
2860 // this test tests all 9 combinations of smaller, equal, and larger in one
2861 // place.
TEST(BalsaHeaders,TestSetResponseVersion)2862 TEST(BalsaHeaders, TestSetResponseVersion) {
2863 const char* response_versions[] = {
2864 "ABCD/123",
2865 "ABCD",
2866 "ABCD/123456",
2867 };
2868 size_t arraysize_squared =
2869 (ABSL_ARRAYSIZE(response_versions) * ABSL_ARRAYSIZE(response_versions));
2870 // We go through the 9 different permutations of (response_versions choose 2)
2871 // in the loop below. For each permutation, we mutate the firstline twice--
2872 // once from the original, and once from the previous.
2873 for (size_t iteration = 0; iteration < arraysize_squared; ++iteration) {
2874 SCOPED_TRACE("Original firstline: \"HTTP/1.0 200 reason phrase\"");
2875 BalsaHeaders headers = CreateHTTPHeaders(false,
2876 "HTTP/1.0 200 reason phrase\r\n"
2877 "content-length: 0\r\n"
2878 "\r\n");
2879 ASSERT_THAT(headers.first_line(), StrEq("HTTP/1.0 200 reason phrase"));
2880
2881 // This structure guarantees that we'll visit all of the possible
2882 // variations of setting.
2883
2884 {
2885 int first = iteration / ABSL_ARRAYSIZE(response_versions);
2886 const char* response_version_first = response_versions[first];
2887 std::string expected_new_firstline =
2888 absl::StrFormat("%s 200 reason phrase", response_version_first);
2889 SCOPED_TRACE(absl::StrFormat("Then set response_version(\"%s\")",
2890 response_version_first));
2891
2892 headers.SetResponseVersion(response_version_first);
2893 EXPECT_THAT(headers.first_line(), StrEq(expected_new_firstline));
2894 EXPECT_THAT(headers.response_version(), StrEq(response_version_first));
2895 EXPECT_THAT(headers.response_code(), StrEq("200"));
2896 EXPECT_THAT(headers.response_reason_phrase(), StrEq("reason phrase"));
2897 }
2898 {
2899 int second = iteration % ABSL_ARRAYSIZE(response_versions);
2900 const char* response_version_second = response_versions[second];
2901 std::string expected_new_firstline =
2902 absl::StrFormat("%s 200 reason phrase", response_version_second);
2903 SCOPED_TRACE(absl::StrFormat("Then set response_version(\"%s\")",
2904 response_version_second));
2905
2906 headers.SetResponseVersion(response_version_second);
2907 EXPECT_THAT(headers.first_line(), StrEq(expected_new_firstline));
2908 EXPECT_THAT(headers.response_version(), StrEq(response_version_second));
2909 EXPECT_THAT(headers.response_code(), StrEq("200"));
2910 EXPECT_THAT(headers.response_reason_phrase(), StrEq("reason phrase"));
2911 }
2912 }
2913 }
2914
TEST(BalsaHeaders,TestSetResponseReasonAndVersionWithNoInitialFirstline)2915 TEST(BalsaHeaders, TestSetResponseReasonAndVersionWithNoInitialFirstline) {
2916 BalsaHeaders headers;
2917 headers.SetResponseVersion("HTTP/1.1");
2918 headers.SetResponseReasonPhrase("don't need a reason");
2919 EXPECT_THAT(headers.first_line(), StrEq("HTTP/1.1 don't need a reason"));
2920 EXPECT_THAT(headers.response_version(), StrEq("HTTP/1.1"));
2921 EXPECT_TRUE(headers.response_code().empty());
2922 EXPECT_THAT(headers.response_reason_phrase(), StrEq("don't need a reason"));
2923 }
2924
TEST(BalsaHeaders,TestSetResponseCodeWithNoInitialFirstline)2925 TEST(BalsaHeaders, TestSetResponseCodeWithNoInitialFirstline) {
2926 BalsaHeaders balsa_headers;
2927 balsa_headers.SetParsedResponseCodeAndUpdateFirstline(2002);
2928 EXPECT_THAT(balsa_headers.first_line(), StrEq(" 2002 "));
2929 EXPECT_TRUE(balsa_headers.response_version().empty());
2930 EXPECT_THAT(balsa_headers.response_code(), StrEq("2002"));
2931 EXPECT_TRUE(balsa_headers.response_reason_phrase().empty());
2932 EXPECT_THAT(balsa_headers.parsed_response_code(), Eq(2002));
2933 }
2934
TEST(BalsaHeaders,TestSetParsedResponseCode)2935 TEST(BalsaHeaders, TestSetParsedResponseCode) {
2936 BalsaHeaders balsa_headers;
2937 balsa_headers.set_parsed_response_code(std::numeric_limits<int>::max());
2938 EXPECT_THAT(balsa_headers.parsed_response_code(),
2939 Eq(std::numeric_limits<int>::max()));
2940 }
2941
TEST(BalsaHeaders,TestSetResponseCode)2942 TEST(BalsaHeaders, TestSetResponseCode) {
2943 const char* response_codes[] = {
2944 "200"
2945 "23",
2946 "200200",
2947 };
2948 size_t arraysize_squared =
2949 (ABSL_ARRAYSIZE(response_codes) * ABSL_ARRAYSIZE(response_codes));
2950 // We go through the 9 different permutations of (response_codes choose 2)
2951 // in the loop below. For each permutation, we mutate the firstline twice--
2952 // once from the original, and once from the previous.
2953 for (size_t iteration = 0; iteration < arraysize_squared; ++iteration) {
2954 SCOPED_TRACE("Original firstline: \"HTTP/1.0 200 reason phrase\"");
2955 BalsaHeaders headers = CreateHTTPHeaders(false,
2956 "HTTP/1.0 200 reason phrase\r\n"
2957 "content-length: 0\r\n"
2958 "\r\n");
2959 ASSERT_THAT(headers.first_line(), StrEq("HTTP/1.0 200 reason phrase"));
2960
2961 // This structure guarantees that we'll visit all of the possible
2962 // variations of setting.
2963
2964 {
2965 int first = iteration / ABSL_ARRAYSIZE(response_codes);
2966 const char* response_code_first = response_codes[first];
2967 std::string expected_new_firstline =
2968 absl::StrFormat("HTTP/1.0 %s reason phrase", response_code_first);
2969 SCOPED_TRACE(absl::StrFormat("Then set response_code(\"%s\")",
2970 response_code_first));
2971
2972 headers.SetResponseCode(response_code_first);
2973
2974 EXPECT_THAT(headers.first_line(), StrEq(expected_new_firstline));
2975 EXPECT_THAT(headers.response_version(), StrEq("HTTP/1.0"));
2976 EXPECT_THAT(headers.response_code(), StrEq(response_code_first));
2977 EXPECT_THAT(headers.response_reason_phrase(), StrEq("reason phrase"));
2978 }
2979 {
2980 int second = iteration % ABSL_ARRAYSIZE(response_codes);
2981 const char* response_code_second = response_codes[second];
2982 std::string expected_new_secondline =
2983 absl::StrFormat("HTTP/1.0 %s reason phrase", response_code_second);
2984 SCOPED_TRACE(absl::StrFormat("Then set response_code(\"%s\")",
2985 response_code_second));
2986
2987 headers.SetResponseCode(response_code_second);
2988
2989 EXPECT_THAT(headers.first_line(), StrEq(expected_new_secondline));
2990 EXPECT_THAT(headers.response_version(), StrEq("HTTP/1.0"));
2991 EXPECT_THAT(headers.response_code(), StrEq(response_code_second));
2992 EXPECT_THAT(headers.response_reason_phrase(), StrEq("reason phrase"));
2993 }
2994 }
2995 }
2996
TEST(BalsaHeaders,TestAppendToHeader)2997 TEST(BalsaHeaders, TestAppendToHeader) {
2998 // Test the basic case of appending to a header.
2999 BalsaHeaders headers;
3000 headers.AppendHeader("foo", "foo_value");
3001 headers.AppendHeader("bar", "bar_value");
3002 headers.AppendToHeader("foo", "foo_value2");
3003
3004 EXPECT_THAT(headers.GetHeader("foo"), StrEq("foo_value,foo_value2"));
3005 EXPECT_THAT(headers.GetHeader("bar"), StrEq("bar_value"));
3006 }
3007
TEST(BalsaHeaders,TestInitialAppend)3008 TEST(BalsaHeaders, TestInitialAppend) {
3009 // Test that AppendToHeader works properly when the header did not already
3010 // exist.
3011 BalsaHeaders headers;
3012 headers.AppendToHeader("foo", "foo_value");
3013 EXPECT_THAT(headers.GetHeader("foo"), StrEq("foo_value"));
3014 headers.AppendToHeader("foo", "foo_value2");
3015 EXPECT_THAT(headers.GetHeader("foo"), StrEq("foo_value,foo_value2"));
3016 }
3017
TEST(BalsaHeaders,TestAppendAndRemove)3018 TEST(BalsaHeaders, TestAppendAndRemove) {
3019 // Test that AppendToHeader works properly with removing.
3020 BalsaHeaders headers;
3021 headers.AppendToHeader("foo", "foo_value");
3022 EXPECT_THAT(headers.GetHeader("foo"), StrEq("foo_value"));
3023 headers.AppendToHeader("foo", "foo_value2");
3024 EXPECT_THAT(headers.GetHeader("foo"), StrEq("foo_value,foo_value2"));
3025 headers.RemoveAllOfHeader("foo");
3026 headers.AppendToHeader("foo", "foo_value3");
3027 EXPECT_THAT(headers.GetHeader("foo"), StrEq("foo_value3"));
3028 headers.AppendToHeader("foo", "foo_value4");
3029 EXPECT_THAT(headers.GetHeader("foo"), StrEq("foo_value3,foo_value4"));
3030 }
3031
TEST(BalsaHeaders,TestAppendToHeaderWithCommaAndSpace)3032 TEST(BalsaHeaders, TestAppendToHeaderWithCommaAndSpace) {
3033 // Test the basic case of appending to a header with comma and space.
3034 BalsaHeaders headers;
3035 headers.AppendHeader("foo", "foo_value");
3036 headers.AppendHeader("bar", "bar_value");
3037 headers.AppendToHeaderWithCommaAndSpace("foo", "foo_value2");
3038
3039 EXPECT_THAT(headers.GetHeader("foo"), StrEq("foo_value, foo_value2"));
3040 EXPECT_THAT(headers.GetHeader("bar"), StrEq("bar_value"));
3041 }
3042
TEST(BalsaHeaders,TestInitialAppendWithCommaAndSpace)3043 TEST(BalsaHeaders, TestInitialAppendWithCommaAndSpace) {
3044 // Test that AppendToHeadeWithCommaAndSpace works properly when the
3045 // header did not already exist.
3046 BalsaHeaders headers;
3047 headers.AppendToHeaderWithCommaAndSpace("foo", "foo_value");
3048 EXPECT_THAT(headers.GetHeader("foo"), StrEq("foo_value"));
3049 headers.AppendToHeaderWithCommaAndSpace("foo", "foo_value2");
3050 EXPECT_THAT(headers.GetHeader("foo"), StrEq("foo_value, foo_value2"));
3051 }
3052
TEST(BalsaHeaders,TestAppendWithCommaAndSpaceAndRemove)3053 TEST(BalsaHeaders, TestAppendWithCommaAndSpaceAndRemove) {
3054 // Test that AppendToHeadeWithCommaAndSpace works properly with removing.
3055 BalsaHeaders headers;
3056 headers.AppendToHeaderWithCommaAndSpace("foo", "foo_value");
3057 EXPECT_THAT(headers.GetHeader("foo"), StrEq("foo_value"));
3058 headers.AppendToHeaderWithCommaAndSpace("foo", "foo_value2");
3059 EXPECT_THAT(headers.GetHeader("foo"), StrEq("foo_value, foo_value2"));
3060 headers.RemoveAllOfHeader("foo");
3061 headers.AppendToHeaderWithCommaAndSpace("foo", "foo_value3");
3062 EXPECT_THAT(headers.GetHeader("foo"), StrEq("foo_value3"));
3063 headers.AppendToHeaderWithCommaAndSpace("foo", "foo_value4");
3064 EXPECT_THAT(headers.GetHeader("foo"), StrEq("foo_value3, foo_value4"));
3065 }
3066
TEST(BalsaHeaders,SetContentLength)3067 TEST(BalsaHeaders, SetContentLength) {
3068 // Test that SetContentLength correctly sets the content-length header and
3069 // sets the content length status.
3070 BalsaHeaders headers;
3071 headers.SetContentLength(10);
3072 EXPECT_THAT(headers.GetHeader("Content-length"), StrEq("10"));
3073 EXPECT_EQ(BalsaHeadersEnums::VALID_CONTENT_LENGTH,
3074 headers.content_length_status());
3075 EXPECT_TRUE(headers.content_length_valid());
3076
3077 // Test overwriting the content-length.
3078 headers.SetContentLength(0);
3079 EXPECT_THAT(headers.GetHeader("Content-length"), StrEq("0"));
3080 EXPECT_EQ(BalsaHeadersEnums::VALID_CONTENT_LENGTH,
3081 headers.content_length_status());
3082 EXPECT_TRUE(headers.content_length_valid());
3083
3084 // Make sure there is only one header line after the overwrite.
3085 BalsaHeaders::const_header_lines_iterator iter =
3086 headers.GetHeaderPosition("Content-length");
3087 EXPECT_EQ(headers.lines().begin(), iter);
3088 EXPECT_EQ(headers.lines().end(), ++iter);
3089
3090 // Test setting the same content-length again, this should be no-op.
3091 headers.SetContentLength(0);
3092 EXPECT_THAT(headers.GetHeader("Content-length"), StrEq("0"));
3093 EXPECT_EQ(BalsaHeadersEnums::VALID_CONTENT_LENGTH,
3094 headers.content_length_status());
3095 EXPECT_TRUE(headers.content_length_valid());
3096
3097 // Make sure the number of header lines didn't change.
3098 iter = headers.GetHeaderPosition("Content-length");
3099 EXPECT_EQ(headers.lines().begin(), iter);
3100 EXPECT_EQ(headers.lines().end(), ++iter);
3101 }
3102
TEST(BalsaHeaders,ToggleChunkedEncoding)3103 TEST(BalsaHeaders, ToggleChunkedEncoding) {
3104 // Test that SetTransferEncodingToChunkedAndClearContentLength correctly adds
3105 // chunk-encoding header and sets the transfer_encoding_is_chunked_
3106 // flag.
3107 BalsaHeaders headers;
3108 headers.SetTransferEncodingToChunkedAndClearContentLength();
3109 EXPECT_EQ("chunked", headers.GetAllOfHeaderAsString("Transfer-Encoding"));
3110 EXPECT_TRUE(headers.HasHeadersWithPrefix("Transfer-Encoding"));
3111 EXPECT_TRUE(headers.HasHeadersWithPrefix("transfer-encoding"));
3112 EXPECT_TRUE(headers.HasHeadersWithPrefix("transfer"));
3113 EXPECT_TRUE(headers.transfer_encoding_is_chunked());
3114
3115 // Set it to the same value, nothing should change.
3116 headers.SetTransferEncodingToChunkedAndClearContentLength();
3117 EXPECT_EQ("chunked", headers.GetAllOfHeaderAsString("Transfer-Encoding"));
3118 EXPECT_TRUE(headers.HasHeadersWithPrefix("Transfer-Encoding"));
3119 EXPECT_TRUE(headers.HasHeadersWithPrefix("transfer-encoding"));
3120 EXPECT_TRUE(headers.HasHeadersWithPrefix("transfer"));
3121 EXPECT_TRUE(headers.transfer_encoding_is_chunked());
3122 BalsaHeaders::const_header_lines_iterator iter =
3123 headers.GetHeaderPosition("Transfer-Encoding");
3124 EXPECT_EQ(headers.lines().begin(), iter);
3125 EXPECT_EQ(headers.lines().end(), ++iter);
3126
3127 // Removes the chunked encoding, and there should be no transfer-encoding
3128 // headers left.
3129 headers.SetNoTransferEncoding();
3130 EXPECT_FALSE(headers.HasHeader("Transfer-Encoding"));
3131 EXPECT_FALSE(headers.HasHeadersWithPrefix("Transfer-Encoding"));
3132 EXPECT_FALSE(headers.HasHeadersWithPrefix("transfer-encoding"));
3133 EXPECT_FALSE(headers.HasHeadersWithPrefix("transfer"));
3134 EXPECT_FALSE(headers.transfer_encoding_is_chunked());
3135 EXPECT_EQ(headers.lines().end(), headers.lines().begin());
3136
3137 // Clear chunked again, this should be a no-op and the header should not
3138 // change.
3139 headers.SetNoTransferEncoding();
3140 EXPECT_FALSE(headers.HasHeader("Transfer-Encoding"));
3141 EXPECT_FALSE(headers.HasHeadersWithPrefix("Transfer-Encoding"));
3142 EXPECT_FALSE(headers.HasHeadersWithPrefix("transfer-encoding"));
3143 EXPECT_FALSE(headers.HasHeadersWithPrefix("transfer"));
3144 EXPECT_FALSE(headers.transfer_encoding_is_chunked());
3145 EXPECT_EQ(headers.lines().end(), headers.lines().begin());
3146 }
3147
TEST(BalsaHeaders,SetNoTransferEncodingByRemoveHeader)3148 TEST(BalsaHeaders, SetNoTransferEncodingByRemoveHeader) {
3149 // Tests that calling Remove() methods to clear the Transfer-Encoding
3150 // header correctly resets transfer_encoding_is_chunked_ internal state.
3151 BalsaHeaders headers;
3152 headers.SetTransferEncodingToChunkedAndClearContentLength();
3153 headers.RemoveAllOfHeader("Transfer-Encoding");
3154 EXPECT_FALSE(headers.transfer_encoding_is_chunked());
3155
3156 headers.SetTransferEncodingToChunkedAndClearContentLength();
3157 std::vector<absl::string_view> headers_to_remove;
3158 headers_to_remove.emplace_back("Transfer-Encoding");
3159 headers.RemoveAllOfHeaderInList(headers_to_remove);
3160 EXPECT_FALSE(headers.transfer_encoding_is_chunked());
3161
3162 headers.SetTransferEncodingToChunkedAndClearContentLength();
3163 headers.RemoveAllHeadersWithPrefix("Transfer");
3164 EXPECT_FALSE(headers.transfer_encoding_is_chunked());
3165 }
3166
TEST(BalsaHeaders,ClearContentLength)3167 TEST(BalsaHeaders, ClearContentLength) {
3168 // Test that ClearContentLength() removes the content-length header and
3169 // resets content_length_status().
3170 BalsaHeaders headers;
3171 headers.SetContentLength(10);
3172 headers.ClearContentLength();
3173 EXPECT_FALSE(headers.HasHeader("Content-length"));
3174 EXPECT_EQ(BalsaHeadersEnums::NO_CONTENT_LENGTH,
3175 headers.content_length_status());
3176 EXPECT_FALSE(headers.content_length_valid());
3177
3178 // Clear it again; nothing should change.
3179 headers.ClearContentLength();
3180 EXPECT_FALSE(headers.HasHeader("Content-length"));
3181 EXPECT_EQ(BalsaHeadersEnums::NO_CONTENT_LENGTH,
3182 headers.content_length_status());
3183 EXPECT_FALSE(headers.content_length_valid());
3184
3185 // Set chunked encoding and test that ClearContentLength() has no effect.
3186 headers.SetTransferEncodingToChunkedAndClearContentLength();
3187 headers.ClearContentLength();
3188 EXPECT_EQ("chunked", headers.GetAllOfHeaderAsString("Transfer-Encoding"));
3189 EXPECT_TRUE(headers.transfer_encoding_is_chunked());
3190 BalsaHeaders::const_header_lines_iterator iter =
3191 headers.GetHeaderPosition("Transfer-Encoding");
3192 EXPECT_EQ(headers.lines().begin(), iter);
3193 EXPECT_EQ(headers.lines().end(), ++iter);
3194
3195 // Remove chunked encoding, and verify that the state is the same as after
3196 // ClearContentLength().
3197 headers.SetNoTransferEncoding();
3198 EXPECT_EQ(BalsaHeadersEnums::NO_CONTENT_LENGTH,
3199 headers.content_length_status());
3200 EXPECT_FALSE(headers.content_length_valid());
3201 }
3202
TEST(BalsaHeaders,ClearContentLengthByRemoveHeader)3203 TEST(BalsaHeaders, ClearContentLengthByRemoveHeader) {
3204 // Test that calling Remove() methods to clear the content-length header
3205 // correctly resets internal content length fields.
3206 BalsaHeaders headers;
3207 headers.SetContentLength(10);
3208 headers.RemoveAllOfHeader("Content-Length");
3209 EXPECT_EQ(BalsaHeadersEnums::NO_CONTENT_LENGTH,
3210 headers.content_length_status());
3211 EXPECT_EQ(0u, headers.content_length());
3212 EXPECT_FALSE(headers.content_length_valid());
3213
3214 headers.SetContentLength(11);
3215 std::vector<absl::string_view> headers_to_remove;
3216 headers_to_remove.emplace_back("Content-Length");
3217 headers.RemoveAllOfHeaderInList(headers_to_remove);
3218 EXPECT_EQ(BalsaHeadersEnums::NO_CONTENT_LENGTH,
3219 headers.content_length_status());
3220 EXPECT_EQ(0u, headers.content_length());
3221 EXPECT_FALSE(headers.content_length_valid());
3222
3223 headers.SetContentLength(12);
3224 headers.RemoveAllHeadersWithPrefix("Content");
3225 EXPECT_EQ(BalsaHeadersEnums::NO_CONTENT_LENGTH,
3226 headers.content_length_status());
3227 EXPECT_EQ(0u, headers.content_length());
3228 EXPECT_FALSE(headers.content_length_valid());
3229 }
3230
3231 // Chunk-encoding an identity-coded BalsaHeaders removes the identity-coding.
TEST(BalsaHeaders,IdentityCodingToChunked)3232 TEST(BalsaHeaders, IdentityCodingToChunked) {
3233 std::string message =
3234 "HTTP/1.1 200 OK\r\n"
3235 "Transfer-Encoding: identity\r\n\r\n";
3236 BalsaHeaders headers;
3237 BalsaFrame balsa_frame;
3238 balsa_frame.set_is_request(false);
3239 balsa_frame.set_balsa_headers(&headers);
3240 EXPECT_EQ(message.size(),
3241 balsa_frame.ProcessInput(message.data(), message.size()));
3242
3243 EXPECT_TRUE(headers.is_framed_by_connection_close());
3244 EXPECT_FALSE(headers.transfer_encoding_is_chunked());
3245 EXPECT_THAT(headers.GetAllOfHeader("Transfer-Encoding"),
3246 ElementsAre("identity"));
3247
3248 headers.SetTransferEncodingToChunkedAndClearContentLength();
3249
3250 EXPECT_FALSE(headers.is_framed_by_connection_close());
3251 EXPECT_TRUE(headers.transfer_encoding_is_chunked());
3252 EXPECT_THAT(headers.GetAllOfHeader("Transfer-Encoding"),
3253 ElementsAre("chunked"));
3254 }
3255
TEST(BalsaHeaders,SwitchContentLengthToChunk)3256 TEST(BalsaHeaders, SwitchContentLengthToChunk) {
3257 // Test that a header originally with content length header is correctly
3258 // switched to using chunk encoding.
3259 BalsaHeaders headers;
3260 headers.SetContentLength(10);
3261 EXPECT_THAT(headers.GetHeader("Content-length"), StrEq("10"));
3262 EXPECT_EQ(BalsaHeadersEnums::VALID_CONTENT_LENGTH,
3263 headers.content_length_status());
3264 EXPECT_TRUE(headers.content_length_valid());
3265
3266 headers.SetTransferEncodingToChunkedAndClearContentLength();
3267 EXPECT_EQ("chunked", headers.GetAllOfHeaderAsString("Transfer-Encoding"));
3268 EXPECT_TRUE(headers.transfer_encoding_is_chunked());
3269 EXPECT_FALSE(headers.HasHeader("Content-length"));
3270 EXPECT_EQ(BalsaHeadersEnums::NO_CONTENT_LENGTH,
3271 headers.content_length_status());
3272 EXPECT_FALSE(headers.content_length_valid());
3273 }
3274
TEST(BalsaHeaders,SwitchChunkedToContentLength)3275 TEST(BalsaHeaders, SwitchChunkedToContentLength) {
3276 // Test that a header originally with chunk encoding is correctly
3277 // switched to using content length.
3278 BalsaHeaders headers;
3279 headers.SetTransferEncodingToChunkedAndClearContentLength();
3280 EXPECT_EQ("chunked", headers.GetAllOfHeaderAsString("Transfer-Encoding"));
3281 EXPECT_TRUE(headers.transfer_encoding_is_chunked());
3282 EXPECT_FALSE(headers.HasHeader("Content-length"));
3283 EXPECT_EQ(BalsaHeadersEnums::NO_CONTENT_LENGTH,
3284 headers.content_length_status());
3285 EXPECT_FALSE(headers.content_length_valid());
3286
3287 headers.SetContentLength(10);
3288 EXPECT_THAT(headers.GetHeader("Content-length"), StrEq("10"));
3289 EXPECT_EQ(BalsaHeadersEnums::VALID_CONTENT_LENGTH,
3290 headers.content_length_status());
3291 EXPECT_TRUE(headers.content_length_valid());
3292 EXPECT_FALSE(headers.HasHeader("Transfer-Encoding"));
3293 EXPECT_FALSE(headers.transfer_encoding_is_chunked());
3294 }
3295
TEST(BalsaHeaders,OneHundredResponseMessagesNoFramedByClose)3296 TEST(BalsaHeaders, OneHundredResponseMessagesNoFramedByClose) {
3297 BalsaHeaders headers;
3298 headers.SetResponseFirstline("HTTP/1.1", 100, "Continue");
3299 EXPECT_FALSE(headers.is_framed_by_connection_close());
3300 }
3301
TEST(BalsaHeaders,TwoOhFourResponseMessagesNoFramedByClose)3302 TEST(BalsaHeaders, TwoOhFourResponseMessagesNoFramedByClose) {
3303 BalsaHeaders headers;
3304 headers.SetResponseFirstline("HTTP/1.1", 204, "Continue");
3305 EXPECT_FALSE(headers.is_framed_by_connection_close());
3306 }
3307
TEST(BalsaHeaders,ThreeOhFourResponseMessagesNoFramedByClose)3308 TEST(BalsaHeaders, ThreeOhFourResponseMessagesNoFramedByClose) {
3309 BalsaHeaders headers;
3310 headers.SetResponseFirstline("HTTP/1.1", 304, "Continue");
3311 EXPECT_FALSE(headers.is_framed_by_connection_close());
3312 }
3313
TEST(BalsaHeaders,InvalidCharInHeaderValue)3314 TEST(BalsaHeaders, InvalidCharInHeaderValue) {
3315 std::string message =
3316 "GET http://www.256.com/foo HTTP/1.1\r\n"
3317 "Host: \x01\x01www.265.com\r\n"
3318 "\r\n";
3319 BalsaHeaders headers = CreateHTTPHeaders(true, message);
3320 EXPECT_EQ("www.265.com", headers.GetHeader("Host"));
3321 SimpleBuffer buffer;
3322 headers.WriteHeaderAndEndingToBuffer(&buffer);
3323 message.replace(message.find_first_of(0x1), 2, "");
3324 EXPECT_EQ(message, buffer.GetReadableRegion());
3325 }
3326
TEST(BalsaHeaders,CarriageReturnAtStartOfLine)3327 TEST(BalsaHeaders, CarriageReturnAtStartOfLine) {
3328 std::string message =
3329 "GET /foo HTTP/1.1\r\n"
3330 "Host: www.265.com\r\n"
3331 "Foo: bar\r\n"
3332 "\rX-User-Ip: 1.2.3.4\r\n"
3333 "\r\n";
3334 BalsaHeaders headers;
3335 BalsaFrame balsa_frame;
3336 balsa_frame.set_is_request(true);
3337 balsa_frame.set_balsa_headers(&headers);
3338 EXPECT_EQ(message.size(),
3339 balsa_frame.ProcessInput(message.data(), message.size()));
3340 EXPECT_EQ(BalsaFrameEnums::INVALID_HEADER_FORMAT, balsa_frame.ErrorCode());
3341 EXPECT_TRUE(balsa_frame.Error());
3342 }
3343
TEST(BalsaHeaders,CheckEmpty)3344 TEST(BalsaHeaders, CheckEmpty) {
3345 BalsaHeaders headers;
3346 EXPECT_TRUE(headers.IsEmpty());
3347 }
3348
TEST(BalsaHeaders,CheckNonEmpty)3349 TEST(BalsaHeaders, CheckNonEmpty) {
3350 BalsaHeaders headers;
3351 BalsaHeadersTestPeer::WriteFromFramer(&headers, "a b c", 5);
3352 EXPECT_FALSE(headers.IsEmpty());
3353 }
3354
TEST(BalsaHeaders,ForEachHeader)3355 TEST(BalsaHeaders, ForEachHeader) {
3356 BalsaHeaders headers;
3357 headers.AppendHeader(":host", "SomeHost");
3358 headers.AppendHeader("key", "val1,val2val2,val2,val3");
3359 headers.AppendHeader("key", "val4val5val6");
3360 headers.AppendHeader("key", "val11 val12");
3361 headers.AppendHeader("key", "v val13");
3362 headers.AppendHeader("key", "val7");
3363 headers.AppendHeader("key", "");
3364 headers.AppendHeader("key", "val8 , val9 ,, val10");
3365 headers.AppendHeader("key", " val14 ");
3366 headers.AppendHeader("key2", "val15");
3367 headers.AppendHeader("key", "Val16");
3368 headers.AppendHeader("key", "foo, Val17, bar");
3369 headers.AppendHeader("date", "2 Jan 1970");
3370 headers.AppendHeader("AcceptEncoding", "MyFavoriteEncoding");
3371
3372 {
3373 std::string result;
3374 EXPECT_TRUE(headers.ForEachHeader(
3375 [&result](const absl::string_view key, absl::string_view value) {
3376 result.append("<")
3377 .append(key.data(), key.size())
3378 .append("> = <")
3379 .append(value.data(), value.size())
3380 .append(">\n");
3381 return true;
3382 }));
3383
3384 EXPECT_EQ(result,
3385 "<:host> = <SomeHost>\n"
3386 "<key> = <val1,val2val2,val2,val3>\n"
3387 "<key> = <val4val5val6>\n"
3388 "<key> = <val11 val12>\n"
3389 "<key> = <v val13>\n"
3390 "<key> = <val7>\n"
3391 "<key> = <>\n"
3392 "<key> = <val8 , val9 ,, val10>\n"
3393 "<key> = < val14 >\n"
3394 "<key2> = <val15>\n"
3395 "<key> = <Val16>\n"
3396 "<key> = <foo, Val17, bar>\n"
3397 "<date> = <2 Jan 1970>\n"
3398 "<AcceptEncoding> = <MyFavoriteEncoding>\n");
3399 }
3400
3401 {
3402 std::string result;
3403 EXPECT_FALSE(headers.ForEachHeader(
3404 [&result](const absl::string_view key, absl::string_view value) {
3405 result.append("<")
3406 .append(key.data(), key.size())
3407 .append("> = <")
3408 .append(value.data(), value.size())
3409 .append(">\n");
3410 return !value.empty();
3411 }));
3412
3413 EXPECT_EQ(result,
3414 "<:host> = <SomeHost>\n"
3415 "<key> = <val1,val2val2,val2,val3>\n"
3416 "<key> = <val4val5val6>\n"
3417 "<key> = <val11 val12>\n"
3418 "<key> = <v val13>\n"
3419 "<key> = <val7>\n"
3420 "<key> = <>\n");
3421 }
3422 }
3423
TEST(BalsaHeaders,WriteToBufferWithLowerCasedHeaderKey)3424 TEST(BalsaHeaders, WriteToBufferWithLowerCasedHeaderKey) {
3425 BalsaHeaders headers;
3426 headers.SetRequestFirstlineFromStringPieces("GET", "/", "HTTP/1.0");
3427 headers.AppendHeader("Key1", "value1");
3428 headers.AppendHeader("Key2", "value2");
3429 std::string expected_lower_case =
3430 "GET / HTTP/1.0\r\n"
3431 "key1: value1\r\n"
3432 "key2: value2\r\n";
3433 std::string expected_lower_case_with_end =
3434 "GET / HTTP/1.0\r\n"
3435 "key1: value1\r\n"
3436 "key2: value2\r\n\r\n";
3437 std::string expected_upper_case =
3438 "GET / HTTP/1.0\r\n"
3439 "Key1: value1\r\n"
3440 "Key2: value2\r\n";
3441 std::string expected_upper_case_with_end =
3442 "GET / HTTP/1.0\r\n"
3443 "Key1: value1\r\n"
3444 "Key2: value2\r\n\r\n";
3445
3446 SimpleBuffer simple_buffer;
3447 headers.WriteToBuffer(&simple_buffer, BalsaHeaders::CaseOption::kLowercase,
3448 BalsaHeaders::CoalesceOption::kNoCoalesce);
3449 EXPECT_THAT(simple_buffer.GetReadableRegion(), StrEq(expected_lower_case));
3450
3451 simple_buffer.Clear();
3452 headers.WriteToBuffer(&simple_buffer);
3453 EXPECT_THAT(simple_buffer.GetReadableRegion(), StrEq(expected_upper_case));
3454
3455 simple_buffer.Clear();
3456 headers.WriteHeaderAndEndingToBuffer(&simple_buffer);
3457 EXPECT_THAT(simple_buffer.GetReadableRegion(),
3458 StrEq(expected_upper_case_with_end));
3459
3460 simple_buffer.Clear();
3461 headers.WriteHeaderAndEndingToBuffer(
3462 &simple_buffer, BalsaHeaders::CaseOption::kLowercase,
3463 BalsaHeaders::CoalesceOption::kNoCoalesce);
3464 EXPECT_THAT(simple_buffer.GetReadableRegion(),
3465 StrEq(expected_lower_case_with_end));
3466 }
3467
TEST(BalsaHeaders,WriteToBufferWithProperCasedHeaderKey)3468 TEST(BalsaHeaders, WriteToBufferWithProperCasedHeaderKey) {
3469 BalsaHeaders headers;
3470 headers.SetRequestFirstlineFromStringPieces("GET", "/", "HTTP/1.0");
3471 headers.AppendHeader("Te", "value1");
3472 headers.AppendHeader("my-Test-header", "value2");
3473 std::string expected_proper_case =
3474 "GET / HTTP/1.0\r\n"
3475 "TE: value1\r\n"
3476 "My-Test-Header: value2\r\n";
3477 std::string expected_proper_case_with_end =
3478 "GET / HTTP/1.0\r\n"
3479 "TE: value1\r\n"
3480 "My-Test-Header: value2\r\n\r\n";
3481 std::string expected_unmodified =
3482 "GET / HTTP/1.0\r\n"
3483 "Te: value1\r\n"
3484 "my-Test-header: value2\r\n";
3485 std::string expected_unmodified_with_end =
3486 "GET / HTTP/1.0\r\n"
3487 "Te: value1\r\n"
3488 "my-Test-header: value2\r\n\r\n";
3489
3490 SimpleBuffer simple_buffer;
3491 headers.WriteToBuffer(&simple_buffer, BalsaHeaders::CaseOption::kPropercase,
3492 BalsaHeaders::CoalesceOption::kNoCoalesce);
3493 EXPECT_EQ(simple_buffer.GetReadableRegion(), expected_proper_case);
3494
3495 simple_buffer.Clear();
3496 headers.WriteToBuffer(&simple_buffer,
3497 BalsaHeaders::CaseOption::kNoModification,
3498 BalsaHeaders::CoalesceOption::kNoCoalesce);
3499 EXPECT_EQ(simple_buffer.GetReadableRegion(), expected_unmodified);
3500
3501 simple_buffer.Clear();
3502 headers.WriteHeaderAndEndingToBuffer(
3503 &simple_buffer, BalsaHeaders::CaseOption::kNoModification,
3504 BalsaHeaders::CoalesceOption::kNoCoalesce);
3505 EXPECT_EQ(simple_buffer.GetReadableRegion(), expected_unmodified_with_end);
3506
3507 simple_buffer.Clear();
3508 headers.WriteHeaderAndEndingToBuffer(
3509 &simple_buffer, BalsaHeaders::CaseOption::kPropercase,
3510 BalsaHeaders::CoalesceOption::kNoCoalesce);
3511 EXPECT_EQ(simple_buffer.GetReadableRegion(), expected_proper_case_with_end);
3512 }
3513
TEST(BalsaHeadersTest,ToPropercaseTest)3514 TEST(BalsaHeadersTest, ToPropercaseTest) {
3515 EXPECT_EQ(BalsaHeaders::ToPropercase(""), "");
3516 EXPECT_EQ(BalsaHeaders::ToPropercase("Foo"), "Foo");
3517 EXPECT_EQ(BalsaHeaders::ToPropercase("foO"), "Foo");
3518 EXPECT_EQ(BalsaHeaders::ToPropercase("my-test-header"), "My-Test-Header");
3519 EXPECT_EQ(BalsaHeaders::ToPropercase("my--test-header"), "My--Test-Header");
3520 }
3521
TEST(BalsaHeaders,WriteToBufferCoalescingMultivaluedHeaders)3522 TEST(BalsaHeaders, WriteToBufferCoalescingMultivaluedHeaders) {
3523 BalsaHeaders::MultivaluedHeadersSet multivalued_headers;
3524 multivalued_headers.insert("KeY1");
3525 multivalued_headers.insert("another_KEY");
3526
3527 BalsaHeaders headers;
3528 headers.SetRequestFirstlineFromStringPieces("GET", "/", "HTTP/1.0");
3529 headers.AppendHeader("Key1", "value1");
3530 headers.AppendHeader("Key2", "value2");
3531 headers.AppendHeader("Key1", "value11");
3532 headers.AppendHeader("Key2", "value21");
3533 headers.AppendHeader("Key1", "multiples, values, already");
3534 std::string expected_non_coalesced =
3535 "GET / HTTP/1.0\r\n"
3536 "Key1: value1\r\n"
3537 "Key2: value2\r\n"
3538 "Key1: value11\r\n"
3539 "Key2: value21\r\n"
3540 "Key1: multiples, values, already\r\n";
3541 std::string expected_coalesced =
3542 "Key1: value1,value11,multiples, values, already\r\n"
3543 "Key2: value2\r\n"
3544 "Key2: value21\r\n";
3545
3546 SimpleBuffer simple_buffer;
3547 headers.WriteToBuffer(&simple_buffer);
3548 EXPECT_EQ(simple_buffer.GetReadableRegion(), expected_non_coalesced);
3549
3550 simple_buffer.Clear();
3551 headers.WriteToBufferCoalescingMultivaluedHeaders(
3552 &simple_buffer, multivalued_headers,
3553 BalsaHeaders::CaseOption::kNoModification);
3554 EXPECT_EQ(simple_buffer.GetReadableRegion(), expected_coalesced);
3555 }
3556
TEST(BalsaHeaders,WriteToBufferCoalescingMultivaluedHeadersMultiLine)3557 TEST(BalsaHeaders, WriteToBufferCoalescingMultivaluedHeadersMultiLine) {
3558 BalsaHeaders::MultivaluedHeadersSet multivalued_headers;
3559 multivalued_headers.insert("Key 2");
3560 multivalued_headers.insert("key\n 3");
3561
3562 BalsaHeaders headers;
3563 headers.AppendHeader("key1", "value1");
3564 headers.AppendHeader("key 2", "value\n 2");
3565 headers.AppendHeader("key\n 3", "value3");
3566 headers.AppendHeader("key 2", "value 21");
3567 headers.AppendHeader("key 3", "value 33");
3568 std::string expected_non_coalesced =
3569 "\r\n"
3570 "key1: value1\r\n"
3571 "key 2: value\n"
3572 " 2\r\n"
3573 "key\n"
3574 " 3: value3\r\n"
3575 "key 2: value 21\r\n"
3576 "key 3: value 33\r\n";
3577
3578 SimpleBuffer simple_buffer;
3579 headers.WriteToBuffer(&simple_buffer);
3580 EXPECT_EQ(simple_buffer.GetReadableRegion(), expected_non_coalesced);
3581
3582 std::string expected_coalesced =
3583 "key1: value1\r\n"
3584 "key 2: value\n"
3585 " 2,value 21\r\n"
3586 "key\n"
3587 " 3: value3\r\n"
3588 "key 3: value 33\r\n";
3589
3590 simple_buffer.Clear();
3591 headers.WriteToBufferCoalescingMultivaluedHeaders(
3592 &simple_buffer, multivalued_headers,
3593 BalsaHeaders::CaseOption::kNoModification);
3594 EXPECT_EQ(simple_buffer.GetReadableRegion(), expected_coalesced);
3595 }
3596
TEST(BalsaHeaders,WriteToBufferCoalescingEnvoyHeaders)3597 TEST(BalsaHeaders, WriteToBufferCoalescingEnvoyHeaders) {
3598 BalsaHeaders headers;
3599 headers.SetRequestFirstlineFromStringPieces("GET", "/", "HTTP/1.0");
3600 headers.AppendHeader("User-Agent", "UserAgent1");
3601 headers.AppendHeader("Key2", "value2");
3602 headers.AppendHeader("USER-AGENT", "UA2");
3603 headers.AppendHeader("Set-Cookie", "Cookie1=aaa");
3604 headers.AppendHeader("user-agent", "agent3");
3605 headers.AppendHeader("Set-Cookie", "Cookie2=bbb");
3606 std::string expected_non_coalesced =
3607 "GET / HTTP/1.0\r\n"
3608 "User-Agent: UserAgent1\r\n"
3609 "Key2: value2\r\n"
3610 "USER-AGENT: UA2\r\n"
3611 "Set-Cookie: Cookie1=aaa\r\n"
3612 "user-agent: agent3\r\n"
3613 "Set-Cookie: Cookie2=bbb\r\n"
3614 "\r\n";
3615 std::string expected_coalesced =
3616 "GET / HTTP/1.0\r\n"
3617 "User-Agent: UserAgent1,UA2,agent3\r\n"
3618 "Key2: value2\r\n"
3619 "Set-Cookie: Cookie1=aaa\r\n"
3620 "Set-Cookie: Cookie2=bbb\r\n"
3621 "\r\n";
3622
3623 SimpleBuffer simple_buffer;
3624 headers.WriteHeaderAndEndingToBuffer(&simple_buffer);
3625 EXPECT_EQ(simple_buffer.GetReadableRegion(), expected_non_coalesced);
3626
3627 simple_buffer.Clear();
3628 headers.WriteHeaderAndEndingToBuffer(
3629 &simple_buffer, BalsaHeaders::CaseOption::kNoModification,
3630 BalsaHeaders::CoalesceOption::kCoalesce);
3631 EXPECT_EQ(simple_buffer.GetReadableRegion(), expected_coalesced);
3632 }
3633
TEST(BalsaHeadersTest,RemoveLastTokenFromOneLineHeader)3634 TEST(BalsaHeadersTest, RemoveLastTokenFromOneLineHeader) {
3635 BalsaHeaders headers =
3636 CreateHTTPHeaders(true,
3637 "GET /foo HTTP/1.1\r\n"
3638 "Content-Length: 0\r\n"
3639 "Content-Encoding: gzip, 3des, tar, prc\r\n\r\n");
3640
3641 BalsaHeaders::const_header_lines_key_iterator it =
3642 headers.GetIteratorForKey("Content-Encoding");
3643 ASSERT_EQ("gzip, 3des, tar, prc", it->second);
3644 EXPECT_EQ(headers.header_lines_key_end(), ++it);
3645
3646 headers.RemoveLastTokenFromHeaderValue("Content-Encoding");
3647 it = headers.GetIteratorForKey("Content-Encoding");
3648 ASSERT_EQ("gzip, 3des, tar", it->second);
3649 EXPECT_EQ(headers.header_lines_key_end(), ++it);
3650
3651 headers.RemoveLastTokenFromHeaderValue("Content-Encoding");
3652 it = headers.GetIteratorForKey("Content-Encoding");
3653 ASSERT_EQ("gzip, 3des", it->second);
3654 EXPECT_EQ(headers.header_lines_key_end(), ++it);
3655
3656 headers.RemoveLastTokenFromHeaderValue("Content-Encoding");
3657 it = headers.GetIteratorForKey("Content-Encoding");
3658 ASSERT_EQ("gzip", it->second);
3659 EXPECT_EQ(headers.header_lines_key_end(), ++it);
3660
3661 headers.RemoveLastTokenFromHeaderValue("Content-Encoding");
3662
3663 EXPECT_FALSE(headers.HasHeader("Content-Encoding"));
3664 }
3665
TEST(BalsaHeadersTest,RemoveLastTokenFromMultiLineHeader)3666 TEST(BalsaHeadersTest, RemoveLastTokenFromMultiLineHeader) {
3667 BalsaHeaders headers =
3668 CreateHTTPHeaders(true,
3669 "GET /foo HTTP/1.1\r\n"
3670 "Content-Length: 0\r\n"
3671 "Content-Encoding: gzip, 3des\r\n"
3672 "Content-Encoding: tar, prc\r\n\r\n");
3673
3674 BalsaHeaders::const_header_lines_key_iterator it =
3675 headers.GetIteratorForKey("Content-Encoding");
3676 ASSERT_EQ("gzip, 3des", it->second);
3677 ASSERT_EQ("tar, prc", (++it)->second);
3678 ASSERT_EQ(headers.header_lines_key_end(), ++it);
3679
3680 // First, we should start removing tokens from the second line.
3681 headers.RemoveLastTokenFromHeaderValue("Content-Encoding");
3682 it = headers.GetIteratorForKey("Content-Encoding");
3683 ASSERT_EQ("gzip, 3des", it->second);
3684 ASSERT_EQ("tar", (++it)->second);
3685 ASSERT_EQ(headers.header_lines_key_end(), ++it);
3686
3687 // Second line should be entirely removed after all its tokens are gone.
3688 headers.RemoveLastTokenFromHeaderValue("Content-Encoding");
3689 it = headers.GetIteratorForKey("Content-Encoding");
3690 ASSERT_EQ("gzip, 3des", it->second);
3691 ASSERT_EQ(headers.header_lines_key_end(), ++it);
3692
3693 // Now we should be removing the tokens from the first line.
3694 headers.RemoveLastTokenFromHeaderValue("Content-Encoding");
3695 it = headers.GetIteratorForKey("Content-Encoding");
3696 ASSERT_EQ("gzip", it->second);
3697 ASSERT_EQ(headers.header_lines_key_end(), ++it);
3698
3699 headers.RemoveLastTokenFromHeaderValue("Content-Encoding");
3700 EXPECT_FALSE(headers.HasHeader("Content-Encoding"));
3701 }
3702
TEST(BalsaHeadersTest,ResponseCanHaveBody)3703 TEST(BalsaHeadersTest, ResponseCanHaveBody) {
3704 // 1xx, 204 no content and 304 not modified responses can't have bodies.
3705 EXPECT_FALSE(BalsaHeaders::ResponseCanHaveBody(100));
3706 EXPECT_FALSE(BalsaHeaders::ResponseCanHaveBody(101));
3707 EXPECT_FALSE(BalsaHeaders::ResponseCanHaveBody(102));
3708 EXPECT_FALSE(BalsaHeaders::ResponseCanHaveBody(204));
3709 EXPECT_FALSE(BalsaHeaders::ResponseCanHaveBody(304));
3710
3711 // Other responses can have body.
3712 EXPECT_TRUE(BalsaHeaders::ResponseCanHaveBody(200));
3713 EXPECT_TRUE(BalsaHeaders::ResponseCanHaveBody(302));
3714 EXPECT_TRUE(BalsaHeaders::ResponseCanHaveBody(404));
3715 EXPECT_TRUE(BalsaHeaders::ResponseCanHaveBody(502));
3716 }
3717
3718 } // namespace
3719
3720 } // namespace test
3721
3722 } // namespace quiche
3723