xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/common/capsule_test.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 2021 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 #include "quiche/common/capsule.h"
6 
7 #include <cstddef>
8 #include <deque>
9 #include <string>
10 #include <vector>
11 
12 #include "absl/strings/escaping.h"
13 #include "absl/strings/str_cat.h"
14 #include "absl/strings/string_view.h"
15 #include "quiche/common/platform/api/quiche_test.h"
16 #include "quiche/common/quiche_buffer_allocator.h"
17 #include "quiche/common/quiche_ip_address.h"
18 #include "quiche/common/simple_buffer_allocator.h"
19 #include "quiche/common/test_tools/quiche_test_utils.h"
20 #include "quiche/web_transport/web_transport.h"
21 
22 using ::testing::_;
23 using ::testing::InSequence;
24 using ::testing::Return;
25 using ::webtransport::StreamType;
26 
27 namespace quiche {
28 namespace test {
29 
30 class CapsuleParserPeer {
31  public:
buffered_data(CapsuleParser * capsule_parser)32   static std::string* buffered_data(CapsuleParser* capsule_parser) {
33     return &capsule_parser->buffered_data_;
34   }
35 };
36 
37 namespace {
38 
39 class MockCapsuleParserVisitor : public CapsuleParser::Visitor {
40  public:
MockCapsuleParserVisitor()41   MockCapsuleParserVisitor() {
42     ON_CALL(*this, OnCapsule(_)).WillByDefault(Return(true));
43   }
44   ~MockCapsuleParserVisitor() override = default;
45   MOCK_METHOD(bool, OnCapsule, (const Capsule& capsule), (override));
46   MOCK_METHOD(void, OnCapsuleParseFailure, (absl::string_view error_message),
47               (override));
48 };
49 
50 class CapsuleTest : public QuicheTest {
51  public:
CapsuleTest()52   CapsuleTest() : capsule_parser_(&visitor_) {}
53 
ValidateParserIsEmpty()54   void ValidateParserIsEmpty() {
55     EXPECT_CALL(visitor_, OnCapsule(_)).Times(0);
56     EXPECT_CALL(visitor_, OnCapsuleParseFailure(_)).Times(0);
57     capsule_parser_.ErrorIfThereIsRemainingBufferedData();
58     EXPECT_TRUE(CapsuleParserPeer::buffered_data(&capsule_parser_)->empty());
59   }
60 
TestSerialization(const Capsule & capsule,const std::string & expected_bytes)61   void TestSerialization(const Capsule& capsule,
62                          const std::string& expected_bytes) {
63     quiche::QuicheBuffer serialized_capsule =
64         SerializeCapsule(capsule, SimpleBufferAllocator::Get());
65     quiche::test::CompareCharArraysWithHexError(
66         "Serialized capsule", serialized_capsule.data(),
67         serialized_capsule.size(), expected_bytes.data(),
68         expected_bytes.size());
69   }
70 
71   ::testing::StrictMock<MockCapsuleParserVisitor> visitor_;
72   CapsuleParser capsule_parser_;
73 };
74 
TEST_F(CapsuleTest,DatagramCapsule)75 TEST_F(CapsuleTest, DatagramCapsule) {
76   std::string capsule_fragment;
77   ASSERT_TRUE(
78       absl::HexStringToBytes("00"                 // DATAGRAM capsule type
79                              "08"                 // capsule length
80                              "a1a2a3a4a5a6a7a8",  // HTTP Datagram payload
81                              &capsule_fragment));
82   std::string datagram_payload;
83   ASSERT_TRUE(absl::HexStringToBytes("a1a2a3a4a5a6a7a8", &datagram_payload));
84   Capsule expected_capsule = Capsule::Datagram(datagram_payload);
85   {
86     EXPECT_CALL(visitor_, OnCapsule(expected_capsule));
87     ASSERT_TRUE(capsule_parser_.IngestCapsuleFragment(capsule_fragment));
88   }
89   ValidateParserIsEmpty();
90   TestSerialization(expected_capsule, capsule_fragment);
91 }
92 
TEST_F(CapsuleTest,DatagramCapsuleViaHeader)93 TEST_F(CapsuleTest, DatagramCapsuleViaHeader) {
94   std::string datagram_payload;
95   ASSERT_TRUE(absl::HexStringToBytes("a1a2a3a4a5a6a7a8", &datagram_payload));
96   quiche::QuicheBuffer expected_capsule = SerializeCapsule(
97       Capsule::Datagram(datagram_payload), SimpleBufferAllocator::Get());
98   quiche::QuicheBuffer actual_header = SerializeDatagramCapsuleHeader(
99       datagram_payload.size(), SimpleBufferAllocator::Get());
100   EXPECT_EQ(expected_capsule.AsStringView(),
101             absl::StrCat(actual_header.AsStringView(), datagram_payload));
102 }
103 
TEST_F(CapsuleTest,LegacyDatagramCapsule)104 TEST_F(CapsuleTest, LegacyDatagramCapsule) {
105   std::string capsule_fragment;
106   ASSERT_TRUE(
107       absl::HexStringToBytes("80ff37a0"  // LEGACY_DATAGRAM capsule type
108                              "08"        // capsule length
109                              "a1a2a3a4a5a6a7a8",  // HTTP Datagram payload
110                              &capsule_fragment));
111   std::string datagram_payload;
112   ASSERT_TRUE(absl::HexStringToBytes("a1a2a3a4a5a6a7a8", &datagram_payload));
113   Capsule expected_capsule = Capsule::LegacyDatagram(datagram_payload);
114   {
115     EXPECT_CALL(visitor_, OnCapsule(expected_capsule));
116     ASSERT_TRUE(capsule_parser_.IngestCapsuleFragment(capsule_fragment));
117   }
118   ValidateParserIsEmpty();
119   TestSerialization(expected_capsule, capsule_fragment);
120 }
121 
TEST_F(CapsuleTest,LegacyDatagramWithoutContextCapsule)122 TEST_F(CapsuleTest, LegacyDatagramWithoutContextCapsule) {
123   std::string capsule_fragment;
124   ASSERT_TRUE(absl::HexStringToBytes(
125       "80ff37a5"           // LEGACY_DATAGRAM_WITHOUT_CONTEXT capsule type
126       "08"                 // capsule length
127       "a1a2a3a4a5a6a7a8",  // HTTP Datagram payload
128       &capsule_fragment));
129   std::string datagram_payload;
130   ASSERT_TRUE(absl::HexStringToBytes("a1a2a3a4a5a6a7a8", &datagram_payload));
131   Capsule expected_capsule =
132       Capsule::LegacyDatagramWithoutContext(datagram_payload);
133   {
134     EXPECT_CALL(visitor_, OnCapsule(expected_capsule));
135     ASSERT_TRUE(capsule_parser_.IngestCapsuleFragment(capsule_fragment));
136   }
137   ValidateParserIsEmpty();
138   TestSerialization(expected_capsule, capsule_fragment);
139 }
140 
TEST_F(CapsuleTest,CloseWebTransportStreamCapsule)141 TEST_F(CapsuleTest, CloseWebTransportStreamCapsule) {
142   std::string capsule_fragment;
143   ASSERT_TRUE(
144       absl::HexStringToBytes("6843"  // CLOSE_WEBTRANSPORT_STREAM capsule type
145                              "09"    // capsule length
146                              "00001234"     // 0x1234 error code
147                              "68656c6c6f",  // "hello" error message
148                              &capsule_fragment));
149   Capsule expected_capsule = Capsule::CloseWebTransportSession(
150       /*error_code=*/0x1234, /*error_message=*/"hello");
151   {
152     EXPECT_CALL(visitor_, OnCapsule(expected_capsule));
153     ASSERT_TRUE(capsule_parser_.IngestCapsuleFragment(capsule_fragment));
154   }
155   ValidateParserIsEmpty();
156   TestSerialization(expected_capsule, capsule_fragment);
157 }
158 
TEST_F(CapsuleTest,DrainWebTransportStreamCapsule)159 TEST_F(CapsuleTest, DrainWebTransportStreamCapsule) {
160   std::string capsule_fragment;
161   ASSERT_TRUE(absl::HexStringToBytes(
162       "800078ae"  // DRAIN_WEBTRANSPORT_STREAM capsule type
163       "00",       // capsule length
164       &capsule_fragment));
165   Capsule expected_capsule = Capsule(DrainWebTransportSessionCapsule());
166   {
167     EXPECT_CALL(visitor_, OnCapsule(expected_capsule));
168     ASSERT_TRUE(capsule_parser_.IngestCapsuleFragment(capsule_fragment));
169   }
170   ValidateParserIsEmpty();
171   TestSerialization(expected_capsule, capsule_fragment);
172 }
173 
TEST_F(CapsuleTest,AddressAssignCapsule)174 TEST_F(CapsuleTest, AddressAssignCapsule) {
175   std::string capsule_fragment;
176   ASSERT_TRUE(absl::HexStringToBytes(
177       "9ECA6A00"  // ADDRESS_ASSIGN capsule type
178       "1A"        // capsule length = 26
179       // first assigned address
180       "00"        // request ID = 0
181       "04"        // IP version = 4
182       "C000022A"  // 192.0.2.42
183       "1F"        // prefix length = 31
184       // second assigned address
185       "01"                                // request ID = 1
186       "06"                                // IP version = 6
187       "20010db8123456780000000000000000"  // 2001:db8:1234:5678::
188       "40",                               // prefix length = 64
189       &capsule_fragment));
190   Capsule expected_capsule = Capsule::AddressAssign();
191   quiche::QuicheIpAddress ip_address1;
192   ip_address1.FromString("192.0.2.42");
193   PrefixWithId assigned_address1;
194   assigned_address1.request_id = 0;
195   assigned_address1.ip_prefix =
196       quiche::QuicheIpPrefix(ip_address1, /*prefix_length=*/31);
197   expected_capsule.address_assign_capsule().assigned_addresses.push_back(
198       assigned_address1);
199   quiche::QuicheIpAddress ip_address2;
200   ip_address2.FromString("2001:db8:1234:5678::");
201   PrefixWithId assigned_address2;
202   assigned_address2.request_id = 1;
203   assigned_address2.ip_prefix =
204       quiche::QuicheIpPrefix(ip_address2, /*prefix_length=*/64);
205   expected_capsule.address_assign_capsule().assigned_addresses.push_back(
206       assigned_address2);
207   {
208     EXPECT_CALL(visitor_, OnCapsule(expected_capsule));
209     ASSERT_TRUE(capsule_parser_.IngestCapsuleFragment(capsule_fragment));
210   }
211   ValidateParserIsEmpty();
212   TestSerialization(expected_capsule, capsule_fragment);
213 }
214 
TEST_F(CapsuleTest,AddressRequestCapsule)215 TEST_F(CapsuleTest, AddressRequestCapsule) {
216   std::string capsule_fragment;
217   ASSERT_TRUE(absl::HexStringToBytes(
218       "9ECA6A01"  // ADDRESS_REQUEST capsule type
219       "1A"        // capsule length = 26
220       // first requested address
221       "00"        // request ID = 0
222       "04"        // IP version = 4
223       "C000022A"  // 192.0.2.42
224       "1F"        // prefix length = 31
225       // second requested address
226       "01"                                // request ID = 1
227       "06"                                // IP version = 6
228       "20010db8123456780000000000000000"  // 2001:db8:1234:5678::
229       "40",                               // prefix length = 64
230       &capsule_fragment));
231   Capsule expected_capsule = Capsule::AddressRequest();
232   quiche::QuicheIpAddress ip_address1;
233   ip_address1.FromString("192.0.2.42");
234   PrefixWithId requested_address1;
235   requested_address1.request_id = 0;
236   requested_address1.ip_prefix =
237       quiche::QuicheIpPrefix(ip_address1, /*prefix_length=*/31);
238   expected_capsule.address_request_capsule().requested_addresses.push_back(
239       requested_address1);
240   quiche::QuicheIpAddress ip_address2;
241   ip_address2.FromString("2001:db8:1234:5678::");
242   PrefixWithId requested_address2;
243   requested_address2.request_id = 1;
244   requested_address2.ip_prefix =
245       quiche::QuicheIpPrefix(ip_address2, /*prefix_length=*/64);
246   expected_capsule.address_request_capsule().requested_addresses.push_back(
247       requested_address2);
248   {
249     EXPECT_CALL(visitor_, OnCapsule(expected_capsule));
250     ASSERT_TRUE(capsule_parser_.IngestCapsuleFragment(capsule_fragment));
251   }
252   ValidateParserIsEmpty();
253   TestSerialization(expected_capsule, capsule_fragment);
254 }
255 
TEST_F(CapsuleTest,RouteAdvertisementCapsule)256 TEST_F(CapsuleTest, RouteAdvertisementCapsule) {
257   std::string capsule_fragment;
258   ASSERT_TRUE(absl::HexStringToBytes(
259       "9ECA6A02"  // ROUTE_ADVERTISEMENT capsule type
260       "2C"        // capsule length = 44
261       // first IP address range
262       "04"        // IP version = 4
263       "C0000218"  // 192.0.2.24
264       "C000022A"  // 192.0.2.42
265       "00"        // ip protocol = 0
266       // second IP address range
267       "06"                                // IP version = 6
268       "00000000000000000000000000000000"  // ::
269       "ffffffffffffffffffffffffffffffff"  // all ones IPv6 address
270       "01",                               // ip protocol = 1 (ICMP)
271       &capsule_fragment));
272   Capsule expected_capsule = Capsule::RouteAdvertisement();
273   IpAddressRange ip_address_range1;
274   ip_address_range1.start_ip_address.FromString("192.0.2.24");
275   ip_address_range1.end_ip_address.FromString("192.0.2.42");
276   ip_address_range1.ip_protocol = 0;
277   expected_capsule.route_advertisement_capsule().ip_address_ranges.push_back(
278       ip_address_range1);
279   IpAddressRange ip_address_range2;
280   ip_address_range2.start_ip_address.FromString("::");
281   ip_address_range2.end_ip_address.FromString(
282       "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
283   ip_address_range2.ip_protocol = 1;
284   expected_capsule.route_advertisement_capsule().ip_address_ranges.push_back(
285       ip_address_range2);
286   {
287     EXPECT_CALL(visitor_, OnCapsule(expected_capsule));
288     ASSERT_TRUE(capsule_parser_.IngestCapsuleFragment(capsule_fragment));
289   }
290   ValidateParserIsEmpty();
291   TestSerialization(expected_capsule, capsule_fragment);
292 }
293 
TEST_F(CapsuleTest,WebTransportStreamData)294 TEST_F(CapsuleTest, WebTransportStreamData) {
295   std::string capsule_fragment;
296   ASSERT_TRUE(
297       absl::HexStringToBytes("990b4d3b"  // WT_STREAM without FIN
298                              "04"        // capsule length
299                              "17"        // stream ID
300                              "abcdef",   // stream payload
301                              &capsule_fragment));
302   Capsule expected_capsule = Capsule(WebTransportStreamDataCapsule());
303   expected_capsule.web_transport_stream_data().stream_id = 0x17;
304   expected_capsule.web_transport_stream_data().data = "\xab\xcd\xef";
305   expected_capsule.web_transport_stream_data().fin = false;
306   {
307     EXPECT_CALL(visitor_, OnCapsule(expected_capsule));
308     ASSERT_TRUE(capsule_parser_.IngestCapsuleFragment(capsule_fragment));
309   }
310   ValidateParserIsEmpty();
311   TestSerialization(expected_capsule, capsule_fragment);
312 }
TEST_F(CapsuleTest,WebTransportStreamDataHeader)313 TEST_F(CapsuleTest, WebTransportStreamDataHeader) {
314   std::string capsule_fragment;
315   ASSERT_TRUE(absl::HexStringToBytes(
316       "990b4d3b"  // WT_STREAM without FIN
317       "04"        // capsule length
318       "17",       // stream ID
319                   // three bytes of stream payload implied below
320       &capsule_fragment));
321   QuicheBufferAllocator* allocator = SimpleBufferAllocator::Get();
322   QuicheBuffer capsule_header =
323       quiche::SerializeWebTransportStreamCapsuleHeader(0x17, /*fin=*/false, 3,
324                                                        allocator);
325   EXPECT_EQ(capsule_header.AsStringView(), capsule_fragment);
326 }
TEST_F(CapsuleTest,WebTransportStreamDataWithFin)327 TEST_F(CapsuleTest, WebTransportStreamDataWithFin) {
328   std::string capsule_fragment;
329   ASSERT_TRUE(
330       absl::HexStringToBytes("990b4d3c"  // data with FIN
331                              "04"        // capsule length
332                              "17"        // stream ID
333                              "abcdef",   // stream payload
334                              &capsule_fragment));
335   Capsule expected_capsule = Capsule(WebTransportStreamDataCapsule());
336   expected_capsule.web_transport_stream_data().stream_id = 0x17;
337   expected_capsule.web_transport_stream_data().data = "\xab\xcd\xef";
338   expected_capsule.web_transport_stream_data().fin = true;
339   {
340     EXPECT_CALL(visitor_, OnCapsule(expected_capsule));
341     ASSERT_TRUE(capsule_parser_.IngestCapsuleFragment(capsule_fragment));
342   }
343   ValidateParserIsEmpty();
344   TestSerialization(expected_capsule, capsule_fragment);
345 }
346 
TEST_F(CapsuleTest,WebTransportResetStream)347 TEST_F(CapsuleTest, WebTransportResetStream) {
348   std::string capsule_fragment;
349   ASSERT_TRUE(
350       absl::HexStringToBytes("990b4d39"  // WT_RESET_STREAM
351                              "02"        // capsule length
352                              "17"        // stream ID
353                              "07",       // error code
354                              &capsule_fragment));
355   Capsule expected_capsule = Capsule(WebTransportResetStreamCapsule());
356   expected_capsule.web_transport_reset_stream().stream_id = 0x17;
357   expected_capsule.web_transport_reset_stream().error_code = 0x07;
358   {
359     EXPECT_CALL(visitor_, OnCapsule(expected_capsule));
360     ASSERT_TRUE(capsule_parser_.IngestCapsuleFragment(capsule_fragment));
361   }
362   ValidateParserIsEmpty();
363   TestSerialization(expected_capsule, capsule_fragment);
364 }
365 
TEST_F(CapsuleTest,WebTransportStopSending)366 TEST_F(CapsuleTest, WebTransportStopSending) {
367   std::string capsule_fragment;
368   ASSERT_TRUE(
369       absl::HexStringToBytes("990b4d3a"  // WT_STOP_SENDING
370                              "02"        // capsule length
371                              "17"        // stream ID
372                              "07",       // error code
373                              &capsule_fragment));
374   Capsule expected_capsule = Capsule(WebTransportStopSendingCapsule());
375   expected_capsule.web_transport_stop_sending().stream_id = 0x17;
376   expected_capsule.web_transport_stop_sending().error_code = 0x07;
377   {
378     EXPECT_CALL(visitor_, OnCapsule(expected_capsule));
379     ASSERT_TRUE(capsule_parser_.IngestCapsuleFragment(capsule_fragment));
380   }
381   ValidateParserIsEmpty();
382   TestSerialization(expected_capsule, capsule_fragment);
383 }
384 
TEST_F(CapsuleTest,WebTransportMaxStreamData)385 TEST_F(CapsuleTest, WebTransportMaxStreamData) {
386   std::string capsule_fragment;
387   ASSERT_TRUE(
388       absl::HexStringToBytes("990b4d3e"  // WT_MAX_STREAM_DATA
389                              "02"        // capsule length
390                              "17"        // stream ID
391                              "10",       // max stream data
392                              &capsule_fragment));
393   Capsule expected_capsule = Capsule(WebTransportMaxStreamDataCapsule());
394   expected_capsule.web_transport_max_stream_data().stream_id = 0x17;
395   expected_capsule.web_transport_max_stream_data().max_stream_data = 0x10;
396   {
397     EXPECT_CALL(visitor_, OnCapsule(expected_capsule));
398     ASSERT_TRUE(capsule_parser_.IngestCapsuleFragment(capsule_fragment));
399   }
400   ValidateParserIsEmpty();
401   TestSerialization(expected_capsule, capsule_fragment);
402 }
403 
TEST_F(CapsuleTest,WebTransportMaxStreamsBi)404 TEST_F(CapsuleTest, WebTransportMaxStreamsBi) {
405   std::string capsule_fragment;
406   ASSERT_TRUE(
407       absl::HexStringToBytes("990b4d3f"  // WT_MAX_STREAMS (bidi)
408                              "01"        // capsule length
409                              "17",       // max streams
410                              &capsule_fragment));
411   Capsule expected_capsule = Capsule(WebTransportMaxStreamsCapsule());
412   expected_capsule.web_transport_max_streams().stream_type =
413       StreamType::kBidirectional;
414   expected_capsule.web_transport_max_streams().max_stream_count = 0x17;
415   {
416     EXPECT_CALL(visitor_, OnCapsule(expected_capsule));
417     ASSERT_TRUE(capsule_parser_.IngestCapsuleFragment(capsule_fragment));
418   }
419   ValidateParserIsEmpty();
420   TestSerialization(expected_capsule, capsule_fragment);
421 }
422 
TEST_F(CapsuleTest,WebTransportMaxStreamsUni)423 TEST_F(CapsuleTest, WebTransportMaxStreamsUni) {
424   std::string capsule_fragment;
425   ASSERT_TRUE(
426       absl::HexStringToBytes("990b4d40"  // WT_MAX_STREAMS (unidi)
427                              "01"        // capsule length
428                              "17",       // max streams
429                              &capsule_fragment));
430   Capsule expected_capsule = Capsule(WebTransportMaxStreamsCapsule());
431   expected_capsule.web_transport_max_streams().stream_type =
432       StreamType::kUnidirectional;
433   expected_capsule.web_transport_max_streams().max_stream_count = 0x17;
434   {
435     EXPECT_CALL(visitor_, OnCapsule(expected_capsule));
436     ASSERT_TRUE(capsule_parser_.IngestCapsuleFragment(capsule_fragment));
437   }
438   ValidateParserIsEmpty();
439   TestSerialization(expected_capsule, capsule_fragment);
440 }
441 
TEST_F(CapsuleTest,UnknownCapsule)442 TEST_F(CapsuleTest, UnknownCapsule) {
443   std::string capsule_fragment;
444   ASSERT_TRUE(
445       absl::HexStringToBytes("17"  // unknown capsule type of 0x17
446                              "08"  // capsule length
447                              "a1a2a3a4a5a6a7a8",  // unknown capsule data
448                              &capsule_fragment));
449   std::string unknown_capsule_data;
450   ASSERT_TRUE(
451       absl::HexStringToBytes("a1a2a3a4a5a6a7a8", &unknown_capsule_data));
452   Capsule expected_capsule = Capsule::Unknown(0x17, unknown_capsule_data);
453   {
454     EXPECT_CALL(visitor_, OnCapsule(expected_capsule));
455     ASSERT_TRUE(capsule_parser_.IngestCapsuleFragment(capsule_fragment));
456   }
457   ValidateParserIsEmpty();
458   TestSerialization(expected_capsule, capsule_fragment);
459 }
460 
TEST_F(CapsuleTest,TwoCapsules)461 TEST_F(CapsuleTest, TwoCapsules) {
462   std::string capsule_fragment;
463   ASSERT_TRUE(
464       absl::HexStringToBytes("00"                 // DATAGRAM capsule type
465                              "08"                 // capsule length
466                              "a1a2a3a4a5a6a7a8"   // HTTP Datagram payload
467                              "00"                 // DATAGRAM capsule type
468                              "08"                 // capsule length
469                              "b1b2b3b4b5b6b7b8",  // HTTP Datagram payload
470                              &capsule_fragment));
471   std::string datagram_payload1;
472   ASSERT_TRUE(absl::HexStringToBytes("a1a2a3a4a5a6a7a8", &datagram_payload1));
473   std::string datagram_payload2;
474   ASSERT_TRUE(absl::HexStringToBytes("b1b2b3b4b5b6b7b8", &datagram_payload2));
475   Capsule expected_capsule1 = Capsule::Datagram(datagram_payload1);
476   Capsule expected_capsule2 = Capsule::Datagram(datagram_payload2);
477   {
478     InSequence s;
479     EXPECT_CALL(visitor_, OnCapsule(expected_capsule1));
480     EXPECT_CALL(visitor_, OnCapsule(expected_capsule2));
481     ASSERT_TRUE(capsule_parser_.IngestCapsuleFragment(capsule_fragment));
482   }
483   ValidateParserIsEmpty();
484 }
485 
TEST_F(CapsuleTest,TwoCapsulesPartialReads)486 TEST_F(CapsuleTest, TwoCapsulesPartialReads) {
487   std::string capsule_fragment1;
488   ASSERT_TRUE(absl::HexStringToBytes(
489       "00"         // first capsule DATAGRAM capsule type
490       "08"         // first capsule length
491       "a1a2a3a4",  // first half of HTTP Datagram payload of first capsule
492       &capsule_fragment1));
493   std::string capsule_fragment2;
494   ASSERT_TRUE(absl::HexStringToBytes(
495       "a5a6a7a8"  // second half of HTTP Datagram payload 1
496       "00",       // second capsule DATAGRAM capsule type
497       &capsule_fragment2));
498   std::string capsule_fragment3;
499   ASSERT_TRUE(absl::HexStringToBytes(
500       "08"                 // second capsule length
501       "b1b2b3b4b5b6b7b8",  // HTTP Datagram payload of second capsule
502       &capsule_fragment3));
503   capsule_parser_.ErrorIfThereIsRemainingBufferedData();
504   std::string datagram_payload1;
505   ASSERT_TRUE(absl::HexStringToBytes("a1a2a3a4a5a6a7a8", &datagram_payload1));
506   std::string datagram_payload2;
507   ASSERT_TRUE(absl::HexStringToBytes("b1b2b3b4b5b6b7b8", &datagram_payload2));
508   Capsule expected_capsule1 = Capsule::Datagram(datagram_payload1);
509   Capsule expected_capsule2 = Capsule::Datagram(datagram_payload2);
510   {
511     InSequence s;
512     EXPECT_CALL(visitor_, OnCapsule(expected_capsule1));
513     EXPECT_CALL(visitor_, OnCapsule(expected_capsule2));
514     ASSERT_TRUE(capsule_parser_.IngestCapsuleFragment(capsule_fragment1));
515     ASSERT_TRUE(capsule_parser_.IngestCapsuleFragment(capsule_fragment2));
516     ASSERT_TRUE(capsule_parser_.IngestCapsuleFragment(capsule_fragment3));
517   }
518   ValidateParserIsEmpty();
519 }
520 
TEST_F(CapsuleTest,TwoCapsulesOneByteAtATime)521 TEST_F(CapsuleTest, TwoCapsulesOneByteAtATime) {
522   std::string capsule_fragment;
523   ASSERT_TRUE(
524       absl::HexStringToBytes("00"                 // DATAGRAM capsule type
525                              "08"                 // capsule length
526                              "a1a2a3a4a5a6a7a8"   // HTTP Datagram payload
527                              "00"                 // DATAGRAM capsule type
528                              "08"                 // capsule length
529                              "b1b2b3b4b5b6b7b8",  // HTTP Datagram payload
530                              &capsule_fragment));
531   std::string datagram_payload1;
532   ASSERT_TRUE(absl::HexStringToBytes("a1a2a3a4a5a6a7a8", &datagram_payload1));
533   std::string datagram_payload2;
534   ASSERT_TRUE(absl::HexStringToBytes("b1b2b3b4b5b6b7b8", &datagram_payload2));
535   Capsule expected_capsule1 = Capsule::Datagram(datagram_payload1);
536   Capsule expected_capsule2 = Capsule::Datagram(datagram_payload2);
537   for (size_t i = 0; i < capsule_fragment.size(); i++) {
538     if (i < capsule_fragment.size() / 2 - 1) {
539       EXPECT_CALL(visitor_, OnCapsule(_)).Times(0);
540       ASSERT_TRUE(
541           capsule_parser_.IngestCapsuleFragment(capsule_fragment.substr(i, 1)));
542     } else if (i == capsule_fragment.size() / 2 - 1) {
543       EXPECT_CALL(visitor_, OnCapsule(expected_capsule1));
544       ASSERT_TRUE(
545           capsule_parser_.IngestCapsuleFragment(capsule_fragment.substr(i, 1)));
546       EXPECT_TRUE(CapsuleParserPeer::buffered_data(&capsule_parser_)->empty());
547     } else if (i < capsule_fragment.size() - 1) {
548       EXPECT_CALL(visitor_, OnCapsule(_)).Times(0);
549       ASSERT_TRUE(
550           capsule_parser_.IngestCapsuleFragment(capsule_fragment.substr(i, 1)));
551     } else {
552       EXPECT_CALL(visitor_, OnCapsule(expected_capsule2));
553       ASSERT_TRUE(
554           capsule_parser_.IngestCapsuleFragment(capsule_fragment.substr(i, 1)));
555       EXPECT_TRUE(CapsuleParserPeer::buffered_data(&capsule_parser_)->empty());
556     }
557   }
558   capsule_parser_.ErrorIfThereIsRemainingBufferedData();
559   EXPECT_TRUE(CapsuleParserPeer::buffered_data(&capsule_parser_)->empty());
560 }
561 
TEST_F(CapsuleTest,PartialCapsuleThenError)562 TEST_F(CapsuleTest, PartialCapsuleThenError) {
563   std::string capsule_fragment;
564   ASSERT_TRUE(
565       absl::HexStringToBytes("00"         // DATAGRAM capsule type
566                              "08"         // capsule length
567                              "a1a2a3a4",  // first half of HTTP Datagram payload
568                              &capsule_fragment));
569   EXPECT_CALL(visitor_, OnCapsule(_)).Times(0);
570   {
571     EXPECT_CALL(visitor_, OnCapsuleParseFailure(_)).Times(0);
572     ASSERT_TRUE(capsule_parser_.IngestCapsuleFragment(capsule_fragment));
573   }
574   {
575     EXPECT_CALL(visitor_,
576                 OnCapsuleParseFailure(
577                     "Incomplete capsule left at the end of the stream"));
578     capsule_parser_.ErrorIfThereIsRemainingBufferedData();
579   }
580 }
581 
TEST_F(CapsuleTest,RejectOverlyLongCapsule)582 TEST_F(CapsuleTest, RejectOverlyLongCapsule) {
583   std::string capsule_fragment;
584   ASSERT_TRUE(
585       absl::HexStringToBytes("17"         // unknown capsule type of 0x17
586                              "80123456",  // capsule length
587                              &capsule_fragment));
588   absl::StrAppend(&capsule_fragment, std::string(1111111, '?'));
589   EXPECT_CALL(visitor_, OnCapsuleParseFailure(
590                             "Refusing to buffer too much capsule data"));
591   EXPECT_FALSE(capsule_parser_.IngestCapsuleFragment(capsule_fragment));
592 }
593 
594 }  // namespace
595 }  // namespace test
596 }  // namespace quiche
597