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_decoder.h"
10 #include "base/basictypes.h"
11 #include "base/strings/string_piece.h"
12 #include "net/spdy/hpack_encoder.h"
13 #include "net/spdy/hpack_input_stream.h"
14 #include "testing/gtest/include/gtest/gtest.h"
20 using base::StringPiece
;
23 // Decoding an encoded name with a valid string literal should work.
24 TEST(HpackDecoderTest
, DecodeNextNameLiteral
) {
25 HpackDecoder
decoder(kuint32max
);
26 HpackInputStream
input_stream(kuint32max
, StringPiece("\x00\x04name", 6));
28 StringPiece string_piece
;
29 EXPECT_TRUE(decoder
.DecodeNextNameForTest(&input_stream
, &string_piece
));
30 EXPECT_EQ("name", string_piece
);
31 EXPECT_FALSE(input_stream
.HasMoreData());
34 // Decoding an encoded name with a valid index should work.
35 TEST(HpackDecoderTest
, DecodeNextNameIndexed
) {
36 HpackDecoder
decoder(kuint32max
);
37 HpackInputStream
input_stream(kuint32max
, "\x01");
39 StringPiece string_piece
;
40 EXPECT_TRUE(decoder
.DecodeNextNameForTest(&input_stream
, &string_piece
));
41 EXPECT_EQ(":authority", string_piece
);
42 EXPECT_FALSE(input_stream
.HasMoreData());
45 // Decoding an encoded name with an invalid index should fail.
46 TEST(HpackDecoderTest
, DecodeNextNameInvalidIndex
) {
47 // One more than the number of static table entries.
48 HpackDecoder
decoder(kuint32max
);
49 HpackInputStream
input_stream(kuint32max
, "\x3d");
51 StringPiece string_piece
;
52 EXPECT_FALSE(decoder
.DecodeNextNameForTest(&input_stream
, &string_piece
));
55 // Utility function to decode a string into a header set, assuming
56 // that the emitted headers have unique names.
57 std::map
<string
, string
> DecodeUniqueHeaderSet(
58 HpackDecoder
* decoder
, StringPiece str
) {
59 HpackHeaderPairVector header_list
;
60 EXPECT_TRUE(decoder
->DecodeHeaderSet(str
, &header_list
));
61 std::map
<string
, string
> header_set(
62 header_list
.begin(), header_list
.end());
63 // Make sure |header_list| has no duplicates.
64 EXPECT_EQ(header_set
.size(), header_list
.size());
68 // Decoding an indexed header should toggle the index's presence in
69 // the reference set, making a copy of static table entries if
70 // necessary. It should also emit the header if toggled on (and only
71 // as many times as it was toggled on).
72 TEST(HpackDecoderTest
, IndexedHeaderBasic
) {
73 HpackDecoder
decoder(kuint32max
);
75 // Toggle on static table entry #2 (and make a copy at index #1),
76 // then toggle on static table entry #5 (which is now #6 because of
78 std::map
<string
, string
> header_set1
=
79 DecodeUniqueHeaderSet(&decoder
, "\x82\x86");
80 std::map
<string
, string
> expected_header_set1
;
81 expected_header_set1
[":method"] = "GET";
82 expected_header_set1
[":path"] = "/index.html";
83 EXPECT_EQ(expected_header_set1
, header_set1
);
85 std::map
<string
, string
> expected_header_set2
;
86 expected_header_set2
[":path"] = "/index.html";
87 // Toggle off the copy of static table entry #5.
88 std::map
<string
, string
> header_set2
=
89 DecodeUniqueHeaderSet(&decoder
, "\x82");
90 EXPECT_EQ(expected_header_set2
, header_set2
);
93 // Decoding an indexed header with index 0 should clear the reference
95 TEST(HpackDecoderTest
, IndexedHeaderZero
) {
96 HpackDecoder
decoder(kuint32max
);
98 // Toggle on a couple of headers.
99 std::map
<string
, string
> header_set1
=
100 DecodeUniqueHeaderSet(&decoder
, "\x82\x86");
101 std::map
<string
, string
> expected_header_set1
;
102 expected_header_set1
[":method"] = "GET";
103 expected_header_set1
[":path"] = "/index.html";
104 EXPECT_EQ(expected_header_set1
, header_set1
);
106 // Toggle index 0 to clear the reference set.
107 std::map
<string
, string
> header_set2
=
108 DecodeUniqueHeaderSet(&decoder
, "\x80");
109 std::map
<string
, string
> expected_header_set2
;
110 EXPECT_EQ(expected_header_set2
, header_set2
);
113 // Decoding two valid encoded literal headers with no indexing should
115 TEST(HpackDecoderTest
, LiteralHeaderNoIndexing
) {
116 HpackDecoder
decoder(kuint32max
);
117 HpackHeaderPairVector header_list
;
118 // First header with indexed name, second header with string literal
120 std::map
<string
, string
> header_set
=
121 DecodeUniqueHeaderSet(
122 &decoder
, "\x44\x0c/sample/path\x40\x06:path2\x0e/sample/path/2");
124 std::map
<string
, string
> expected_header_set
;
125 expected_header_set
[":path"] = "/sample/path";
126 expected_header_set
[":path2"] = "/sample/path/2";
127 EXPECT_EQ(expected_header_set
, header_set
);
130 // Decoding two valid encoded literal headers with incremental
131 // indexing and string literal names should work and add the headers
132 // to the reference set.
133 TEST(HpackDecoderTest
, LiteralHeaderIncrementalIndexing
) {
134 HpackDecoder
decoder(kuint32max
);
135 std::map
<string
, string
> header_set
= DecodeUniqueHeaderSet(
137 StringPiece("\x04\x0c/sample/path\x00\x06:path2\x0e/sample/path/2", 37));
139 std::map
<string
, string
> expected_header_set
;
140 expected_header_set
[":path"] = "/sample/path";
141 expected_header_set
[":path2"] = "/sample/path/2";
142 EXPECT_EQ(expected_header_set
, header_set
);
144 // Decoding an empty string should just return the reference set.
145 std::map
<string
, string
> header_set2
= DecodeUniqueHeaderSet(&decoder
, "");
146 EXPECT_EQ(expected_header_set
, header_set2
);
149 // Decoding literal headers with invalid indices should fail
151 TEST(HpackDecoderTest
, LiteralHeaderInvalidIndices
) {
152 HpackDecoder
decoder(kuint32max
);
154 HpackHeaderPairVector header_list
;
158 // One more than the number of static table entries.
159 EXPECT_FALSE(decoder
.DecodeHeaderSet(StringPiece("\x7d", 1), &header_list
));
160 EXPECT_FALSE(decoder
.DecodeHeaderSet(StringPiece("\x40", 1), &header_list
));
162 // Incremental indexing.
164 // One more than the number of static table entries.
165 EXPECT_FALSE(decoder
.DecodeHeaderSet(StringPiece("\x3d", 1), &header_list
));
166 EXPECT_FALSE(decoder
.DecodeHeaderSet(StringPiece("\x00", 1), &header_list
));
169 // Round-tripping the header set from E.2.1 should work.
170 TEST(HpackDecoderTest
, BasicE21
) {
171 HpackEncoder
encoder(kuint32max
);
173 std::map
<string
, string
> expected_header_set
;
174 expected_header_set
[":method"] = "GET";
175 expected_header_set
[":scheme"] = "http";
176 expected_header_set
[":path"] = "/";
177 expected_header_set
[":authority"] = "www.example.com";
179 string encoded_header_set
;
180 EXPECT_TRUE(encoder
.EncodeHeaderSet(
181 expected_header_set
, &encoded_header_set
));
183 HpackDecoder
decoder(kuint32max
);
184 HpackHeaderPairVector header_list
;
185 EXPECT_TRUE(decoder
.DecodeHeaderSet(encoded_header_set
, &header_list
));
186 std::map
<string
, string
> header_set(header_list
.begin(), header_list
.end());
187 EXPECT_EQ(expected_header_set
, header_set
);