| Index: net/http2/hpack/decoder/hpack_decoder_string_buffer_test.cc
|
| diff --git a/net/http2/hpack/decoder/hpack_decoder_string_buffer_test.cc b/net/http2/hpack/decoder/hpack_decoder_string_buffer_test.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..313a4570c432b3b7855c871968d5e7d673fb7701
|
| --- /dev/null
|
| +++ b/net/http2/hpack/decoder/hpack_decoder_string_buffer_test.cc
|
| @@ -0,0 +1,245 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "net/http2/hpack/decoder/hpack_decoder_string_buffer.h"
|
| +
|
| +// Tests of HpackDecoderStringBuffer.
|
| +
|
| +#include <initializer_list>
|
| +#include <sstream>
|
| +#include <string>
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/strings/string_piece.h"
|
| +#include "net/http2/tools/failure.h"
|
| +#include "net/spdy/spdy_test_utils.h"
|
| +#include "testing/gmock/include/gmock/gmock.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +using ::testing::AssertionResult;
|
| +using ::testing::AssertionSuccess;
|
| +using ::testing::HasSubstr;
|
| +using base::StringPiece;
|
| +using std::string;
|
| +
|
| +namespace net {
|
| +namespace test {
|
| +namespace {
|
| +
|
| +class HpackDecoderStringBufferTest : public ::testing::Test {
|
| + protected:
|
| + typedef HpackDecoderStringBuffer::State State;
|
| + typedef HpackDecoderStringBuffer::Backing Backing;
|
| +
|
| + State state() const { return buf_.state_for_testing(); }
|
| + Backing backing() const { return buf_.backing_for_testing(); }
|
| +
|
| + // We want to know that LOG(x) << buf_ will work in production should that
|
| + // be needed, so we test that it outputs the expected values.
|
| + AssertionResult VerifyLogHasSubstrs(std::initializer_list<string> strs) {
|
| + VLOG(1) << buf_;
|
| + std::ostringstream ss;
|
| + buf_.OutputDebugStringTo(ss);
|
| + string dbg_str(ss.str());
|
| + for (const auto& expected : strs) {
|
| + VERIFY_THAT(dbg_str, HasSubstr(expected));
|
| + }
|
| + return AssertionSuccess();
|
| + }
|
| +
|
| + HpackDecoderStringBuffer buf_;
|
| +};
|
| +
|
| +TEST_F(HpackDecoderStringBufferTest, SetStatic) {
|
| + StringPiece data("static string");
|
| +
|
| + EXPECT_EQ(state(), State::RESET);
|
| + EXPECT_TRUE(VerifyLogHasSubstrs({"state=RESET"}));
|
| +
|
| + buf_.Set(data, /*is_static*/ true);
|
| + LOG(INFO) << buf_;
|
| + EXPECT_EQ(state(), State::COMPLETE);
|
| + EXPECT_EQ(backing(), Backing::STATIC);
|
| + EXPECT_EQ(data, buf_.str());
|
| + EXPECT_EQ(data.data(), buf_.str().data());
|
| + EXPECT_TRUE(VerifyLogHasSubstrs(
|
| + {"state=COMPLETE", "backing=STATIC", "value: static string"}));
|
| +
|
| + // The string is static, so BufferStringIfUnbuffered won't change anything.
|
| + buf_.BufferStringIfUnbuffered();
|
| + EXPECT_EQ(state(), State::COMPLETE);
|
| + EXPECT_EQ(backing(), Backing::STATIC);
|
| + EXPECT_EQ(data, buf_.str());
|
| + EXPECT_EQ(data.data(), buf_.str().data());
|
| + EXPECT_TRUE(VerifyLogHasSubstrs(
|
| + {"state=COMPLETE", "backing=STATIC", "value: static string"}));
|
| +}
|
| +
|
| +TEST_F(HpackDecoderStringBufferTest, PlainWhole) {
|
| + StringPiece data("some text.");
|
| +
|
| + LOG(INFO) << buf_;
|
| + EXPECT_EQ(state(), State::RESET);
|
| +
|
| + buf_.OnStart(/*huffman_encoded*/ false, data.size());
|
| + EXPECT_EQ(state(), State::COLLECTING);
|
| + EXPECT_EQ(backing(), Backing::RESET);
|
| + LOG(INFO) << buf_;
|
| +
|
| + EXPECT_TRUE(buf_.OnData(data.data(), data.size()));
|
| + EXPECT_EQ(state(), State::COLLECTING);
|
| + EXPECT_EQ(backing(), Backing::UNBUFFERED);
|
| +
|
| + EXPECT_TRUE(buf_.OnEnd());
|
| + EXPECT_EQ(state(), State::COMPLETE);
|
| + EXPECT_EQ(backing(), Backing::UNBUFFERED);
|
| + EXPECT_EQ(0u, buf_.BufferedLength());
|
| + EXPECT_TRUE(VerifyLogHasSubstrs(
|
| + {"state=COMPLETE", "backing=UNBUFFERED", "value: some text."}));
|
| +
|
| + // We expect that the string buffer points to the passed in StringPiece's
|
| + // backing store.
|
| + EXPECT_EQ(data.data(), buf_.str().data());
|
| +
|
| + // Now force it to buffer the string, after which it will still have the same
|
| + // string value, but the backing store will be different.
|
| + buf_.BufferStringIfUnbuffered();
|
| + LOG(INFO) << buf_;
|
| + EXPECT_EQ(backing(), Backing::BUFFERED);
|
| + EXPECT_EQ(buf_.BufferedLength(), data.size());
|
| + EXPECT_EQ(data, buf_.str());
|
| + EXPECT_NE(data.data(), buf_.str().data());
|
| + EXPECT_TRUE(VerifyLogHasSubstrs(
|
| + {"state=COMPLETE", "backing=BUFFERED", "buffer: some text."}));
|
| +}
|
| +
|
| +TEST_F(HpackDecoderStringBufferTest, PlainSplit) {
|
| + StringPiece data("some text.");
|
| + StringPiece part1 = data.substr(0, 1);
|
| + StringPiece part2 = data.substr(1);
|
| +
|
| + EXPECT_EQ(state(), State::RESET);
|
| + buf_.OnStart(/*huffman_encoded*/ false, data.size());
|
| + EXPECT_EQ(state(), State::COLLECTING);
|
| + EXPECT_EQ(backing(), Backing::RESET);
|
| +
|
| + // OnData with only a part of the data, not the whole, so buf_ will buffer
|
| + // the data.
|
| + EXPECT_TRUE(buf_.OnData(part1.data(), part1.size()));
|
| + EXPECT_EQ(state(), State::COLLECTING);
|
| + EXPECT_EQ(backing(), Backing::BUFFERED);
|
| + EXPECT_EQ(buf_.BufferedLength(), part1.size());
|
| + LOG(INFO) << buf_;
|
| +
|
| + EXPECT_TRUE(buf_.OnData(part2.data(), part2.size()));
|
| + EXPECT_EQ(state(), State::COLLECTING);
|
| + EXPECT_EQ(backing(), Backing::BUFFERED);
|
| + EXPECT_EQ(buf_.BufferedLength(), data.size());
|
| +
|
| + EXPECT_TRUE(buf_.OnEnd());
|
| + EXPECT_EQ(state(), State::COMPLETE);
|
| + EXPECT_EQ(backing(), Backing::BUFFERED);
|
| + EXPECT_EQ(buf_.BufferedLength(), data.size());
|
| + LOG(INFO) << buf_;
|
| +
|
| + StringPiece buffered = buf_.str();
|
| + EXPECT_EQ(data, buffered);
|
| + EXPECT_NE(data.data(), buffered.data());
|
| +
|
| + // The string is already buffered, so BufferStringIfUnbuffered should not make
|
| + // any change.
|
| + buf_.BufferStringIfUnbuffered();
|
| + EXPECT_EQ(backing(), Backing::BUFFERED);
|
| + EXPECT_EQ(buf_.BufferedLength(), data.size());
|
| + EXPECT_EQ(buffered, buf_.str());
|
| + EXPECT_EQ(buffered.data(), buf_.str().data());
|
| +}
|
| +
|
| +TEST_F(HpackDecoderStringBufferTest, HuffmanWhole) {
|
| + string encoded = a2b_hex("f1e3c2e5f23a6ba0ab90f4ff");
|
| + StringPiece decoded("www.example.com");
|
| +
|
| + EXPECT_EQ(state(), State::RESET);
|
| + buf_.OnStart(/*huffman_encoded*/ true, encoded.size());
|
| + EXPECT_EQ(state(), State::COLLECTING);
|
| +
|
| + EXPECT_TRUE(buf_.OnData(encoded.data(), encoded.size()));
|
| + EXPECT_EQ(state(), State::COLLECTING);
|
| + EXPECT_EQ(backing(), Backing::BUFFERED);
|
| +
|
| + EXPECT_TRUE(buf_.OnEnd());
|
| + EXPECT_EQ(state(), State::COMPLETE);
|
| + EXPECT_EQ(backing(), Backing::BUFFERED);
|
| + EXPECT_EQ(buf_.BufferedLength(), decoded.size());
|
| + EXPECT_EQ(decoded, buf_.str());
|
| + EXPECT_TRUE(VerifyLogHasSubstrs(
|
| + {"{state=COMPLETE", "backing=BUFFERED", "buffer: www.example.com}"}));
|
| +}
|
| +
|
| +TEST_F(HpackDecoderStringBufferTest, HuffmanSplit) {
|
| + string encoded = a2b_hex("f1e3c2e5f23a6ba0ab90f4ff");
|
| + string part1 = encoded.substr(0, 5);
|
| + string part2 = encoded.substr(5);
|
| + StringPiece decoded("www.example.com");
|
| +
|
| + EXPECT_EQ(state(), State::RESET);
|
| + buf_.OnStart(/*huffman_encoded*/ true, encoded.size());
|
| + EXPECT_EQ(state(), State::COLLECTING);
|
| + EXPECT_EQ(backing(), Backing::BUFFERED);
|
| + EXPECT_EQ(0u, buf_.BufferedLength());
|
| + LOG(INFO) << buf_;
|
| +
|
| + EXPECT_TRUE(buf_.OnData(part1.data(), part1.size()));
|
| + EXPECT_EQ(state(), State::COLLECTING);
|
| + EXPECT_EQ(backing(), Backing::BUFFERED);
|
| + EXPECT_GT(buf_.BufferedLength(), 0u);
|
| + EXPECT_LT(buf_.BufferedLength(), decoded.size());
|
| + LOG(INFO) << buf_;
|
| +
|
| + EXPECT_TRUE(buf_.OnData(part2.data(), part2.size()));
|
| + EXPECT_EQ(state(), State::COLLECTING);
|
| + EXPECT_EQ(backing(), Backing::BUFFERED);
|
| + EXPECT_EQ(buf_.BufferedLength(), decoded.size());
|
| + LOG(INFO) << buf_;
|
| +
|
| + EXPECT_TRUE(buf_.OnEnd());
|
| + EXPECT_EQ(state(), State::COMPLETE);
|
| + EXPECT_EQ(backing(), Backing::BUFFERED);
|
| + EXPECT_EQ(buf_.BufferedLength(), decoded.size());
|
| + EXPECT_EQ(decoded, buf_.str());
|
| + LOG(INFO) << buf_;
|
| +}
|
| +
|
| +TEST_F(HpackDecoderStringBufferTest, InvalidHuffmanOnData) {
|
| + // Explicitly encode the End-of-String symbol, a no-no.
|
| + string encoded = a2b_hex("ffffffff");
|
| +
|
| + buf_.OnStart(/*huffman_encoded*/ true, encoded.size());
|
| + EXPECT_EQ(state(), State::COLLECTING);
|
| +
|
| + EXPECT_FALSE(buf_.OnData(encoded.data(), encoded.size()));
|
| + EXPECT_EQ(state(), State::COLLECTING);
|
| + EXPECT_EQ(backing(), Backing::BUFFERED);
|
| +
|
| + LOG(INFO) << buf_;
|
| +}
|
| +
|
| +TEST_F(HpackDecoderStringBufferTest, InvalidHuffmanOnEnd) {
|
| + // Last byte of string doesn't end with prefix of End-of-String symbol.
|
| + string encoded = a2b_hex("00");
|
| +
|
| + buf_.OnStart(/*huffman_encoded*/ true, encoded.size());
|
| + EXPECT_EQ(state(), State::COLLECTING);
|
| +
|
| + EXPECT_TRUE(buf_.OnData(encoded.data(), encoded.size()));
|
| + EXPECT_EQ(state(), State::COLLECTING);
|
| + EXPECT_EQ(backing(), Backing::BUFFERED);
|
| +
|
| + EXPECT_FALSE(buf_.OnEnd());
|
| + LOG(INFO) << buf_;
|
| +}
|
| +
|
| +} // namespace
|
| +} // namespace test
|
| +} // namespace net
|
|
|