Commit 42dc140e authored by bnc's avatar bnc Committed by Commit bot

Add SpdyDeframerVisitor.

SpdyDeframerVisitor reconstructs SpdyFrameIR instances from callbacks to
SpdyFramerVisitorInterface.

This CL lands server changes 122860864, 122867216, 126441874, and 126727481
by jamessynge.

BUG=488484

Review-Url: https://codereview.chromium.org/2248343004
Cr-Commit-Position: refs/heads/master@{#412805}
parent 7f3b02f9
......@@ -1797,6 +1797,9 @@
'spdy/priority_write_scheduler_test.cc',
'spdy/spdy_alt_svc_wire_format_test.cc',
'spdy/spdy_buffer_unittest.cc',
'spdy/spdy_deframer_visitor.cc',
'spdy/spdy_deframer_visitor.h',
'spdy/spdy_deframer_visitor_test.cc',
'spdy/spdy_frame_builder_test.cc',
'spdy/spdy_frame_reader_test.cc',
'spdy/spdy_framer_test.cc',
......@@ -1810,6 +1813,8 @@
'spdy/spdy_pinnable_buffer_piece_test.cc',
'spdy/spdy_prefixed_buffer_reader_test.cc',
'spdy/spdy_protocol_test.cc',
'spdy/spdy_protocol_test_utils.cc',
'spdy/spdy_protocol_test_utils.h',
'spdy/spdy_proxy_client_socket_unittest.cc',
'spdy/spdy_read_queue_unittest.cc',
'spdy/spdy_session_pool_unittest.cc',
......
This diff is collapsed.
This diff is collapsed.
// 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/spdy/spdy_deframer_visitor.h"
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <limits>
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/rand_util.h"
#include "base/strings/string_piece.h"
#include "net/spdy/hpack/hpack_constants.h"
#include "net/spdy/mock_spdy_framer_visitor.h"
#include "net/spdy/spdy_frame_builder.h"
#include "net/spdy/spdy_frame_reader.h"
#include "net/spdy/spdy_protocol.h"
#include "net/spdy/spdy_protocol_test_utils.h"
#include "net/spdy/spdy_test_utils.h"
using ::base::MakeUnique;
using ::std::string;
namespace net {
namespace test {
namespace {
class SpdyDeframerVisitorTest : public ::testing::Test {
protected:
SpdyDeframerVisitorTest() : encoder_(HTTP2), decoder_(HTTP2) {
decoder_.set_process_single_input_frame(true);
decoder_.set_use_new_methods_for_test(true);
auto collector = MakeUnique<DeframerCallbackCollector>(&collected_frames_);
auto log_and_collect =
SpdyDeframerVisitorInterface::LogBeforeVisiting(std::move(collector));
deframer_ = SpdyTestDeframer::CreateConverter(std::move(log_and_collect));
decoder_.set_visitor(deframer_.get());
}
bool DeframeInput(const char* input, size_t size) {
size_t input_remaining = size;
while (input_remaining > 0 &&
decoder_.error_code() == SpdyFramer::SPDY_NO_ERROR) {
// To make the tests more interesting, we feed random (and small) chunks
// into the framer. This simulates getting strange-sized reads from
// the socket.
const size_t kMaxReadSize = 32;
size_t bytes_read =
(base::RandGenerator(std::min(input_remaining, kMaxReadSize))) + 1;
size_t bytes_processed = decoder_.ProcessInput(input, bytes_read);
input_remaining -= bytes_processed;
input += bytes_processed;
if (decoder_.state() == SpdyFramer::SPDY_READY_FOR_FRAME) {
deframer_->AtFrameEnd();
}
}
return (input_remaining == 0 &&
decoder_.error_code() == SpdyFramer::SPDY_NO_ERROR);
}
SpdySerializedFrame SerializeFrame(const SpdyFrameIR& frame) {
return encoder_.SerializeFrame(frame);
}
string SerializeFrames(
const std::vector<std::unique_ptr<SpdyFrameIR>>& frames) {
string result;
for (const auto& frame_ptr : frames) {
auto sf = SerializeFrame(*frame_ptr);
base::StringPiece(sf.data(), sf.size()).AppendToString(&result);
}
return result;
}
// bool
SpdyFramer encoder_;
SpdyFramer decoder_;
std::vector<CollectedFrame> collected_frames_;
std::unique_ptr<SpdyTestDeframer> deframer_;
};
TEST_F(SpdyDeframerVisitorTest, DataFrame) {
const char kFrameData[] = {
0x00, 0x00, 0x0d, // Length = 13.
0x00, // DATA
0x08, // PADDED
0x00, 0x00, 0x00, 0x01, // Stream 1
0x07, // Pad length field.
'h', 'e', 'l', 'l', // Data
'o', // More Data
0x00, 0x00, 0x00, 0x00, // Padding
0x00, 0x00, 0x00 // More Padding
};
EXPECT_TRUE(DeframeInput(kFrameData, sizeof kFrameData));
ASSERT_EQ(1u, collected_frames_.size());
const CollectedFrame& cf0 = collected_frames_[0];
ASSERT_NE(cf0.frame_ir, nullptr);
SpdyDataIR expected_ir(1, "hello");
expected_ir.set_padding_len(8);
EXPECT_TRUE(cf0.VerifyHasFrame(expected_ir));
}
TEST_F(SpdyDeframerVisitorTest, HeaderFrameWithContinuation) {
const char kFrameData[] = {
0x00, 0x00, 0x05, // Payload Length: 5
0x01, // Type: HEADERS
0x09, // Flags: PADDED | END_STREAM
0x00, 0x00, 0x00, 0x01, // Stream: 1
0x04, // Padding Length: 4
0x00, 0x00, 0x00, 0x00, // Padding
/* Second Frame */
0x00, 0x00, 0x12, // Payload Length: 18
0x09, // Type: CONTINUATION
0x04, // Flags: END_HEADERS
0x00, 0x00, 0x00, 0x01, // Stream: 1
0x00, // Unindexed, literal name & value
0x03, 0x62, 0x61, 0x72, // Name len and name (3, "bar")
0x03, 0x66, 0x6f, 0x6f, // Value len and value (3, "foo")
0x00, // Unindexed, literal name & value
0x03, 0x66, 0x6f, 0x6f, // Name len and name (3, "foo")
0x03, 0x62, 0x61, 0x72, // Value len and value (3, "bar")
};
EXPECT_TRUE(DeframeInput(kFrameData, sizeof kFrameData));
ASSERT_EQ(1u, collected_frames_.size());
const CollectedFrame& cf0 = collected_frames_[0];
StringPairVector headers;
headers.push_back({"bar", "foo"});
headers.push_back({"foo", "bar"});
EXPECT_TRUE(cf0.VerifyHasHeaders(headers));
SpdyHeadersIR expected_ir(1);
// Yet again SpdyFramerVisitorInterface is lossy: it doesn't call OnPadding
// for HEADERS, just for DATA. Sigh.
// expected_ir.set_padding_len(5);
expected_ir.set_fin(true);
for (const auto& nv : headers) {
expected_ir.SetHeader(nv.first, nv.second);
}
EXPECT_TRUE(cf0.VerifyHasFrame(expected_ir));
// Confirm that mismatches are also detected.
headers.push_back({"baz", "bing"});
EXPECT_FALSE(cf0.VerifyHasHeaders(headers));
EXPECT_TRUE(cf0.VerifyHasFrame(expected_ir));
headers.pop_back();
EXPECT_TRUE(cf0.VerifyHasHeaders(headers));
EXPECT_TRUE(cf0.VerifyHasFrame(expected_ir));
expected_ir.SetHeader("baz", "bing");
EXPECT_FALSE(cf0.VerifyHasFrame(expected_ir));
EXPECT_TRUE(cf0.VerifyHasHeaders(headers));
}
TEST_F(SpdyDeframerVisitorTest, PriorityFrame) {
const char kFrameData[] = {
0x00, 0x00, 0x05, // Length: 5
0x02, // Type: PRIORITY
0x00, // Flags: none
0x00, 0x00, 0x00, 0x65, // Stream: 101
0x80u, 0x00, 0x00, 0x01, // Parent: 1 (Exclusive)
0x10, // Weight: 17
};
EXPECT_TRUE(DeframeInput(kFrameData, sizeof kFrameData));
ASSERT_EQ(1u, collected_frames_.size());
const CollectedFrame& cf0 = collected_frames_[0];
SpdyPriorityIR expected_ir(101, 1, 17, true);
EXPECT_TRUE(cf0.VerifyHasFrame(expected_ir));
// Confirm that mismatches are also detected.
expected_ir.set_weight(16);
EXPECT_FALSE(cf0.VerifyHasFrame(expected_ir));
expected_ir.set_weight(17);
EXPECT_TRUE(cf0.VerifyHasFrame(expected_ir));
expected_ir.set_parent_stream_id(50);
EXPECT_FALSE(cf0.VerifyHasFrame(expected_ir));
expected_ir.set_parent_stream_id(1);
EXPECT_TRUE(cf0.VerifyHasFrame(expected_ir));
expected_ir.set_stream_id(201);
EXPECT_FALSE(cf0.VerifyHasFrame(expected_ir));
expected_ir.set_stream_id(101);
EXPECT_TRUE(cf0.VerifyHasFrame(expected_ir));
expected_ir.set_exclusive(false);
EXPECT_FALSE(cf0.VerifyHasFrame(expected_ir));
expected_ir.set_exclusive(true);
EXPECT_TRUE(cf0.VerifyHasFrame(expected_ir));
}
TEST_F(SpdyDeframerVisitorTest, DISABLED_RstStreamFrame) {
// TODO(jamessynge): Please implement.
}
TEST_F(SpdyDeframerVisitorTest, SettingsFrame) {
// Settings frame with two entries for the same parameter but with different
// values. The last one will be in the decoded SpdySettingsIR, but the vector
// of settings will have both, in the same order.
const char kFrameData[] = {
0x00, 0x00, 0x0c, // Length
0x04, // Type (SETTINGS)
0x00, // Flags
0x00, 0x00, 0x00, 0x00, // Stream id (must be zero)
0x00, 0x04, // Setting id (SETTINGS_INITIAL_WINDOW_SIZE)
0x0a, 0x0b, 0x0c, 0x0d, // Setting value
0x00, 0x04, // Setting id (SETTINGS_INITIAL_WINDOW_SIZE)
0x00, 0x00, 0x00, 0xffu // Setting value
};
EXPECT_TRUE(DeframeInput(kFrameData, sizeof kFrameData));
ASSERT_EQ(1u, collected_frames_.size());
const CollectedFrame& cf0 = collected_frames_[0];
ASSERT_NE(cf0.frame_ir, nullptr);
SpdySettingsIR expected_ir;
expected_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, true, true, 255);
EXPECT_TRUE(cf0.VerifyHasFrame(expected_ir));
SettingVector expected_settings;
expected_settings.push_back({SETTINGS_INITIAL_WINDOW_SIZE, 0x0a0b0c0d});
expected_settings.push_back({SETTINGS_INITIAL_WINDOW_SIZE, 255});
EXPECT_TRUE(cf0.VerifyHasSettings(expected_settings));
// Confirm that mismatches are also detected.
expected_settings.push_back({SETTINGS_INITIAL_WINDOW_SIZE, 65536});
EXPECT_FALSE(cf0.VerifyHasSettings(expected_settings));
expected_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, true, true, 65536);
EXPECT_FALSE(cf0.VerifyHasFrame(expected_ir));
SpdySettingsIR unexpected_ir;
unexpected_ir.set_is_ack(true);
EXPECT_FALSE(cf0.VerifyHasFrame(unexpected_ir));
}
TEST_F(SpdyDeframerVisitorTest, DISABLED_PushPromiseFrame) {
// TODO(jamessynge): Please implement.
}
TEST_F(SpdyDeframerVisitorTest, DISABLED_PingFrame) {
// TODO(jamessynge): Please implement.
}
TEST_F(SpdyDeframerVisitorTest, DISABLED_GoAwayFrame) {
// TODO(jamessynge): Please implement.
}
TEST_F(SpdyDeframerVisitorTest, DISABLED_WindowUpdateFrame) {
// TODO(jamessynge): Please implement.
}
TEST_F(SpdyDeframerVisitorTest, DISABLED_AltSvcFrame) {
// TODO(jamessynge): Please implement.
}
} // namespace
} // namespace test
} // namespace net
......@@ -535,12 +535,6 @@ class NET_EXPORT_PRIVATE SpdyFramer {
recv_frame_size_limit_ = recv_frame_size_limit;
}
void SetDecoderHeaderTableDebugVisitor(
std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor);
void SetEncoderHeaderTableDebugVisitor(
std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor);
// Returns the (minimum) size of frames (sans variable-length portions).
size_t GetDataFrameMinimumSize() const;
size_t GetFrameHeaderSize() const;
......@@ -597,6 +591,12 @@ class NET_EXPORT_PRIVATE SpdyFramer {
// Returns the maximum size of the header encoder compression table.
size_t header_encoder_table_size() const;
void SetDecoderHeaderTableDebugVisitor(
std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor);
void SetEncoderHeaderTableDebugVisitor(
std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor);
// For testing support (i.e. for clients and backends),
// allow overriding the flag on a per framer basis.
void set_use_new_methods_for_test(bool v) { use_new_methods_ = v; }
......
// 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 <stdint.h>
#include "net/spdy/spdy_protocol_test_utils.h"
namespace net {
namespace test {
// TODO(jamessynge): Where it makes sense in these functions, it would be nice
// to make use of the existing gMock matchers here, instead of rolling our own.
::testing::AssertionResult VerifySpdyFrameWithHeaderBlockIREquals(
const SpdyFrameWithHeaderBlockIR& expected,
const SpdyFrameWithHeaderBlockIR& actual) {
DVLOG(1) << "VerifySpdyFrameWithHeaderBlockIREquals";
if (actual.header_block() != expected.header_block())
return ::testing::AssertionFailure();
return ::testing::AssertionSuccess();
}
::testing::AssertionResult VerifySpdyFrameIREquals(const SpdyAltSvcIR& expected,
const SpdyAltSvcIR& actual) {
if (expected.stream_id() != actual.stream_id())
return ::testing::AssertionFailure();
if (expected.origin() != actual.origin())
return ::testing::AssertionFailure();
if (actual.altsvc_vector() != expected.altsvc_vector())
return ::testing::AssertionFailure();
return ::testing::AssertionSuccess();
}
::testing::AssertionResult VerifySpdyFrameIREquals(
const SpdyContinuationIR& expected,
const SpdyContinuationIR& actual) {
return ::testing::AssertionFailure()
<< "VerifySpdyFrameIREquals SpdyContinuationIR not yet implemented";
}
::testing::AssertionResult VerifySpdyFrameIREquals(const SpdyDataIR& expected,
const SpdyDataIR& actual) {
DVLOG(1) << "VerifySpdyFrameIREquals SpdyDataIR";
if (expected.stream_id() != actual.stream_id())
return ::testing::AssertionFailure();
if (expected.fin() != actual.fin())
return ::testing::AssertionFailure();
if (expected.data().size() != actual.data().size())
return ::testing::AssertionFailure();
if (expected.data() != actual.data())
return ::testing::AssertionFailure();
if (!VerifySpdyFrameWithPaddingIREquals(expected, actual))
return ::testing::AssertionFailure();
return ::testing::AssertionSuccess();
}
::testing::AssertionResult VerifySpdyFrameIREquals(const SpdyGoAwayIR& expected,
const SpdyGoAwayIR& actual) {
DVLOG(1) << "VerifySpdyFrameIREquals SpdyGoAwayIR";
if (expected.last_good_stream_id() != actual.last_good_stream_id())
return ::testing::AssertionFailure();
if (expected.status() != actual.status())
return ::testing::AssertionFailure();
if (expected.description() != actual.description())
return ::testing::AssertionFailure();
return ::testing::AssertionSuccess();
}
::testing::AssertionResult VerifySpdyFrameIREquals(
const SpdyHeadersIR& expected,
const SpdyHeadersIR& actual) {
DVLOG(1) << "VerifySpdyFrameIREquals SpdyHeadersIR";
if (expected.stream_id() != actual.stream_id())
return ::testing::AssertionFailure();
if (expected.fin() != actual.fin())
return ::testing::AssertionFailure();
if (!VerifySpdyFrameWithHeaderBlockIREquals(expected, actual))
return ::testing::AssertionFailure();
if (expected.has_priority() != actual.has_priority())
return ::testing::AssertionFailure();
if (expected.has_priority()) {
if (!VerifySpdyFrameWithPriorityIREquals(expected, actual))
return ::testing::AssertionFailure();
}
if (!VerifySpdyFrameWithPaddingIREquals(expected, actual))
return ::testing::AssertionFailure();
return ::testing::AssertionSuccess();
}
::testing::AssertionResult VerifySpdyFrameIREquals(const SpdyPingIR& expected,
const SpdyPingIR& actual) {
DVLOG(1) << "VerifySpdyFrameIREquals SpdyPingIR";
if (expected.id() != actual.id())
return ::testing::AssertionFailure();
if (expected.is_ack() != actual.is_ack())
return ::testing::AssertionFailure();
return ::testing::AssertionSuccess();
}
::testing::AssertionResult VerifySpdyFrameIREquals(
const SpdyPriorityIR& expected,
const SpdyPriorityIR& actual) {
DVLOG(1) << "VerifySpdyFrameIREquals SpdyPriorityIR";
if (expected.stream_id() != actual.stream_id())
return ::testing::AssertionFailure();
if (!VerifySpdyFrameWithPriorityIREquals(expected, actual))
return ::testing::AssertionFailure();
return ::testing::AssertionSuccess();
}
::testing::AssertionResult VerifySpdyFrameIREquals(
const SpdyPushPromiseIR& expected,
const SpdyPushPromiseIR& actual) {
DVLOG(1) << "VerifySpdyFrameIREquals SpdyPushPromiseIR";
if (expected.stream_id() != actual.stream_id())
return ::testing::AssertionFailure();
if (!VerifySpdyFrameWithPaddingIREquals(expected, actual))
return ::testing::AssertionFailure();
if (expected.promised_stream_id() != actual.promised_stream_id())
return ::testing::AssertionFailure();
if (!VerifySpdyFrameWithHeaderBlockIREquals(expected, actual))
return ::testing::AssertionFailure();
return ::testing::AssertionSuccess();
}
::testing::AssertionResult VerifySpdyFrameIREquals(
const SpdyRstStreamIR& expected,
const SpdyRstStreamIR& actual) {
DVLOG(1) << "VerifySpdyFrameIREquals SpdyRstStreamIR";
if (expected.stream_id() != actual.stream_id())
return ::testing::AssertionFailure();
if (expected.status() != actual.status())
return ::testing::AssertionFailure();
return ::testing::AssertionSuccess();
}
::testing::AssertionResult VerifySpdyFrameIREquals(
const SpdySettingsIR& expected,
const SpdySettingsIR& actual) {
DVLOG(1) << "VerifySpdyFrameIREquals SpdySettingsIR";
// Note, ignoring non-HTTP/2 fields such as clear_settings.
if (expected.is_ack() != actual.is_ack())
return ::testing::AssertionFailure();
if (expected.values().size() != actual.values().size())
return ::testing::AssertionFailure();
for (const auto& entry : expected.values()) {
const auto& param = entry.first;
auto actual_itr = actual.values().find(param);
if (actual_itr == actual.values().end()) {
DVLOG(1) << "actual doesn't contain param: " << param;
return ::testing::AssertionFailure();
}
uint32_t expected_value = entry.second.value;
uint32_t actual_value = actual_itr->second.value;
if (expected_value != actual_value) {
DVLOG(1) << "Values don't match for parameter: " << param;
return ::testing::AssertionFailure();
}
}
return ::testing::AssertionSuccess();
}
::testing::AssertionResult VerifySpdyFrameIREquals(
const SpdyWindowUpdateIR& expected,
const SpdyWindowUpdateIR& actual) {
DVLOG(1) << "VerifySpdyFrameIREquals SpdyWindowUpdateIR";
if (expected.stream_id() != actual.stream_id())
return ::testing::AssertionFailure();
if (expected.delta() != actual.delta())
return ::testing::AssertionFailure();
return ::testing::AssertionSuccess();
}
} // namespace test
} // namespace net
// 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.
#ifndef NET_SPDY_SPDY_PROTOCOL_TEST_UTILS_H_
#define NET_SPDY_SPDY_PROTOCOL_TEST_UTILS_H_
// These functions support tests that need to compare two concrete SpdyFrameIR
// instances for equality. They return AssertionResult, so they may be used as
// follows:
//
// SomeSpdyFrameIRSubClass expected_ir(...);
// std::unique_ptr<SpdyFrameIR> collected_frame;
// ... some test code that may fill in collected_frame ...
// ASSERT_TRUE(VerifySpdyFrameIREquals(expected_ir, collected_frame.get()));
//
// TODO(jamessynge): Where it makes sense in these functions, it would be nice
// to make use of the existing gMock matchers here, instead of rolling our own.
#include <typeinfo>
#include "base/logging.h"
#include "base/strings/string_piece.h"
#include "net/spdy/spdy_protocol.h"
#include "net/spdy/spdy_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace net {
namespace test {
// Verify the header entries in two SpdyFrameWithHeaderBlockIR instances
// are the same.
::testing::AssertionResult VerifySpdyFrameWithHeaderBlockIREquals(
const SpdyFrameWithHeaderBlockIR& expected,
const SpdyFrameWithHeaderBlockIR& actual);
// Verify that the padding in two frames of type T is the same.
template <class T>
::testing::AssertionResult VerifySpdyFrameWithPaddingIREquals(const T& expected,
const T& actual) {
DVLOG(1) << "VerifySpdyFrameWithPaddingIREquals";
if (expected.padded() != actual.padded())
return ::testing::AssertionFailure();
if (expected.padded()) {
if (expected.padding_payload_len() != actual.padding_payload_len())
return ::testing::AssertionFailure();
}
return ::testing::AssertionSuccess();
}
// Verify the priority fields in two frames of type T are the same.
template <class T>
::testing::AssertionResult VerifySpdyFrameWithPriorityIREquals(
const T& expected,
const T& actual) {
DVLOG(1) << "VerifySpdyFrameWithPriorityIREquals";
if (expected.parent_stream_id() != actual.parent_stream_id())
return ::testing::AssertionFailure();
if (expected.weight() != actual.weight())
return ::testing::AssertionFailure();
if (expected.exclusive() != actual.exclusive())
return ::testing::AssertionFailure();
return ::testing::AssertionSuccess();
}
// Verify that two SpdyAltSvcIR frames are the same.
::testing::AssertionResult VerifySpdyFrameIREquals(const SpdyAltSvcIR& expected,
const SpdyAltSvcIR& actual);
// VerifySpdyFrameIREquals for SpdyContinuationIR frames isn't really needed
// because we don't really make use of SpdyContinuationIR, instead creating
// SpdyHeadersIR or SpdyPushPromiseIR with the pre-encoding form of the HPACK
// block (i.e. we don't yet have a CONTINUATION frame).
//
// ::testing::AssertionResult VerifySpdyFrameIREquals(
// const SpdyContinuationIR& expected,
// const SpdyContinuationIR& actual) {
// return ::testing::AssertionFailure()
// << "VerifySpdyFrameIREquals SpdyContinuationIR NYI";
// }
// Verify that two SpdyDataIR frames are the same.
::testing::AssertionResult VerifySpdyFrameIREquals(const SpdyDataIR& expected,
const SpdyDataIR& actual);
// Verify that two SpdyGoAwayIR frames are the same.
::testing::AssertionResult VerifySpdyFrameIREquals(const SpdyGoAwayIR& expected,
const SpdyGoAwayIR& actual);
// Verify that two SpdyHeadersIR frames are the same.
::testing::AssertionResult VerifySpdyFrameIREquals(
const SpdyHeadersIR& expected,
const SpdyHeadersIR& actual);
// Verify that two SpdyPingIR frames are the same.
::testing::AssertionResult VerifySpdyFrameIREquals(const SpdyPingIR& expected,
const SpdyPingIR& actual);
// Verify that two SpdyPriorityIR frames are the same.
::testing::AssertionResult VerifySpdyFrameIREquals(
const SpdyPriorityIR& expected,
const SpdyPriorityIR& actual);
// Verify that two SpdyPushPromiseIR frames are the same.
::testing::AssertionResult VerifySpdyFrameIREquals(
const SpdyPushPromiseIR& expected,
const SpdyPushPromiseIR& actual);
// Verify that two SpdyRstStreamIR frames are the same.
::testing::AssertionResult VerifySpdyFrameIREquals(
const SpdyRstStreamIR& expected,
const SpdyRstStreamIR& actual);
// Verify that two SpdySettingsIR frames are the same.
::testing::AssertionResult VerifySpdyFrameIREquals(
const SpdySettingsIR& expected,
const SpdySettingsIR& actual);
// Verify that two SpdyWindowUpdateIR frames are the same.
::testing::AssertionResult VerifySpdyFrameIREquals(
const SpdyWindowUpdateIR& expected,
const SpdyWindowUpdateIR& actual);
// Verify that either expected and actual are both nullptr, or that both are not
// nullptr, and that actual is of type E, and that it matches expected.
template <class E>
::testing::AssertionResult VerifySpdyFrameIREquals(const E* expected,
const SpdyFrameIR* actual) {
if (expected == nullptr || actual == nullptr) {
DVLOG(1) << "VerifySpdyFrameIREquals one null";
if (expected != nullptr)
return ::testing::AssertionFailure();
if (actual != nullptr)
return ::testing::AssertionFailure();
return ::testing::AssertionSuccess();
}
DVLOG(1) << "VerifySpdyFrameIREquals not null";
const E* actual2 = reinterpret_cast<const E*>(actual);
if (actual2 == nullptr)
return ::testing::AssertionFailure();
return VerifySpdyFrameIREquals(*expected, *actual2);
}
// Verify that actual is not nullptr, that it is of type E and that it
// matches expected.
template <class E>
::testing::AssertionResult VerifySpdyFrameIREquals(const E& expected,
const SpdyFrameIR* actual) {
DVLOG(1) << "VerifySpdyFrameIREquals";
return VerifySpdyFrameIREquals(&expected, actual);
}
} // namespace test
} // namespace net
#endif // NET_SPDY_SPDY_PROTOCOL_TEST_UTILS_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment