blob: ceeebcae48adc7c4cbd47443fc855da5ee09b5eb [file] [log] [blame]
QUICHE teamfd50a402018-12-07 22:54:05 -05001// Copyright 2016 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 "net/third_party/quiche/src/http2/hpack/decoder/hpack_string_decoder.h"
6
7// Tests of HpackStringDecoder.
8
9#include "testing/gtest/include/gtest/gtest.h"
10#include "net/third_party/quiche/src/http2/hpack/decoder/hpack_string_collector.h"
11#include "net/third_party/quiche/src/http2/hpack/decoder/hpack_string_decoder_listener.h"
12#include "net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder.h"
13#include "net/third_party/quiche/src/http2/platform/api/http2_string_piece.h"
14#include "net/third_party/quiche/src/http2/platform/api/http2_test_helpers.h"
15#include "net/third_party/quiche/src/http2/test_tools/http2_random.h"
16#include "net/third_party/quiche/src/http2/tools/random_decoder_test.h"
17
18using ::testing::AssertionResult;
19
20namespace http2 {
21namespace test {
22namespace {
23
24const bool kMayReturnZeroOnFirst = false;
25const bool kCompressed = true;
26const bool kUncompressed = false;
27
28class HpackStringDecoderTest : public RandomDecoderTest {
29 protected:
30 HpackStringDecoderTest() : listener_(&collector_) {}
31
32 DecodeStatus StartDecoding(DecodeBuffer* b) override {
33 ++start_decoding_calls_;
34 collector_.Clear();
35 return decoder_.Start(b, &listener_);
36 }
37
38 DecodeStatus ResumeDecoding(DecodeBuffer* b) override {
39 // Provides coverage of DebugString and StateToString.
40 // Not validating output.
QUICHE team61940b42019-03-07 23:32:27 -050041 HTTP2_VLOG(1) << decoder_.DebugString();
42 HTTP2_VLOG(2) << collector_;
QUICHE teamfd50a402018-12-07 22:54:05 -050043 return decoder_.Resume(b, &listener_);
44 }
45
46 AssertionResult Collected(Http2StringPiece s, bool huffman_encoded) {
QUICHE team61940b42019-03-07 23:32:27 -050047 HTTP2_VLOG(1) << collector_;
QUICHE teamfd50a402018-12-07 22:54:05 -050048 return collector_.Collected(s, huffman_encoded);
49 }
50
bnc47904002019-08-16 11:49:48 -070051 // expected_str is a std::string rather than a const std::string& or
QUICHE teamfd50a402018-12-07 22:54:05 -050052 // Http2StringPiece so that the lambda makes a copy of the string, and thus
53 // the string to be passed to Collected outlives the call to MakeValidator.
bnc47904002019-08-16 11:49:48 -070054 Validator MakeValidator(const std::string& expected_str,
QUICHE teamfd50a402018-12-07 22:54:05 -050055 bool expected_huffman) {
56 return
57 [expected_str, expected_huffman, this](
58 const DecodeBuffer& input, DecodeStatus status) -> AssertionResult {
59 AssertionResult result = Collected(expected_str, expected_huffman);
60 if (result) {
61 VERIFY_EQ(collector_,
62 HpackStringCollector(expected_str, expected_huffman));
63 } else {
64 VERIFY_NE(collector_,
65 HpackStringCollector(expected_str, expected_huffman));
66 }
QUICHE team61940b42019-03-07 23:32:27 -050067 HTTP2_VLOG(2) << collector_.ToString();
QUICHE teamfd50a402018-12-07 22:54:05 -050068 collector_.Clear();
QUICHE team61940b42019-03-07 23:32:27 -050069 HTTP2_VLOG(2) << collector_;
QUICHE teamfd50a402018-12-07 22:54:05 -050070 return result;
71 };
72 }
73
74 HpackStringDecoder decoder_;
75 HpackStringCollector collector_;
76 HpackStringDecoderVLoggingListener listener_;
77 size_t start_decoding_calls_ = 0;
78};
79
80TEST_F(HpackStringDecoderTest, DecodeEmptyString) {
81 {
82 Validator validator = ValidateDoneAndEmpty(MakeValidator("", kCompressed));
83 const char kData[] = {'\x80'};
84 DecodeBuffer b(kData);
85 EXPECT_TRUE(
86 DecodeAndValidateSeveralWays(&b, kMayReturnZeroOnFirst, validator));
87 }
88 {
89 // Make sure it stops after decoding the empty string.
90 Validator validator =
91 ValidateDoneAndOffset(1, MakeValidator("", kUncompressed));
92 const char kData[] = {'\x00', '\xff'};
93 DecodeBuffer b(kData);
94 EXPECT_EQ(2u, b.Remaining());
95 EXPECT_TRUE(
96 DecodeAndValidateSeveralWays(&b, kMayReturnZeroOnFirst, validator));
97 EXPECT_EQ(1u, b.Remaining());
98 }
99}
100
101TEST_F(HpackStringDecoderTest, DecodeShortString) {
102 {
103 // Make sure it stops after decoding the non-empty string.
104 Validator validator =
105 ValidateDoneAndOffset(11, MakeValidator("start end.", kCompressed));
106 const char kData[] = "\x8astart end.Don't peek at this.";
107 DecodeBuffer b(kData);
108 EXPECT_TRUE(
109 DecodeAndValidateSeveralWays(&b, kMayReturnZeroOnFirst, validator));
110 }
111 {
112 Validator validator =
113 ValidateDoneAndOffset(11, MakeValidator("start end.", kUncompressed));
114 Http2StringPiece data("\x0astart end.");
115 DecodeBuffer b(data);
116 EXPECT_TRUE(
117 DecodeAndValidateSeveralWays(&b, kMayReturnZeroOnFirst, validator));
118 }
119}
120
121TEST_F(HpackStringDecoderTest, DecodeLongStrings) {
bnc47904002019-08-16 11:49:48 -0700122 std::string name = Random().RandString(1024);
123 std::string value = Random().RandString(65536);
QUICHE teamfd50a402018-12-07 22:54:05 -0500124 HpackBlockBuilder hbb;
125
126 hbb.AppendString(false, name);
127 uint32_t offset_after_name = hbb.size();
128 EXPECT_EQ(3 + name.size(), offset_after_name);
129
130 hbb.AppendString(true, value);
131 uint32_t offset_after_value = hbb.size();
132 EXPECT_EQ(3 + name.size() + 4 + value.size(), offset_after_value);
133
134 DecodeBuffer b(hbb.buffer());
135
136 // Decode the name...
137 EXPECT_TRUE(DecodeAndValidateSeveralWays(
138 &b, kMayReturnZeroOnFirst,
139 ValidateDoneAndOffset(offset_after_name,
140 MakeValidator(name, kUncompressed))));
141 EXPECT_EQ(offset_after_name, b.Offset());
142 EXPECT_EQ(offset_after_value - offset_after_name, b.Remaining());
143
144 // Decode the value...
145 EXPECT_TRUE(DecodeAndValidateSeveralWays(
146 &b, kMayReturnZeroOnFirst,
147 ValidateDoneAndOffset(offset_after_value - offset_after_name,
148 MakeValidator(value, kCompressed))));
149 EXPECT_EQ(offset_after_value, b.Offset());
150 EXPECT_EQ(0u, b.Remaining());
151}
152
153} // namespace
154} // namespace test
155} // namespace http2