xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_output_stream_test.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2014 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/spdy/core/hpack/hpack_output_stream.h"
6 
7 #include <cstdint>
8 #include <string>
9 
10 #include "quiche/common/platform/api/quiche_test.h"
11 
12 namespace spdy {
13 
14 namespace {
15 
16 // Make sure that AppendBits() appends bits starting from the most
17 // significant bit, and that it can handle crossing a byte boundary.
TEST(HpackOutputStreamTest,AppendBits)18 TEST(HpackOutputStreamTest, AppendBits) {
19   HpackOutputStream output_stream;
20   std::string expected_str;
21 
22   output_stream.AppendBits(0x1, 1);
23   expected_str.append(1, 0x00);
24   expected_str.back() |= (0x1 << 7);
25 
26   output_stream.AppendBits(0x0, 1);
27 
28   output_stream.AppendBits(0x3, 2);
29   *expected_str.rbegin() |= (0x3 << 4);
30 
31   output_stream.AppendBits(0x0, 2);
32 
33   // Byte-crossing append.
34   output_stream.AppendBits(0x7, 3);
35   *expected_str.rbegin() |= (0x7 >> 1);
36   expected_str.append(1, 0x00);
37   expected_str.back() |= (0x7 << 7);
38 
39   output_stream.AppendBits(0x0, 7);
40 
41   std::string str = output_stream.TakeString();
42   EXPECT_EQ(expected_str, str);
43 }
44 
45 // Utility function to return I as a string encoded with an N-bit
46 // prefix.
EncodeUint32(uint8_t N,uint32_t I)47 std::string EncodeUint32(uint8_t N, uint32_t I) {
48   HpackOutputStream output_stream;
49   if (N < 8) {
50     output_stream.AppendBits(0x00, 8 - N);
51   }
52   output_stream.AppendUint32(I);
53   std::string str = output_stream.TakeString();
54   return str;
55 }
56 
57 // The {Number}ByteIntegersEightBitPrefix tests below test that
58 // certain integers are encoded correctly with an 8-bit prefix in
59 // exactly {Number} bytes.
60 
TEST(HpackOutputStreamTest,OneByteIntegersEightBitPrefix)61 TEST(HpackOutputStreamTest, OneByteIntegersEightBitPrefix) {
62   // Minimum.
63   EXPECT_EQ(std::string("\x00", 1), EncodeUint32(8, 0x00));
64   EXPECT_EQ("\x7f", EncodeUint32(8, 0x7f));
65   // Maximum.
66   EXPECT_EQ("\xfe", EncodeUint32(8, 0xfe));
67 }
68 
TEST(HpackOutputStreamTest,TwoByteIntegersEightBitPrefix)69 TEST(HpackOutputStreamTest, TwoByteIntegersEightBitPrefix) {
70   // Minimum.
71   EXPECT_EQ(std::string("\xff\x00", 2), EncodeUint32(8, 0xff));
72   EXPECT_EQ("\xff\x01", EncodeUint32(8, 0x0100));
73   // Maximum.
74   EXPECT_EQ("\xff\x7f", EncodeUint32(8, 0x017e));
75 }
76 
TEST(HpackOutputStreamTest,ThreeByteIntegersEightBitPrefix)77 TEST(HpackOutputStreamTest, ThreeByteIntegersEightBitPrefix) {
78   // Minimum.
79   EXPECT_EQ("\xff\x80\x01", EncodeUint32(8, 0x017f));
80   EXPECT_EQ("\xff\x80\x1e", EncodeUint32(8, 0x0fff));
81   // Maximum.
82   EXPECT_EQ("\xff\xff\x7f", EncodeUint32(8, 0x40fe));
83 }
84 
TEST(HpackOutputStreamTest,FourByteIntegersEightBitPrefix)85 TEST(HpackOutputStreamTest, FourByteIntegersEightBitPrefix) {
86   // Minimum.
87   EXPECT_EQ("\xff\x80\x80\x01", EncodeUint32(8, 0x40ff));
88   EXPECT_EQ("\xff\x80\xfe\x03", EncodeUint32(8, 0xffff));
89   // Maximum.
90   EXPECT_EQ("\xff\xff\xff\x7f", EncodeUint32(8, 0x002000fe));
91 }
92 
TEST(HpackOutputStreamTest,FiveByteIntegersEightBitPrefix)93 TEST(HpackOutputStreamTest, FiveByteIntegersEightBitPrefix) {
94   // Minimum.
95   EXPECT_EQ("\xff\x80\x80\x80\x01", EncodeUint32(8, 0x002000ff));
96   EXPECT_EQ("\xff\x80\xfe\xff\x07", EncodeUint32(8, 0x00ffffff));
97   // Maximum.
98   EXPECT_EQ("\xff\xff\xff\xff\x7f", EncodeUint32(8, 0x100000fe));
99 }
100 
TEST(HpackOutputStreamTest,SixByteIntegersEightBitPrefix)101 TEST(HpackOutputStreamTest, SixByteIntegersEightBitPrefix) {
102   // Minimum.
103   EXPECT_EQ("\xff\x80\x80\x80\x80\x01", EncodeUint32(8, 0x100000ff));
104   // Maximum.
105   EXPECT_EQ("\xff\x80\xfe\xff\xff\x0f", EncodeUint32(8, 0xffffffff));
106 }
107 
108 // The {Number}ByteIntegersOneToSevenBitPrefix tests below test that
109 // certain integers are encoded correctly with an N-bit prefix in
110 // exactly {Number} bytes for N in {1, 2, ..., 7}.
111 
TEST(HpackOutputStreamTest,OneByteIntegersOneToSevenBitPrefixes)112 TEST(HpackOutputStreamTest, OneByteIntegersOneToSevenBitPrefixes) {
113   // Minimums.
114   EXPECT_EQ(std::string("\x00", 1), EncodeUint32(7, 0x00));
115   EXPECT_EQ(std::string("\x00", 1), EncodeUint32(6, 0x00));
116   EXPECT_EQ(std::string("\x00", 1), EncodeUint32(5, 0x00));
117   EXPECT_EQ(std::string("\x00", 1), EncodeUint32(4, 0x00));
118   EXPECT_EQ(std::string("\x00", 1), EncodeUint32(3, 0x00));
119   EXPECT_EQ(std::string("\x00", 1), EncodeUint32(2, 0x00));
120   EXPECT_EQ(std::string("\x00", 1), EncodeUint32(1, 0x00));
121 
122   // Maximums.
123   EXPECT_EQ("\x7e", EncodeUint32(7, 0x7e));
124   EXPECT_EQ("\x3e", EncodeUint32(6, 0x3e));
125   EXPECT_EQ("\x1e", EncodeUint32(5, 0x1e));
126   EXPECT_EQ("\x0e", EncodeUint32(4, 0x0e));
127   EXPECT_EQ("\x06", EncodeUint32(3, 0x06));
128   EXPECT_EQ("\x02", EncodeUint32(2, 0x02));
129   EXPECT_EQ(std::string("\x00", 1), EncodeUint32(1, 0x00));
130 }
131 
TEST(HpackOutputStreamTest,TwoByteIntegersOneToSevenBitPrefixes)132 TEST(HpackOutputStreamTest, TwoByteIntegersOneToSevenBitPrefixes) {
133   // Minimums.
134   EXPECT_EQ(std::string("\x7f\x00", 2), EncodeUint32(7, 0x7f));
135   EXPECT_EQ(std::string("\x3f\x00", 2), EncodeUint32(6, 0x3f));
136   EXPECT_EQ(std::string("\x1f\x00", 2), EncodeUint32(5, 0x1f));
137   EXPECT_EQ(std::string("\x0f\x00", 2), EncodeUint32(4, 0x0f));
138   EXPECT_EQ(std::string("\x07\x00", 2), EncodeUint32(3, 0x07));
139   EXPECT_EQ(std::string("\x03\x00", 2), EncodeUint32(2, 0x03));
140   EXPECT_EQ(std::string("\x01\x00", 2), EncodeUint32(1, 0x01));
141 
142   // Maximums.
143   EXPECT_EQ("\x7f\x7f", EncodeUint32(7, 0xfe));
144   EXPECT_EQ("\x3f\x7f", EncodeUint32(6, 0xbe));
145   EXPECT_EQ("\x1f\x7f", EncodeUint32(5, 0x9e));
146   EXPECT_EQ("\x0f\x7f", EncodeUint32(4, 0x8e));
147   EXPECT_EQ("\x07\x7f", EncodeUint32(3, 0x86));
148   EXPECT_EQ("\x03\x7f", EncodeUint32(2, 0x82));
149   EXPECT_EQ("\x01\x7f", EncodeUint32(1, 0x80));
150 }
151 
TEST(HpackOutputStreamTest,ThreeByteIntegersOneToSevenBitPrefixes)152 TEST(HpackOutputStreamTest, ThreeByteIntegersOneToSevenBitPrefixes) {
153   // Minimums.
154   EXPECT_EQ("\x7f\x80\x01", EncodeUint32(7, 0xff));
155   EXPECT_EQ("\x3f\x80\x01", EncodeUint32(6, 0xbf));
156   EXPECT_EQ("\x1f\x80\x01", EncodeUint32(5, 0x9f));
157   EXPECT_EQ("\x0f\x80\x01", EncodeUint32(4, 0x8f));
158   EXPECT_EQ("\x07\x80\x01", EncodeUint32(3, 0x87));
159   EXPECT_EQ("\x03\x80\x01", EncodeUint32(2, 0x83));
160   EXPECT_EQ("\x01\x80\x01", EncodeUint32(1, 0x81));
161 
162   // Maximums.
163   EXPECT_EQ("\x7f\xff\x7f", EncodeUint32(7, 0x407e));
164   EXPECT_EQ("\x3f\xff\x7f", EncodeUint32(6, 0x403e));
165   EXPECT_EQ("\x1f\xff\x7f", EncodeUint32(5, 0x401e));
166   EXPECT_EQ("\x0f\xff\x7f", EncodeUint32(4, 0x400e));
167   EXPECT_EQ("\x07\xff\x7f", EncodeUint32(3, 0x4006));
168   EXPECT_EQ("\x03\xff\x7f", EncodeUint32(2, 0x4002));
169   EXPECT_EQ("\x01\xff\x7f", EncodeUint32(1, 0x4000));
170 }
171 
TEST(HpackOutputStreamTest,FourByteIntegersOneToSevenBitPrefixes)172 TEST(HpackOutputStreamTest, FourByteIntegersOneToSevenBitPrefixes) {
173   // Minimums.
174   EXPECT_EQ("\x7f\x80\x80\x01", EncodeUint32(7, 0x407f));
175   EXPECT_EQ("\x3f\x80\x80\x01", EncodeUint32(6, 0x403f));
176   EXPECT_EQ("\x1f\x80\x80\x01", EncodeUint32(5, 0x401f));
177   EXPECT_EQ("\x0f\x80\x80\x01", EncodeUint32(4, 0x400f));
178   EXPECT_EQ("\x07\x80\x80\x01", EncodeUint32(3, 0x4007));
179   EXPECT_EQ("\x03\x80\x80\x01", EncodeUint32(2, 0x4003));
180   EXPECT_EQ("\x01\x80\x80\x01", EncodeUint32(1, 0x4001));
181 
182   // Maximums.
183   EXPECT_EQ("\x7f\xff\xff\x7f", EncodeUint32(7, 0x20007e));
184   EXPECT_EQ("\x3f\xff\xff\x7f", EncodeUint32(6, 0x20003e));
185   EXPECT_EQ("\x1f\xff\xff\x7f", EncodeUint32(5, 0x20001e));
186   EXPECT_EQ("\x0f\xff\xff\x7f", EncodeUint32(4, 0x20000e));
187   EXPECT_EQ("\x07\xff\xff\x7f", EncodeUint32(3, 0x200006));
188   EXPECT_EQ("\x03\xff\xff\x7f", EncodeUint32(2, 0x200002));
189   EXPECT_EQ("\x01\xff\xff\x7f", EncodeUint32(1, 0x200000));
190 }
191 
TEST(HpackOutputStreamTest,FiveByteIntegersOneToSevenBitPrefixes)192 TEST(HpackOutputStreamTest, FiveByteIntegersOneToSevenBitPrefixes) {
193   // Minimums.
194   EXPECT_EQ("\x7f\x80\x80\x80\x01", EncodeUint32(7, 0x20007f));
195   EXPECT_EQ("\x3f\x80\x80\x80\x01", EncodeUint32(6, 0x20003f));
196   EXPECT_EQ("\x1f\x80\x80\x80\x01", EncodeUint32(5, 0x20001f));
197   EXPECT_EQ("\x0f\x80\x80\x80\x01", EncodeUint32(4, 0x20000f));
198   EXPECT_EQ("\x07\x80\x80\x80\x01", EncodeUint32(3, 0x200007));
199   EXPECT_EQ("\x03\x80\x80\x80\x01", EncodeUint32(2, 0x200003));
200   EXPECT_EQ("\x01\x80\x80\x80\x01", EncodeUint32(1, 0x200001));
201 
202   // Maximums.
203   EXPECT_EQ("\x7f\xff\xff\xff\x7f", EncodeUint32(7, 0x1000007e));
204   EXPECT_EQ("\x3f\xff\xff\xff\x7f", EncodeUint32(6, 0x1000003e));
205   EXPECT_EQ("\x1f\xff\xff\xff\x7f", EncodeUint32(5, 0x1000001e));
206   EXPECT_EQ("\x0f\xff\xff\xff\x7f", EncodeUint32(4, 0x1000000e));
207   EXPECT_EQ("\x07\xff\xff\xff\x7f", EncodeUint32(3, 0x10000006));
208   EXPECT_EQ("\x03\xff\xff\xff\x7f", EncodeUint32(2, 0x10000002));
209   EXPECT_EQ("\x01\xff\xff\xff\x7f", EncodeUint32(1, 0x10000000));
210 }
211 
TEST(HpackOutputStreamTest,SixByteIntegersOneToSevenBitPrefixes)212 TEST(HpackOutputStreamTest, SixByteIntegersOneToSevenBitPrefixes) {
213   // Minimums.
214   EXPECT_EQ("\x7f\x80\x80\x80\x80\x01", EncodeUint32(7, 0x1000007f));
215   EXPECT_EQ("\x3f\x80\x80\x80\x80\x01", EncodeUint32(6, 0x1000003f));
216   EXPECT_EQ("\x1f\x80\x80\x80\x80\x01", EncodeUint32(5, 0x1000001f));
217   EXPECT_EQ("\x0f\x80\x80\x80\x80\x01", EncodeUint32(4, 0x1000000f));
218   EXPECT_EQ("\x07\x80\x80\x80\x80\x01", EncodeUint32(3, 0x10000007));
219   EXPECT_EQ("\x03\x80\x80\x80\x80\x01", EncodeUint32(2, 0x10000003));
220   EXPECT_EQ("\x01\x80\x80\x80\x80\x01", EncodeUint32(1, 0x10000001));
221 
222   // Maximums.
223   EXPECT_EQ("\x7f\x80\xff\xff\xff\x0f", EncodeUint32(7, 0xffffffff));
224   EXPECT_EQ("\x3f\xc0\xff\xff\xff\x0f", EncodeUint32(6, 0xffffffff));
225   EXPECT_EQ("\x1f\xe0\xff\xff\xff\x0f", EncodeUint32(5, 0xffffffff));
226   EXPECT_EQ("\x0f\xf0\xff\xff\xff\x0f", EncodeUint32(4, 0xffffffff));
227   EXPECT_EQ("\x07\xf8\xff\xff\xff\x0f", EncodeUint32(3, 0xffffffff));
228   EXPECT_EQ("\x03\xfc\xff\xff\xff\x0f", EncodeUint32(2, 0xffffffff));
229   EXPECT_EQ("\x01\xfe\xff\xff\xff\x0f", EncodeUint32(1, 0xffffffff));
230 }
231 
232 // Test that encoding an integer with an N-bit prefix preserves the
233 // upper (8-N) bits of the first byte.
TEST(HpackOutputStreamTest,AppendUint32PreservesUpperBits)234 TEST(HpackOutputStreamTest, AppendUint32PreservesUpperBits) {
235   HpackOutputStream output_stream;
236   output_stream.AppendBits(0x7f, 7);
237   output_stream.AppendUint32(0x01);
238   std::string str = output_stream.TakeString();
239   EXPECT_EQ(std::string("\xff\x00", 2), str);
240 }
241 
TEST(HpackOutputStreamTest,AppendBytes)242 TEST(HpackOutputStreamTest, AppendBytes) {
243   HpackOutputStream output_stream;
244 
245   output_stream.AppendBytes("buffer1");
246   output_stream.AppendBytes("buffer2");
247 
248   std::string str = output_stream.TakeString();
249   EXPECT_EQ("buffer1buffer2", str);
250 }
251 
TEST(HpackOutputStreamTest,BoundedTakeString)252 TEST(HpackOutputStreamTest, BoundedTakeString) {
253   HpackOutputStream output_stream;
254 
255   output_stream.AppendBytes("buffer12");
256   output_stream.AppendBytes("buffer456");
257 
258   std::string str = output_stream.BoundedTakeString(9);
259   EXPECT_EQ("buffer12b", str);
260 
261   output_stream.AppendBits(0x7f, 7);
262   output_stream.AppendUint32(0x11);
263   str = output_stream.BoundedTakeString(9);
264   EXPECT_EQ("uffer456\xff", str);
265 
266   str = output_stream.BoundedTakeString(9);
267   EXPECT_EQ("\x10", str);
268 }
269 
TEST(HpackOutputStreamTest,MutableString)270 TEST(HpackOutputStreamTest, MutableString) {
271   HpackOutputStream output_stream;
272 
273   output_stream.AppendBytes("1");
274   output_stream.MutableString()->append("2");
275 
276   output_stream.AppendBytes("foo");
277   output_stream.MutableString()->append("bar");
278 
279   std::string str = output_stream.TakeString();
280   EXPECT_EQ("12foobar", str);
281 }
282 
283 }  // namespace
284 
285 }  // namespace spdy
286