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.
5 #include "net/spdy/hpack_encoding_context.h"
9 #include "base/basictypes.h"
10 #include "net/spdy/hpack_constants.h"
11 #include "testing/gtest/include/gtest/gtest.h"
17 class HpackEncodingContextPeer
{
19 explicit HpackEncodingContextPeer(const HpackEncodingContext
& context
)
20 : context_(context
) {}
22 const HpackHeaderTable
& header_table() {
23 return context_
.header_table_
;
25 uint32
settings_header_table_size() {
26 return context_
.settings_header_table_size_
;
30 const HpackEncodingContext
& context_
;
37 TEST(HpackEncodingContextTest
, ApplyHeaderTableSizeSetting
) {
38 HpackEncodingContext context
;
39 test::HpackEncodingContextPeer
peer(context
);
41 // Default setting and table size are kDefaultHeaderTableSizeSetting.
42 EXPECT_EQ(kDefaultHeaderTableSizeSetting
,
43 peer
.settings_header_table_size());
44 EXPECT_EQ(kDefaultHeaderTableSizeSetting
,
45 peer
.header_table().max_size());
47 // Applying a larger table size setting doesn't affect the headers table.
48 context
.ApplyHeaderTableSizeSetting(kDefaultHeaderTableSizeSetting
* 2);
50 EXPECT_EQ(kDefaultHeaderTableSizeSetting
* 2,
51 peer
.settings_header_table_size());
52 EXPECT_EQ(kDefaultHeaderTableSizeSetting
,
53 peer
.header_table().max_size());
55 // Applying a smaller size setting does update the headers table.
56 context
.ApplyHeaderTableSizeSetting(kDefaultHeaderTableSizeSetting
/ 2);
58 EXPECT_EQ(kDefaultHeaderTableSizeSetting
/ 2,
59 peer
.settings_header_table_size());
60 EXPECT_EQ(kDefaultHeaderTableSizeSetting
/ 2,
61 peer
.header_table().max_size());
64 TEST(HpackEncodingContextTest
, ProcessContextUpdateNewMaximumSize
) {
65 HpackEncodingContext context
;
66 test::HpackEncodingContextPeer
peer(context
);
68 EXPECT_EQ(kDefaultHeaderTableSizeSetting
,
69 peer
.settings_header_table_size());
71 // Shrink maximum size by half. Succeeds.
72 EXPECT_TRUE(context
.ProcessContextUpdateNewMaximumSize(
73 kDefaultHeaderTableSizeSetting
/ 2));
74 EXPECT_EQ(kDefaultHeaderTableSizeSetting
/ 2,
75 peer
.header_table().max_size());
77 // Double maximum size. Succeeds.
78 EXPECT_TRUE(context
.ProcessContextUpdateNewMaximumSize(
79 kDefaultHeaderTableSizeSetting
));
80 EXPECT_EQ(kDefaultHeaderTableSizeSetting
, peer
.header_table().max_size());
82 // One beyond table size setting. Fails.
83 EXPECT_FALSE(context
.ProcessContextUpdateNewMaximumSize(
84 kDefaultHeaderTableSizeSetting
+ 1));
85 EXPECT_EQ(kDefaultHeaderTableSizeSetting
, peer
.header_table().max_size());
88 // Try to process an indexed header with an index for a static
89 // header. That should succeed and add a mutable copy into the header
91 TEST(HpackEncodingContextTest
, IndexedHeaderStatic
) {
92 HpackEncodingContext encoding_context
;
94 std::string name
= encoding_context
.GetNameAt(2).as_string();
95 std::string value
= encoding_context
.GetValueAt(2).as_string();
96 EXPECT_EQ(0u, encoding_context
.GetMutableEntryCount());
97 EXPECT_NE(name
, encoding_context
.GetNameAt(1));
98 EXPECT_NE(value
, encoding_context
.GetValueAt(1));
101 uint32 new_index
= 0;
102 std::vector
<uint32
> removed_referenced_indices
;
104 encoding_context
.ProcessIndexedHeader(2,
106 &removed_referenced_indices
));
107 EXPECT_EQ(1u, new_index
);
108 EXPECT_TRUE(removed_referenced_indices
.empty());
110 EXPECT_EQ(1u, encoding_context
.GetMutableEntryCount());
111 EXPECT_EQ(name
, encoding_context
.GetNameAt(1));
112 EXPECT_EQ(value
, encoding_context
.GetValueAt(1));
113 EXPECT_TRUE(encoding_context
.IsReferencedAt(1));
116 uint32 new_index
= 0;
117 std::vector
<uint32
> removed_referenced_indices
;
119 encoding_context
.ProcessIndexedHeader(1,
121 &removed_referenced_indices
));
122 EXPECT_EQ(1u, new_index
);
123 EXPECT_TRUE(removed_referenced_indices
.empty());
125 EXPECT_EQ(1u, encoding_context
.GetMutableEntryCount());
126 EXPECT_EQ(name
, encoding_context
.GetNameAt(1));
127 EXPECT_EQ(value
, encoding_context
.GetValueAt(1));
128 EXPECT_LE(1u, encoding_context
.GetMutableEntryCount());
129 EXPECT_FALSE(encoding_context
.IsReferencedAt(1));
132 // Try to process an indexed header with an index for a static header
133 // and an encoding context where a copy of that header wouldn't
134 // fit. That should succeed without making a copy.
135 TEST(HpackEncodingContextTest
, IndexedHeaderStaticCopyDoesNotFit
) {
136 HpackEncodingContext encoding_context
;
137 encoding_context
.ProcessContextUpdateNewMaximumSize(0);
139 uint32 new_index
= 0;
140 std::vector
<uint32
> removed_referenced_indices
;
142 encoding_context
.ProcessIndexedHeader(1,
144 &removed_referenced_indices
));
145 EXPECT_EQ(0u, new_index
);
146 EXPECT_TRUE(removed_referenced_indices
.empty());
147 EXPECT_EQ(0u, encoding_context
.GetMutableEntryCount());
150 // Add a bunch of new headers and then process a context update to empty the
151 // reference set. Expect it to be empty.
152 TEST(HpackEncodingContextTest
, ProcessContextUpdateEmptyReferenceSet
) {
153 HpackEncodingContext encoding_context
;
154 test::HpackEncodingContextPeer
peer(encoding_context
);
156 uint32 kEntryCount
= 50;
158 for (uint32 i
= 1; i
<= kEntryCount
; ++i
) {
159 uint32 new_index
= 0;
160 std::vector
<uint32
> removed_referenced_indices
;
162 encoding_context
.ProcessIndexedHeader(i
,
164 &removed_referenced_indices
));
165 EXPECT_EQ(1u, new_index
);
166 EXPECT_TRUE(removed_referenced_indices
.empty());
167 EXPECT_EQ(i
, encoding_context
.GetMutableEntryCount());
170 for (uint32 i
= 1; i
<= kEntryCount
; ++i
) {
171 EXPECT_TRUE(peer
.header_table().GetEntry(i
).IsReferenced());
173 encoding_context
.ProcessContextUpdateEmptyReferenceSet();
174 for (uint32 i
= 1; i
<= kEntryCount
; ++i
) {
175 EXPECT_FALSE(peer
.header_table().GetEntry(i
).IsReferenced());
179 // NOTE: It's too onerous to try to test invalid input to
180 // ProcessLiteralHeaderWithIncrementalIndexing(); that would require
181 // making a really large (>4GB of memory) string.
183 // Try to process a reasonably-sized literal header with incremental
184 // indexing. It should succeed.
185 TEST(HpackEncodingContextTest
, LiteralHeaderIncrementalIndexing
) {
186 HpackEncodingContext encoding_context
;
189 std::vector
<uint32
> removed_referenced_indices
;
191 encoding_context
.ProcessLiteralHeaderWithIncrementalIndexing(
192 "name", "value", &index
, &removed_referenced_indices
));
193 EXPECT_EQ(1u, index
);
194 EXPECT_TRUE(removed_referenced_indices
.empty());
195 EXPECT_EQ("name", encoding_context
.GetNameAt(1).as_string());
196 EXPECT_EQ("value", encoding_context
.GetValueAt(1).as_string());
197 EXPECT_TRUE(encoding_context
.IsReferencedAt(1));
198 EXPECT_EQ(1u, encoding_context
.GetMutableEntryCount());
201 // Try to process a literal header with incremental indexing that is
202 // too large for the header table. It should succeed without indexing
204 TEST(HpackEncodingContextTest
, LiteralHeaderIncrementalIndexingDoesNotFit
) {
205 HpackEncodingContext encoding_context
;
206 encoding_context
.ProcessContextUpdateNewMaximumSize(0);
209 std::vector
<uint32
> removed_referenced_indices
;
211 encoding_context
.ProcessLiteralHeaderWithIncrementalIndexing(
212 "name", "value", &index
, &removed_referenced_indices
));
213 EXPECT_EQ(0u, index
);
214 EXPECT_TRUE(removed_referenced_indices
.empty());
215 EXPECT_EQ(0u, encoding_context
.GetMutableEntryCount());