blob: abd1353608676e4139981e1555deb494c0356032 [file] [log] [blame]
// Copyright 2018 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/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
namespace quic {
namespace test {
namespace {
class QpackInstructionEncoderTest : public QuicTest {
protected:
QpackInstructionEncoderTest() : verified_position_(0) {}
~QpackInstructionEncoderTest() override = default;
// Append encoded |instruction| to |output_|.
void EncodeInstruction(const QpackInstruction* instruction,
const QpackInstructionEncoder::Values& values) {
encoder_.Encode(instruction, values, &output_);
}
// Compare substring appended to |output_| since last EncodedSegmentMatches()
// call against hex-encoded argument.
bool EncodedSegmentMatches(QuicStringPiece hex_encoded_expected_substring) {
auto recently_encoded = QuicStringPiece(output_).substr(verified_position_);
auto expected = QuicTextUtils::HexDecode(hex_encoded_expected_substring);
verified_position_ = output_.size();
return recently_encoded == expected;
}
private:
QpackInstructionEncoder encoder_;
std::string output_;
std::string::size_type verified_position_;
};
TEST_F(QpackInstructionEncoderTest, Varint) {
const QpackInstruction instruction{QpackInstructionOpcode{0x00, 0x80},
{{QpackInstructionFieldType::kVarint, 7}}};
QpackInstructionEncoder::Values values;
values.varint = 5;
EncodeInstruction(&instruction, values);
EXPECT_TRUE(EncodedSegmentMatches("05"));
values.varint = 127;
EncodeInstruction(&instruction, values);
EXPECT_TRUE(EncodedSegmentMatches("7f00"));
}
TEST_F(QpackInstructionEncoderTest, SBitAndTwoVarint2) {
const QpackInstruction instruction{
QpackInstructionOpcode{0x80, 0xc0},
{{QpackInstructionFieldType::kSbit, 0x20},
{QpackInstructionFieldType::kVarint, 5},
{QpackInstructionFieldType::kVarint2, 8}}};
QpackInstructionEncoder::Values values;
values.s_bit = true;
values.varint = 5;
values.varint2 = 200;
EncodeInstruction(&instruction, values);
EXPECT_TRUE(EncodedSegmentMatches("a5c8"));
values.s_bit = false;
values.varint = 31;
values.varint2 = 356;
EncodeInstruction(&instruction, values);
EXPECT_TRUE(EncodedSegmentMatches("9f00ff65"));
}
TEST_F(QpackInstructionEncoderTest, SBitAndVarintAndValue) {
const QpackInstruction instruction{QpackInstructionOpcode{0xc0, 0xc0},
{{QpackInstructionFieldType::kSbit, 0x20},
{QpackInstructionFieldType::kVarint, 5},
{QpackInstructionFieldType::kValue, 7}}};
QpackInstructionEncoder::Values values;
values.s_bit = true;
values.varint = 100;
values.value = "foo";
EncodeInstruction(&instruction, values);
EXPECT_TRUE(EncodedSegmentMatches("ff458294e7"));
values.s_bit = false;
values.varint = 3;
values.value = "bar";
EncodeInstruction(&instruction, values);
EXPECT_TRUE(EncodedSegmentMatches("c303626172"));
}
TEST_F(QpackInstructionEncoderTest, Name) {
const QpackInstruction instruction{QpackInstructionOpcode{0xe0, 0xe0},
{{QpackInstructionFieldType::kName, 4}}};
QpackInstructionEncoder::Values values;
values.name = "";
EncodeInstruction(&instruction, values);
EXPECT_TRUE(EncodedSegmentMatches("e0"));
values.name = "foo";
EncodeInstruction(&instruction, values);
EXPECT_TRUE(EncodedSegmentMatches("f294e7"));
values.name = "bar";
EncodeInstruction(&instruction, values);
EXPECT_TRUE(EncodedSegmentMatches("e3626172"));
}
TEST_F(QpackInstructionEncoderTest, Value) {
const QpackInstruction instruction{QpackInstructionOpcode{0xf0, 0xf0},
{{QpackInstructionFieldType::kValue, 3}}};
QpackInstructionEncoder::Values values;
values.value = "";
EncodeInstruction(&instruction, values);
EXPECT_TRUE(EncodedSegmentMatches("f0"));
values.value = "foo";
EncodeInstruction(&instruction, values);
EXPECT_TRUE(EncodedSegmentMatches("fa94e7"));
values.value = "bar";
EncodeInstruction(&instruction, values);
EXPECT_TRUE(EncodedSegmentMatches("f3626172"));
}
TEST_F(QpackInstructionEncoderTest, SBitAndNameAndValue) {
const QpackInstruction instruction{QpackInstructionOpcode{0xf0, 0xf0},
{{QpackInstructionFieldType::kSbit, 0x08},
{QpackInstructionFieldType::kName, 2},
{QpackInstructionFieldType::kValue, 7}}};
QpackInstructionEncoder::Values values;
values.s_bit = false;
values.name = "";
values.value = "";
EncodeInstruction(&instruction, values);
EXPECT_TRUE(EncodedSegmentMatches("f000"));
values.s_bit = true;
values.name = "foo";
values.value = "bar";
EncodeInstruction(&instruction, values);
EXPECT_TRUE(EncodedSegmentMatches("fe94e703626172"));
}
} // namespace
} // namespace test
} // namespace quic