xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_round_trip_test.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 2018 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 <string>
6 #include <tuple>
7 
8 #include "absl/strings/string_view.h"
9 #include "quiche/quic/core/qpack/qpack_decoder.h"
10 #include "quiche/quic/core/qpack/qpack_encoder.h"
11 #include "quiche/quic/platform/api/quic_test.h"
12 #include "quiche/quic/test_tools/qpack/qpack_decoder_test_utils.h"
13 #include "quiche/quic/test_tools/qpack/qpack_test_utils.h"
14 #include "quiche/spdy/core/http2_header_block.h"
15 
16 using ::testing::Values;
17 
18 namespace quic {
19 namespace test {
20 namespace {
21 
22 class QpackRoundTripTest : public QuicTestWithParam<FragmentMode> {
23  public:
24   QpackRoundTripTest() = default;
25   ~QpackRoundTripTest() override = default;
26 
EncodeThenDecode(const spdy::Http2HeaderBlock & header_list)27   spdy::Http2HeaderBlock EncodeThenDecode(
28       const spdy::Http2HeaderBlock& header_list) {
29     NoopDecoderStreamErrorDelegate decoder_stream_error_delegate;
30     NoopQpackStreamSenderDelegate encoder_stream_sender_delegate;
31     QpackEncoder encoder(&decoder_stream_error_delegate,
32                          HuffmanEncoding::kEnabled);
33     encoder.set_qpack_stream_sender_delegate(&encoder_stream_sender_delegate);
34     std::string encoded_header_block =
35         encoder.EncodeHeaderList(/* stream_id = */ 1, header_list, nullptr);
36 
37     TestHeadersHandler handler;
38     NoopEncoderStreamErrorDelegate encoder_stream_error_delegate;
39     NoopQpackStreamSenderDelegate decoder_stream_sender_delegate;
40     // TODO(b/112770235): Test dynamic table and blocked streams.
41     QpackDecode(
42         /* maximum_dynamic_table_capacity = */ 0,
43         /* maximum_blocked_streams = */ 0, &encoder_stream_error_delegate,
44         &decoder_stream_sender_delegate, &handler,
45         FragmentModeToFragmentSizeGenerator(GetParam()), encoded_header_block);
46 
47     EXPECT_TRUE(handler.decoding_completed());
48     EXPECT_FALSE(handler.decoding_error_detected());
49 
50     return handler.ReleaseHeaderList();
51   }
52 };
53 
54 INSTANTIATE_TEST_SUITE_P(All, QpackRoundTripTest,
55                          Values(FragmentMode::kSingleChunk,
56                                 FragmentMode::kOctetByOctet));
57 
TEST_P(QpackRoundTripTest,Empty)58 TEST_P(QpackRoundTripTest, Empty) {
59   spdy::Http2HeaderBlock header_list;
60   spdy::Http2HeaderBlock output = EncodeThenDecode(header_list);
61   EXPECT_EQ(header_list, output);
62 }
63 
TEST_P(QpackRoundTripTest,EmptyName)64 TEST_P(QpackRoundTripTest, EmptyName) {
65   spdy::Http2HeaderBlock header_list;
66   header_list["foo"] = "bar";
67   header_list[""] = "bar";
68 
69   spdy::Http2HeaderBlock output = EncodeThenDecode(header_list);
70   EXPECT_EQ(header_list, output);
71 }
72 
TEST_P(QpackRoundTripTest,EmptyValue)73 TEST_P(QpackRoundTripTest, EmptyValue) {
74   spdy::Http2HeaderBlock header_list;
75   header_list["foo"] = "";
76   header_list[""] = "";
77 
78   spdy::Http2HeaderBlock output = EncodeThenDecode(header_list);
79   EXPECT_EQ(header_list, output);
80 }
81 
TEST_P(QpackRoundTripTest,MultipleWithLongEntries)82 TEST_P(QpackRoundTripTest, MultipleWithLongEntries) {
83   spdy::Http2HeaderBlock header_list;
84   header_list["foo"] = "bar";
85   header_list[":path"] = "/";
86   header_list["foobaar"] = std::string(127, 'Z');
87   header_list[std::string(1000, 'b')] = std::string(1000, 'c');
88 
89   spdy::Http2HeaderBlock output = EncodeThenDecode(header_list);
90   EXPECT_EQ(header_list, output);
91 }
92 
TEST_P(QpackRoundTripTest,StaticTable)93 TEST_P(QpackRoundTripTest, StaticTable) {
94   {
95     spdy::Http2HeaderBlock header_list;
96     header_list[":method"] = "GET";
97     header_list["accept-encoding"] = "gzip, deflate";
98     header_list["cache-control"] = "";
99     header_list["foo"] = "bar";
100     header_list[":path"] = "/";
101 
102     spdy::Http2HeaderBlock output = EncodeThenDecode(header_list);
103     EXPECT_EQ(header_list, output);
104   }
105   {
106     spdy::Http2HeaderBlock header_list;
107     header_list[":method"] = "POST";
108     header_list["accept-encoding"] = "brotli";
109     header_list["cache-control"] = "foo";
110     header_list["foo"] = "bar";
111     header_list[":path"] = "/";
112 
113     spdy::Http2HeaderBlock output = EncodeThenDecode(header_list);
114     EXPECT_EQ(header_list, output);
115   }
116   {
117     spdy::Http2HeaderBlock header_list;
118     header_list[":method"] = "CONNECT";
119     header_list["accept-encoding"] = "";
120     header_list["foo"] = "bar";
121     header_list[":path"] = "/";
122 
123     spdy::Http2HeaderBlock output = EncodeThenDecode(header_list);
124     EXPECT_EQ(header_list, output);
125   }
126 }
127 
TEST_P(QpackRoundTripTest,ValueHasNullCharacter)128 TEST_P(QpackRoundTripTest, ValueHasNullCharacter) {
129   spdy::Http2HeaderBlock header_list;
130   header_list["foo"] = absl::string_view("bar\0bar\0baz", 11);
131 
132   spdy::Http2HeaderBlock output = EncodeThenDecode(header_list);
133   EXPECT_EQ(header_list, output);
134 }
135 
136 }  // namespace
137 }  // namespace test
138 }  // namespace quic
139