Commit 317ae394 authored by bnc's avatar bnc Committed by Commit bot

Use std::function instead of base::Callback in net/http2/.

This CL also lands server change 143046389 by bnc.

BUG=488484

Review-Url: https://codereview.chromium.org/2572343002
Cr-Commit-Position: refs/heads/master@{#442895}
parent c38084e1
......@@ -6,9 +6,6 @@
#include <string>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/logging.h"
#include "base/strings/string_piece.h"
#include "net/http2/tools/http2_random.h"
......@@ -68,7 +65,7 @@ class DecodeBufferTest : public ::testing::Test {
bool SlowDecodeField(DecodeBuffer* b,
size_t field_size,
size_t field_offset,
const base::Callback<bool(DecodeBuffer*)>& fn,
std::function<bool(DecodeBuffer*)> fn,
T* f) {
VLOG(2) << "Remaining: " << b->Remaining();
VLOG(2) << "field_size: " << field_size;
......@@ -80,7 +77,7 @@ class DecodeBufferTest : public ::testing::Test {
uint32_t old = static_cast<uint32_t>(*f);
VLOG(2) << "old: " << old;
size_t old_decode_offset = decode_offset_;
bool done = fn.Run(b);
bool done = fn(b);
VLOG(2) << "done: " << done;
if (old_decode_offset == decode_offset_) {
// Didn't do any decoding (may have no input, or may have already
......@@ -106,35 +103,35 @@ class DecodeBufferTest : public ::testing::Test {
return done;
}
bool decode_f1(TestStruct* p, DecodeBuffer* db) {
return db->SlowDecodeUInt8(kF1Offset, &decode_offset_, &p->f1);
}
bool decode_f2(TestStruct* p, DecodeBuffer* db) {
return db->SlowDecodeUInt16(kF2Offset, &decode_offset_, &p->f2);
}
bool decode_f3(TestStruct* p, DecodeBuffer* db) {
return db->SlowDecodeUInt24(kF3Offset, &decode_offset_, &p->f3);
}
bool decode_f4(TestStruct* p, DecodeBuffer* db) {
return db->SlowDecodeUInt32(kF4Offset, &decode_offset_, &p->f4);
}
bool decode_f5(TestStruct* p, DecodeBuffer* db) {
return db->SlowDecodeUInt31(kF5Offset, &decode_offset_, &p->f5);
}
bool decode_f6(TestStruct* p, DecodeBuffer* db) {
return db->SlowDecodeEnum(4, kF6Offset, &decode_offset_, &p->f6);
}
bool decode_f7(TestStruct* p, DecodeBuffer* db) {
return db->SlowDecodeEnum(1, kF7Offset, &decode_offset_, &p->f7);
}
bool decode_f8(TestStruct* p, DecodeBuffer* db) {
return db->SlowDecodeEnum(1, kF8Offset, &decode_offset_, &p->f8);
}
void SlowDecodeTestStruct(StringPiece input, TestStruct* p) {
VLOG(2) << "############################################################";
EXPECT_LE(10u, input.size());
decode_offset_ = 0;
auto decode_f1 = [this, p](DecodeBuffer* db) {
return db->SlowDecodeUInt8(kF1Offset, &decode_offset_, &p->f1);
};
auto decode_f2 = [this, p](DecodeBuffer* db) {
return db->SlowDecodeUInt16(kF2Offset, &decode_offset_, &p->f2);
};
auto decode_f3 = [this, p](DecodeBuffer* db) {
return db->SlowDecodeUInt24(kF3Offset, &decode_offset_, &p->f3);
};
auto decode_f4 = [this, p](DecodeBuffer* db) {
return db->SlowDecodeUInt32(kF4Offset, &decode_offset_, &p->f4);
};
auto decode_f5 = [this, p](DecodeBuffer* db) {
return db->SlowDecodeUInt31(kF5Offset, &decode_offset_, &p->f5);
};
auto decode_f6 = [this, p](DecodeBuffer* db) {
return db->SlowDecodeEnum(4, kF6Offset, &decode_offset_, &p->f6);
};
auto decode_f7 = [this, p](DecodeBuffer* db) {
return db->SlowDecodeEnum(1, kF7Offset, &decode_offset_, &p->f7);
};
auto decode_f8 = [this, p](DecodeBuffer* db) {
return db->SlowDecodeEnum(1, kF8Offset, &decode_offset_, &p->f8);
};
while (input.size() > 0) {
size_t size = input.size();
// Sometimes check that zero length input is OK.
......@@ -148,38 +145,14 @@ class DecodeBufferTest : public ::testing::Test {
VLOG(2) << "================= input size " << size;
DecodeBuffer b(input.data(), size);
size_t old_decode_offset = decode_offset_;
if (SlowDecodeField(&b, 1, kF1Offset,
base::Bind(&DecodeBufferTest::decode_f1,
base::Unretained(this), p),
&p->f1) &&
SlowDecodeField(&b, 2, kF2Offset,
base::Bind(&DecodeBufferTest::decode_f2,
base::Unretained(this), p),
&p->f2) &&
SlowDecodeField(&b, 3, kF3Offset,
base::Bind(&DecodeBufferTest::decode_f3,
base::Unretained(this), p),
&p->f3) &&
SlowDecodeField(&b, 4, kF4Offset,
base::Bind(&DecodeBufferTest::decode_f4,
base::Unretained(this), p),
&p->f4) &&
SlowDecodeField(&b, 4, kF5Offset,
base::Bind(&DecodeBufferTest::decode_f5,
base::Unretained(this), p),
&p->f5) &&
SlowDecodeField(&b, 4, kF6Offset,
base::Bind(&DecodeBufferTest::decode_f6,
base::Unretained(this), p),
&p->f6) &&
SlowDecodeField(&b, 1, kF7Offset,
base::Bind(&DecodeBufferTest::decode_f7,
base::Unretained(this), p),
&p->f7) &&
SlowDecodeField(&b, 1, kF8Offset,
base::Bind(&DecodeBufferTest::decode_f8,
base::Unretained(this), p),
&p->f8)) {
if (SlowDecodeField(&b, 1, kF1Offset, decode_f1, &p->f1) &&
SlowDecodeField(&b, 2, kF2Offset, decode_f2, &p->f2) &&
SlowDecodeField(&b, 3, kF3Offset, decode_f3, &p->f3) &&
SlowDecodeField(&b, 4, kF4Offset, decode_f4, &p->f4) &&
SlowDecodeField(&b, 4, kF5Offset, decode_f5, &p->f5) &&
SlowDecodeField(&b, 4, kF6Offset, decode_f6, &p->f6) &&
SlowDecodeField(&b, 1, kF7Offset, decode_f7, &p->f7) &&
SlowDecodeField(&b, 1, kF8Offset, decode_f8, &p->f8)) {
EXPECT_TRUE(b.Empty());
EXPECT_EQ(size, input.size());
EXPECT_EQ(input.size(), b.Offset()); // All input consumed.
......@@ -245,7 +218,6 @@ TEST_F(DecodeBufferTest, SlowDecodeTestStruct) {
ts.f2 = random_.Rand16();
ts.f3 = random_.Rand32();
ts.f4 = random_.Rand32();
// Ensure high-bit is set.
ts.f5 = 0x80000000 | random_.Rand32(); // Ensure high-bit is set.
ts.f6 = static_cast<TestEnumClass32>(random_.Rand32());
ts.f7 = static_cast<TestEnumClass8>(random_.Rand8());
......
......@@ -14,8 +14,6 @@
#include <stddef.h>
#include <string>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/strings/string_piece.h"
#include "net/http2/decoder/decode_buffer.h"
......@@ -110,17 +108,6 @@ class StructureDecoderTest : public RandomDecoderTest {
// Set the fields of |*p| to random values.
void Randomize(S* p) { ::net::test::Randomize(p, RandomPtr()); }
AssertionResult ValidatorForDecodeLeadingStructure(const S* expected,
const DecodeBuffer& db,
DecodeStatus status) {
if (expected != nullptr && *expected != structure_) {
return AssertionFailure()
<< "Expected structs to be equal\nExpected: " << *expected
<< "\n Actual: " << structure_;
}
return AssertionSuccess();
}
// Fully decodes the Structure at the start of data, and confirms it matches
// *expected (if provided).
void DecodeLeadingStructure(const S* expected, StringPiece data) {
......@@ -130,20 +117,25 @@ class StructureDecoderTest : public RandomDecoderTest {
// The validator is called after each of the several times that the input
// DecodeBuffer is decoded, each with a different segmentation of the input.
// Validate that structure_ matches the expected value, if provided.
Validator validator =
base::Bind(&StructureDecoderTest::ValidatorForDecodeLeadingStructure,
base::Unretained(this), expected);
Validator validator = [expected, this](
const DecodeBuffer& db, DecodeStatus status) -> AssertionResult {
if (expected != nullptr && *expected != structure_) {
return AssertionFailure()
<< "Expected structs to be equal\nExpected: " << *expected
<< "\n Actual: " << structure_;
}
return AssertionSuccess();
};
// First validate that decoding is done and that we've advanced the cursor
// the expected amount.
Validator wrapped_validator =
ValidateDoneAndOffset(S::EncodedSize(), validator);
validator = ValidateDoneAndOffset(S::EncodedSize(), validator);
// Decode several times, with several segmentations of the input buffer.
fast_decode_count_ = 0;
slow_decode_count_ = 0;
EXPECT_TRUE(DecodeAndValidateSeveralWays(
&original, false /*return_non_zero_on_first*/, wrapped_validator));
&original, false /*return_non_zero_on_first*/, validator));
if (!HasFailure()) {
EXPECT_EQ(S::EncodedSize(), decode_offset_);
......
......@@ -10,8 +10,6 @@
#include <string>
#include <vector>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "net/http2/decoder/frame_parts.h"
#include "net/http2/decoder/frame_parts_collector_listener.h"
......@@ -38,24 +36,6 @@ class Http2FrameDecoderPeer {
namespace {
class Http2FrameDecoderTest : public RandomDecoderTest {
public:
AssertionResult ValidatorForDecodePayloadExpectingError(
const FrameParts& expected,
const DecodeBuffer& input,
DecodeStatus status) {
VERIFY_EQ(status, DecodeStatus::kDecodeError);
VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected));
}
AssertionResult ValidatorForBeyondMaximum(const FrameParts& expected,
const DecodeBuffer& input,
DecodeStatus status) {
VERIFY_EQ(status, DecodeStatus::kDecodeError);
// The decoder detects this error after decoding the header, and without
// trying to decode the payload.
VERIFY_EQ(input.Offset(), Http2FrameHeader::EncodedSize());
VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected));
}
protected:
void SetUp() override {
......@@ -152,13 +132,6 @@ class Http2FrameDecoderTest : public RandomDecoderTest {
validator);
}
AssertionResult ValidatorForDecodePayloadAndValidateSeveralWays(
const FrameParts& expected,
const DecodeBuffer& input,
DecodeStatus status) {
VERIFY_EQ(status, DecodeStatus::kDecodeDone);
VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected));
}
// Decode one frame's payload and confirm that the listener recorded the
// expected FrameParts instance, and only one FrameParts instance. The
......@@ -167,9 +140,11 @@ class Http2FrameDecoderTest : public RandomDecoderTest {
AssertionResult DecodePayloadAndValidateSeveralWays(
StringPiece payload,
const FrameParts& expected) {
Validator validator = base::Bind(
&Http2FrameDecoderTest::ValidatorForDecodePayloadAndValidateSeveralWays,
base::Unretained(this), base::ConstRef(expected));
Validator validator = [&expected, this](
const DecodeBuffer& input, DecodeStatus status) -> AssertionResult {
VERIFY_EQ(status, DecodeStatus::kDecodeDone);
VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected));
};
ResetDecodeSpeedCounters();
VERIFY_SUCCESS(DecodePayloadAndValidateSeveralWays(
payload, ValidateDoneAndEmpty(validator)));
......@@ -209,12 +184,14 @@ class Http2FrameDecoderTest : public RandomDecoderTest {
template <size_t N>
AssertionResult DecodePayloadExpectingError(const char (&buf)[N],
const FrameParts& expected) {
auto validator = [&expected, this](const DecodeBuffer& input,
DecodeStatus status) -> AssertionResult {
VERIFY_EQ(status, DecodeStatus::kDecodeError);
VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected));
};
ResetDecodeSpeedCounters();
EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(
ToStringPiece(buf),
base::Bind(
&Http2FrameDecoderTest::ValidatorForDecodePayloadExpectingError,
base::Unretained(this), expected)));
EXPECT_TRUE(
DecodePayloadAndValidateSeveralWays(ToStringPiece(buf), validator));
EXPECT_GT(fast_decode_count_, 0u);
EXPECT_GT(slow_decode_count_, 0u);
return AssertionSuccess();
......@@ -865,11 +842,17 @@ TEST_F(Http2FrameDecoderTest, BeyondMaximum) {
Http2FrameFlag::FLAG_END_STREAM | Http2FrameFlag::FLAG_PADDED, 2);
FrameParts expected(header);
expected.has_frame_size_error = true;
auto validator = [&expected, this](const DecodeBuffer& input,
DecodeStatus status) -> AssertionResult {
VERIFY_EQ(status, DecodeStatus::kDecodeError);
// The decoder detects this error after decoding the header, and without
// trying to decode the payload.
VERIFY_EQ(input.Offset(), Http2FrameHeader::EncodedSize());
VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected));
};
ResetDecodeSpeedCounters();
EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(
ToStringPiece(kFrameData),
base::Bind(&Http2FrameDecoderTest::ValidatorForBeyondMaximum,
base::Unretained(this), expected)));
EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(ToStringPiece(kFrameData),
validator));
EXPECT_GT(fast_decode_count_, 0u);
EXPECT_GT(slow_decode_count_, 0u);
}
......
......@@ -21,8 +21,6 @@
#include <stddef.h>
#include <string>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/strings/string_piece.h"
#include "net/http2/decoder/decode_buffer.h"
......@@ -102,12 +100,6 @@ class Http2StructureDecoderTest : public RandomDecoderTest {
}
}
AssertionResult ValidatorForDecodeLeadingStructure(const S* expected,
const DecodeBuffer& db,
DecodeStatus status) {
VERIFY_EQ(*expected, structure_);
return AssertionSuccess();
}
// Fully decodes the Structure at the start of data, and confirms it matches
// *expected (if provided).
......@@ -118,17 +110,18 @@ class Http2StructureDecoderTest : public RandomDecoderTest {
// The validator is called after each of the several times that the input
// DecodeBuffer is decoded, each with a different segmentation of the input.
// Validate that structure_ matches the expected value, if provided.
Validator validator =
(expected == nullptr)
? base::Bind(&SucceedingValidator)
: base::Bind(&Http2StructureDecoderTest::
ValidatorForDecodeLeadingStructure,
base::Unretained(this), expected);
Validator validator;
if (expected != nullptr) {
validator = [expected, this](const DecodeBuffer& db,
DecodeStatus status) -> AssertionResult {
VERIFY_EQ(*expected, structure_);
return AssertionSuccess();
};
}
// Before that, validate that decoding is done and that we've advanced
// the cursor the expected amount.
Validator wrapped_validator =
ValidateDoneAndOffset(S::EncodedSize(), validator);
validator = ValidateDoneAndOffset(S::EncodedSize(), validator);
// Decode several times, with several segmentations of the input buffer.
fast_decode_count_ = 0;
......@@ -136,7 +129,7 @@ class Http2StructureDecoderTest : public RandomDecoderTest {
incomplete_start_count_ = 0;
incomplete_resume_count_ = 0;
VERIFY_SUCCESS(DecodeAndValidateSeveralWays(
&original, kMayReturnZeroOnFirst, wrapped_validator));
&original, kMayReturnZeroOnFirst, validator));
VERIFY_FALSE(HasFailure());
VERIFY_EQ(S::EncodedSize(), structure_decoder_.offset());
VERIFY_EQ(S::EncodedSize(), original.Offset());
......
......@@ -8,7 +8,6 @@
#include <string>
#include "base/bind.h"
#include "base/logging.h"
#include "net/http2/decoder/frame_parts.h"
#include "net/http2/decoder/frame_parts_collector.h"
......@@ -88,9 +87,8 @@ TEST_F(AltSvcPayloadDecoderTest, Truncated) {
Http2FrameBuilder fb;
fb.Append(Http2AltSvcFields{0xffff}); // The longest possible origin length.
fb.Append("Too little origin!");
EXPECT_TRUE(VerifyDetectsFrameSizeError(
0, fb.buffer(),
base::Bind(&AbstractPayloadDecoderTest::SucceedingApproveSize)));
EXPECT_TRUE(
VerifyDetectsFrameSizeError(0, fb.buffer(), /*approve_size*/ nullptr));
}
class AltSvcPayloadLengthTests : public AltSvcPayloadDecoderTest,
......
......@@ -8,7 +8,6 @@
#include <string>
#include "base/bind.h"
#include "base/logging.h"
#include "net/http2/decoder/frame_parts.h"
#include "net/http2/decoder/frame_parts_collector.h"
......@@ -70,21 +69,17 @@ struct Listener : public FramePartsCollector {
class GoAwayPayloadDecoderTest
: public AbstractPayloadDecoderTest<GoAwayPayloadDecoder,
GoAwayPayloadDecoderPeer,
Listener> {
public:
static bool ApproveSizeForTruncated(size_t size) {
return size != Http2GoAwayFields::EncodedSize();
}
};
Listener> {};
// Confirm we get an error if the payload is not long enough to hold
// Http2GoAwayFields.
TEST_F(GoAwayPayloadDecoderTest, Truncated) {
auto approve_size = [](size_t size) {
return size != Http2GoAwayFields::EncodedSize();
};
Http2FrameBuilder fb;
fb.Append(Http2GoAwayFields(123, Http2ErrorCode::ENHANCE_YOUR_CALM));
EXPECT_TRUE(VerifyDetectsFrameSizeError(
0, fb.buffer(),
base::Bind(&GoAwayPayloadDecoderTest::ApproveSizeForTruncated)));
EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size));
}
class GoAwayOpaqueDataLengthTests
......
......@@ -8,7 +8,6 @@
#include <string>
#include "base/bind.h"
#include "base/logging.h"
#include "net/http2/decoder/frame_parts.h"
#include "net/http2/decoder/frame_parts_collector.h"
......@@ -103,12 +102,7 @@ struct Listener : public FramePartsCollector {
class HeadersPayloadDecoderTest
: public AbstractPaddablePayloadDecoderTest<HeadersPayloadDecoder,
HeadersPayloadDecoderPeer,
Listener> {
public:
static bool ApproveSizeForTruncated(size_t size) {
return size != Http2PriorityFields::EncodedSize();
}
};
Listener> {};
INSTANTIATE_TEST_CASE_P(VariousPadLengths,
HeadersPayloadDecoderTest,
......@@ -153,12 +147,14 @@ TEST_P(HeadersPayloadDecoderTest, VariousHpackPayloadSizes) {
// Confirm we get an error if the PRIORITY flag is set but the payload is
// not long enough, regardless of the amount of (valid) padding.
TEST_P(HeadersPayloadDecoderTest, Truncated) {
auto approve_size = [](size_t size) {
return size != Http2PriorityFields::EncodedSize();
};
Http2FrameBuilder fb;
fb.Append(Http2PriorityFields(RandStreamId(), 1 + Random().Rand8(),
Random().OneIn(2)));
EXPECT_TRUE(VerifyDetectsMultipleFrameSizeErrors(
Http2FrameFlag::FLAG_PRIORITY, fb.buffer(),
base::Bind(&HeadersPayloadDecoderTest::ApproveSizeForTruncated),
Http2FrameFlag::FLAG_PRIORITY, fb.buffer(), approve_size,
total_pad_length_));
}
......
......@@ -11,9 +11,6 @@
#include <string>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/logging.h"
#include "base/strings/string_piece.h"
#include "net/http2/decoder/decode_buffer.h"
......@@ -123,15 +120,13 @@ template <class Decoder,
class Listener,
bool SupportedFrameType = true>
class AbstractPayloadDecoderTest : public PayloadDecoderBaseTest {
public:
static bool SucceedingApproveSize(size_t size) { return true; }
protected:
// An ApproveSize function returns true to approve decoding the specified
// size of payload, else false to skip that size. Typically used for negative
// tests; for example, decoding a SETTINGS frame at all sizes except for
// multiples of 6.
typedef base::Callback<bool(size_t size)> ApproveSize;
typedef std::function<bool(size_t size)> ApproveSize;
AbstractPayloadDecoderTest() {}
......@@ -196,14 +191,6 @@ class AbstractPayloadDecoderTest : public PayloadDecoderBaseTest {
return payload_decoder_.ResumeDecodingPayload(mutable_state(), db);
}
// Wrap |validator| in another one which will check that we've reached the
// expected state of kDecodeError with OnFrameSizeError having been called by
AssertionResult ValidatorForDecodePayloadAndValidateSeveralWays(
const FrameParts& expected) {
VERIFY_FALSE(listener_.IsInProgress());
VERIFY_EQ(1u, listener_.size());
VERIFY_AND_RETURN_SUCCESS(expected.VerifyEquals(*listener_.frame(0)));
}
// Decode one frame's payload and confirm that the listener recorded the
// expected FrameParts instance, and only FrameParts instance. The payload
......@@ -212,33 +199,13 @@ class AbstractPayloadDecoderTest : public PayloadDecoderBaseTest {
AssertionResult DecodePayloadAndValidateSeveralWays(
base::StringPiece payload,
const FrameParts& expected) {
NoArgValidator validator = [&expected, this]() -> AssertionResult {
VERIFY_FALSE(listener_.IsInProgress());
VERIFY_EQ(1u, listener_.size());
VERIFY_AND_RETURN_SUCCESS(expected.VerifyEquals(*listener_.frame(0)));
};
return PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays(
payload, this->ValidateDoneAndEmpty(base::Bind(
&AbstractPayloadDecoderTest::
ValidatorForDecodePayloadAndValidateSeveralWays,
base::Unretained(this), base::ConstRef(expected))));
}
// Wrap |validator| in another one which will check that we've reached the
// expected state of kDecodeError with OnFrameSizeError having been called by
// the payload decoder.
AssertionResult ValidatorForVerifyDetectsFrameSizeError(
const Http2FrameHeader& header,
const Validator& validator,
const DecodeBuffer& input,
DecodeStatus status) {
DVLOG(2) << "VerifyDetectsFrameSizeError validator; status=" << status
<< "; input.Remaining=" << input.Remaining();
VERIFY_EQ(DecodeStatus::kDecodeError, status);
VERIFY_FALSE(listener_.IsInProgress());
VERIFY_EQ(1u, listener_.size());
const FrameParts* frame = listener_.frame(0);
VERIFY_EQ(header, frame->frame_header);
VERIFY_TRUE(frame->has_frame_size_error);
// Verify did not get OnPaddingTooLong, as we should only ever produce
// one of these two errors for a single frame.
VERIFY_FALSE(frame->opt_missing_length);
return validator.Run(input, status);
payload, ValidateDoneAndEmpty(validator));
}
// Decode one frame's payload, expecting that the final status will be
......@@ -254,13 +221,29 @@ class AbstractPayloadDecoderTest : public PayloadDecoderBaseTest {
WrappedValidator wrapped_validator) {
set_frame_header(header);
// If wrapped_validator is not a RandomDecoderTest::Validator, make it so.
Validator validator = this->ToValidator(wrapped_validator);
Validator validator = ToValidator(wrapped_validator);
// And wrap that validator in another which will check that we've reached
// the expected state of kDecodeError with OnFrameSizeError having been
// called by the payload decoder.
validator = [header, validator, this](
const DecodeBuffer& input,
DecodeStatus status) -> ::testing::AssertionResult {
DVLOG(2) << "VerifyDetectsFrameSizeError validator; status=" << status
<< "; input.Remaining=" << input.Remaining();
VERIFY_EQ(DecodeStatus::kDecodeError, status);
VERIFY_FALSE(listener_.IsInProgress());
VERIFY_EQ(1u, listener_.size());
const FrameParts* frame = listener_.frame(0);
VERIFY_EQ(header, frame->frame_header);
VERIFY_TRUE(frame->has_frame_size_error);
// Verify did not get OnPaddingTooLong, as we should only ever produce
// one of these two errors for a single frame.
VERIFY_FALSE(frame->opt_missing_length);
return validator(input, status);
};
VERIFY_AND_RETURN_SUCCESS(
PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays(
payload, base::Bind(&AbstractPayloadDecoderTest::
ValidatorForVerifyDetectsFrameSizeError,
base::Unretained(this), base::ConstRef(header),
base::ConstRef(validator))));
PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays(payload,
validator));
}
// Confirm that we get OnFrameSizeError when trying to decode unpadded_payload
......@@ -299,7 +282,7 @@ class AbstractPayloadDecoderTest : public PayloadDecoderBaseTest {
bool validated = false;
for (size_t real_payload_size = 0;
real_payload_size <= unpadded_payload.size(); ++real_payload_size) {
if (!approve_size.Run(real_payload_size)) {
if (approve_size != nullptr && !approve_size(real_payload_size)) {
continue;
}
VLOG(1) << "real_payload_size=" << real_payload_size;
......@@ -320,8 +303,7 @@ class AbstractPayloadDecoderTest : public PayloadDecoderBaseTest {
// checking stream ids.
uint32_t stream_id = RandStreamId();
Http2FrameHeader header(fb.size(), frame_type, flags, stream_id);
VERIFY_SUCCESS(VerifyDetectsFrameSizeError(
fb.buffer(), header, base::Bind(&SucceedingValidator)));
VERIFY_SUCCESS(VerifyDetectsFrameSizeError(fb.buffer(), header, nullptr));
validated = true;
}
VERIFY_TRUE(validated);
......@@ -406,23 +388,6 @@ class AbstractPaddablePayloadDecoderTest
return flags;
}
static ::testing::AssertionResult ValidatorForVerifyDetectsPaddingTooLong(
const Http2FrameHeader& header,
int expected_missing_length,
const Listener& listener,
const DecodeBuffer& input,
DecodeStatus status) {
VERIFY_EQ(DecodeStatus::kDecodeError, status);
VERIFY_FALSE(listener.IsInProgress());
VERIFY_EQ(1u, listener.size());
const FrameParts* frame = listener.frame(0);
VERIFY_EQ(header, frame->frame_header);
VERIFY_TRUE(frame->opt_missing_length);
VERIFY_EQ(expected_missing_length, frame->opt_missing_length.value());
// Verify did not get OnFrameSizeError.
VERIFY_FALSE(frame->has_frame_size_error);
return ::testing::AssertionSuccess();
}
// Verify that we get OnPaddingTooLong when decoding payload, and that the
// amount of missing padding is as specified. header.IsPadded must be true,
......@@ -433,12 +398,23 @@ class AbstractPaddablePayloadDecoderTest
int expected_missing_length) {
set_frame_header(header);
auto& listener = listener_;
Validator validator = [header, expected_missing_length, &listener](
const DecodeBuffer& input,
DecodeStatus status) -> ::testing::AssertionResult {
VERIFY_EQ(DecodeStatus::kDecodeError, status);
VERIFY_FALSE(listener.IsInProgress());
VERIFY_EQ(1u, listener.size());
const FrameParts* frame = listener.frame(0);
VERIFY_EQ(header, frame->frame_header);
VERIFY_TRUE(frame->opt_missing_length);
VERIFY_EQ(expected_missing_length, frame->opt_missing_length.value());
// Verify did not get OnFrameSizeError.
VERIFY_FALSE(frame->has_frame_size_error);
return ::testing::AssertionSuccess();
};
VERIFY_AND_RETURN_SUCCESS(
PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays(
payload, base::Bind(&AbstractPaddablePayloadDecoderTest::
ValidatorForVerifyDetectsPaddingTooLong,
header, expected_missing_length,
base::ConstRef(listener))));
PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays(payload,
validator));
}
// Verifies that we get OnPaddingTooLong for a padded frame payload whose
......
......@@ -6,7 +6,6 @@
#include <stddef.h>
#include "base/bind.h"
#include "base/logging.h"
#include "net/http2/decoder/frame_parts.h"
#include "net/http2/decoder/frame_parts_collector.h"
......@@ -61,11 +60,6 @@ class PingPayloadDecoderTest
: public AbstractPayloadDecoderTest<PingPayloadDecoder,
PingPayloadDecoderPeer,
Listener> {
public:
static bool ApproveSizeForWrongSize(size_t size) {
return size != Http2PingFields::EncodedSize();
}
protected:
Http2PingFields RandPingFields() {
Http2PingFields fields;
......@@ -77,13 +71,14 @@ class PingPayloadDecoderTest
// Confirm we get an error if the payload is not the correct size to hold
// exactly one Http2PingFields.
TEST_F(PingPayloadDecoderTest, WrongSize) {
auto approve_size = [](size_t size) {
return size != Http2PingFields::EncodedSize();
};
Http2FrameBuilder fb;
fb.Append(RandPingFields());
fb.Append(RandPingFields());
fb.Append(RandPingFields());
EXPECT_TRUE(VerifyDetectsFrameSizeError(
0, fb.buffer(),
base::Bind(&PingPayloadDecoderTest::ApproveSizeForWrongSize)));
EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size));
}
TEST_F(PingPayloadDecoderTest, Ping) {
......
......@@ -6,7 +6,6 @@
#include <stddef.h>
#include "base/bind.h"
#include "base/logging.h"
#include "net/http2/decoder/frame_parts.h"
#include "net/http2/decoder/frame_parts_collector.h"
......@@ -57,11 +56,6 @@ class PriorityPayloadDecoderTest
: public AbstractPayloadDecoderTest<PriorityPayloadDecoder,
PriorityPayloadDecoderPeer,
Listener> {
public:
static bool ApproveSizeForWrongSize(size_t size) {
return size != Http2PriorityFields::EncodedSize();
}
protected:
Http2PriorityFields RandPriorityFields() {
Http2PriorityFields fields;
......@@ -73,12 +67,13 @@ class PriorityPayloadDecoderTest
// Confirm we get an error if the payload is not the correct size to hold
// exactly one Http2PriorityFields.
TEST_F(PriorityPayloadDecoderTest, WrongSize) {
auto approve_size = [](size_t size) {
return size != Http2PriorityFields::EncodedSize();
};
Http2FrameBuilder fb;
fb.Append(RandPriorityFields());
fb.Append(RandPriorityFields());
EXPECT_TRUE(VerifyDetectsFrameSizeError(
0, fb.buffer(),
base::Bind(&PriorityPayloadDecoderTest::ApproveSizeForWrongSize)));
EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size));
}
TEST_F(PriorityPayloadDecoderTest, VariousPayloads) {
......
......@@ -8,7 +8,6 @@
#include <string>
#include "base/bind.h"
#include "base/logging.h"
#include "net/http2/decoder/frame_parts.h"
#include "net/http2/decoder/frame_parts_collector.h"
......@@ -96,10 +95,6 @@ class PushPromisePayloadDecoderTest
: public AbstractPaddablePayloadDecoderTest<PushPromisePayloadDecoder,
PushPromisePayloadDecoderPeer,
Listener> {
public:
static bool ApproveSizeForTruncated(size_t size) {
return size != Http2PushPromiseFields::EncodedSize();
}
};
INSTANTIATE_TEST_CASE_P(VariousPadLengths,
......@@ -131,13 +126,14 @@ TEST_P(PushPromisePayloadDecoderTest, VariousHpackPayloadSizes) {
// Confirm we get an error if the payload is not long enough for the required
// portion of the payload, regardless of the amount of (valid) padding.
TEST_P(PushPromisePayloadDecoderTest, Truncated) {
auto approve_size = [](size_t size) {
return size != Http2PushPromiseFields::EncodedSize();
};
Http2PushPromiseFields push_promise{RandStreamId()};
Http2FrameBuilder fb;
fb.Append(push_promise);
EXPECT_TRUE(VerifyDetectsMultipleFrameSizeErrors(
0, fb.buffer(),
base::Bind(&PushPromisePayloadDecoderTest::ApproveSizeForTruncated),
total_pad_length_));
EXPECT_TRUE(VerifyDetectsMultipleFrameSizeErrors(0, fb.buffer(), approve_size,
total_pad_length_));
}
// Confirm we get an error if the PADDED flag is set but the payload is not
......
......@@ -6,7 +6,6 @@
#include <stddef.h>
#include "base/bind.h"
#include "base/logging.h"
#include "net/http2/decoder/frame_parts.h"
#include "net/http2/decoder/frame_parts_collector.h"
......@@ -58,11 +57,6 @@ class RstStreamPayloadDecoderTest
: public AbstractPayloadDecoderTest<RstStreamPayloadDecoder,
RstStreamPayloadDecoderPeer,
Listener> {
public:
static bool ApproveSizeForWrongSize(size_t size) {
return size != Http2RstStreamFields::EncodedSize();
}
protected:
Http2RstStreamFields RandRstStreamFields() {
Http2RstStreamFields fields;
......@@ -74,13 +68,14 @@ class RstStreamPayloadDecoderTest
// Confirm we get an error if the payload is not the correct size to hold
// exactly one Http2RstStreamFields.
TEST_F(RstStreamPayloadDecoderTest, WrongSize) {
auto approve_size = [](size_t size) {
return size != Http2RstStreamFields::EncodedSize();
};
Http2FrameBuilder fb;
fb.Append(RandRstStreamFields());
fb.Append(RandRstStreamFields());
fb.Append(RandRstStreamFields());
EXPECT_TRUE(VerifyDetectsFrameSizeError(
0, fb.buffer(),
base::Bind(&RstStreamPayloadDecoderTest::ApproveSizeForWrongSize)));
EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size));
}
TEST_F(RstStreamPayloadDecoderTest, AllErrors) {
......
......@@ -8,7 +8,6 @@
#include <vector>
#include "base/bind.h"
#include "base/logging.h"
#include "net/http2/decoder/frame_parts.h"
#include "net/http2/decoder/frame_parts_collector.h"
......@@ -78,17 +77,6 @@ class SettingsPayloadDecoderTest
: public AbstractPayloadDecoderTest<SettingsPayloadDecoder,
SettingsPayloadDecoderPeer,
Listener> {
public:
static bool ApproveSizeForSettingsWrongSize(size_t size) {
// Should get an error if size is not an integral multiple of the size
// of one setting.
return 0 != (size % Http2SettingFields::EncodedSize());
}
static bool ApproveSizeForSettingsAkcWrongSize(size_t size) {
return size != 0;
}
protected:
Http2SettingFields RandSettingsFields() {
Http2SettingFields fields;
......@@ -100,26 +88,27 @@ class SettingsPayloadDecoderTest
// Confirm we get an error if the SETTINGS payload is not the correct size
// to hold exactly zero or more whole Http2SettingFields.
TEST_F(SettingsPayloadDecoderTest, SettingsWrongSize) {
auto approve_size = [](size_t size) {
// Should get an error if size is not an integral multiple of the size
// of one setting.
return 0 != (size % Http2SettingFields::EncodedSize());
};
Http2FrameBuilder fb;
fb.Append(RandSettingsFields());
fb.Append(RandSettingsFields());
fb.Append(RandSettingsFields());
EXPECT_TRUE(VerifyDetectsFrameSizeError(
0, fb.buffer(),
base::Bind(
&SettingsPayloadDecoderTest::ApproveSizeForSettingsWrongSize)));
EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size));
}
// Confirm we get an error if the SETTINGS ACK payload is not empty.
TEST_F(SettingsPayloadDecoderTest, SettingsAkcWrongSize) {
auto approve_size = [](size_t size) { return size != 0; };
Http2FrameBuilder fb;
fb.Append(RandSettingsFields());
fb.Append(RandSettingsFields());
fb.Append(RandSettingsFields());
EXPECT_TRUE(VerifyDetectsFrameSizeError(
Http2FrameFlag::FLAG_ACK, fb.buffer(),
base::Bind(
&SettingsPayloadDecoderTest::ApproveSizeForSettingsAkcWrongSize)));
EXPECT_TRUE(VerifyDetectsFrameSizeError(Http2FrameFlag::FLAG_ACK, fb.buffer(),
approve_size));
}
// SETTINGS must have stream_id==0, but the payload decoder doesn't check that.
......
......@@ -6,7 +6,6 @@
#include <stddef.h>
#include "base/bind.h"
#include "base/logging.h"
#include "net/http2/decoder/frame_parts.h"
#include "net/http2/decoder/frame_parts_collector.h"
......@@ -60,10 +59,6 @@ class WindowUpdatePayloadDecoderTest
: public AbstractPayloadDecoderTest<WindowUpdatePayloadDecoder,
WindowUpdatePayloadDecoderPeer,
Listener> {
public:
static bool ApproveSizeForWrongSize(size_t size) {
return size != Http2WindowUpdateFields::EncodedSize();
}
protected:
Http2WindowUpdateFields RandWindowUpdateFields() {
......@@ -77,13 +72,14 @@ class WindowUpdatePayloadDecoderTest
// Confirm we get an error if the payload is not the correct size to hold
// exactly one Http2WindowUpdateFields.
TEST_F(WindowUpdatePayloadDecoderTest, WrongSize) {
auto approve_size = [](size_t size) {
return size != Http2WindowUpdateFields::EncodedSize();
};
Http2FrameBuilder fb;
fb.Append(RandWindowUpdateFields());
fb.Append(RandWindowUpdateFields());
fb.Append(RandWindowUpdateFields());
EXPECT_TRUE(VerifyDetectsFrameSizeError(
0, fb.buffer(),
base::Bind(&WindowUpdatePayloadDecoderTest::ApproveSizeForWrongSize)));
EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size));
}
TEST_F(WindowUpdatePayloadDecoderTest, VariousPayloads) {
......
......@@ -8,8 +8,6 @@
#include <sstream>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "net/http2/decoder/decode_buffer.h"
#include "net/http2/hpack/decoder/hpack_block_collector.h"
#include "net/http2/hpack/http2_hpack_constants.h"
......@@ -29,31 +27,6 @@ namespace test {
namespace {
class HpackBlockDecoderTest : public RandomDecoderTest {
public:
AssertionResult VerifyExpected(const HpackBlockCollector& expected) {
VERIFY_AND_RETURN_SUCCESS(collector_.VerifyEq(expected));
}
AssertionResult ValidateForSpecExample_C_2_1() {
VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleLiteralNameValueHeader(
HpackEntryType::kIndexedLiteralHeader, false, "custom-key", false,
"custom-header"));
}
AssertionResult ValidateForSpecExample_C_2_2() {
VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleLiteralValueHeader(
HpackEntryType::kUnindexedLiteralHeader, 4, false, "/sample/path"));
}
AssertionResult ValidateForSpecExample_C_2_3() {
VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleLiteralNameValueHeader(
HpackEntryType::kNeverIndexedLiteralHeader, false, "password", false,
"secret"));
}
AssertionResult ValidateForSpecExample_C_2_4() {
VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleIndexedHeader(2));
}
protected:
HpackBlockDecoderTest() : listener_(&collector_), decoder_(&listener_) {
......@@ -112,9 +85,11 @@ class HpackBlockDecoderTest : public RandomDecoderTest {
// http://httpwg.org/specs/rfc7541.html#rfc.section.C.2.1
TEST_F(HpackBlockDecoderTest, SpecExample_C_2_1) {
NoArgValidator do_check =
base::Bind(&HpackBlockDecoderTest::ValidateForSpecExample_C_2_1,
base::Unretained(this));
NoArgValidator do_check = [this]() {
VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleLiteralNameValueHeader(
HpackEntryType::kIndexedLiteralHeader, false, "custom-key", false,
"custom-header"));
};
EXPECT_TRUE(
DecodeHpackExampleAndValidateSeveralWays(R"(
40 | == Literal indexed ==
......@@ -126,14 +101,15 @@ TEST_F(HpackBlockDecoderTest, SpecExample_C_2_1) {
| custom-header
)",
ValidateDoneAndEmpty(do_check)));
EXPECT_TRUE(do_check.Run());
EXPECT_TRUE(do_check());
}
// http://httpwg.org/specs/rfc7541.html#rfc.section.C.2.2
TEST_F(HpackBlockDecoderTest, SpecExample_C_2_2) {
NoArgValidator do_check =
base::Bind(&HpackBlockDecoderTest::ValidateForSpecExample_C_2_2,
base::Unretained(this));
NoArgValidator do_check = [this]() {
VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleLiteralValueHeader(
HpackEntryType::kUnindexedLiteralHeader, 4, false, "/sample/path"));
};
EXPECT_TRUE(
DecodeHpackExampleAndValidateSeveralWays(R"(
04 | == Literal not indexed ==
......@@ -144,14 +120,16 @@ TEST_F(HpackBlockDecoderTest, SpecExample_C_2_2) {
| -> :path: /sample/path
)",
ValidateDoneAndEmpty(do_check)));
EXPECT_TRUE(do_check.Run());
EXPECT_TRUE(do_check());
}
// http://httpwg.org/specs/rfc7541.html#rfc.section.C.2.3
TEST_F(HpackBlockDecoderTest, SpecExample_C_2_3) {
NoArgValidator do_check =
base::Bind(&HpackBlockDecoderTest::ValidateForSpecExample_C_2_3,
base::Unretained(this));
NoArgValidator do_check = [this]() {
VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleLiteralNameValueHeader(
HpackEntryType::kNeverIndexedLiteralHeader, false, "password", false,
"secret"));
};
EXPECT_TRUE(
DecodeHpackExampleAndValidateSeveralWays(R"(
10 | == Literal never indexed ==
......@@ -162,14 +140,14 @@ TEST_F(HpackBlockDecoderTest, SpecExample_C_2_3) {
| -> password: secret
)",
ValidateDoneAndEmpty(do_check)));
EXPECT_TRUE(do_check.Run());
EXPECT_TRUE(do_check());
}
// http://httpwg.org/specs/rfc7541.html#rfc.section.C.2.4
TEST_F(HpackBlockDecoderTest, SpecExample_C_2_4) {
NoArgValidator do_check =
base::Bind(&HpackBlockDecoderTest::ValidateForSpecExample_C_2_4,
base::Unretained(this));
NoArgValidator do_check = [this]() {
VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleIndexedHeader(2));
};
EXPECT_TRUE(
DecodeHpackExampleAndValidateSeveralWays(R"(
82 | == Indexed - Add ==
......@@ -177,7 +155,7 @@ TEST_F(HpackBlockDecoderTest, SpecExample_C_2_4) {
| -> :method: GET
)",
ValidateDoneAndEmpty(do_check)));
EXPECT_TRUE(do_check.Run());
EXPECT_TRUE(do_check());
}
// http://httpwg.org/specs/rfc7541.html#rfc.section.C.3.1
TEST_F(HpackBlockDecoderTest, SpecExample_C_3_1) {
......@@ -205,11 +183,12 @@ TEST_F(HpackBlockDecoderTest, SpecExample_C_3_1) {
expected.ExpectIndexedHeader(4);
expected.ExpectNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader,
1, false, "www.example.com");
NoArgValidator do_check = base::Bind(&HpackBlockDecoderTest::VerifyExpected,
base::Unretained(this), expected);
NoArgValidator do_check = [expected, this]() {
VERIFY_AND_RETURN_SUCCESS(collector_.VerifyEq(expected));
};
EXPECT_TRUE(DecodeHpackExampleAndValidateSeveralWays(
example, ValidateDoneAndEmpty(do_check)));
EXPECT_TRUE(do_check.Run());
EXPECT_TRUE(do_check());
}
// http://httpwg.org/specs/rfc7541.html#rfc.section.C.5.1
......@@ -254,11 +233,12 @@ TEST_F(HpackBlockDecoderTest, SpecExample_C_5_1) {
"Mon, 21 Oct 2013 20:13:21 GMT");
expected.ExpectNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader,
46, false, "https://www.example.com");
NoArgValidator do_check = base::Bind(&HpackBlockDecoderTest::VerifyExpected,
base::Unretained(this), expected);
NoArgValidator do_check = [expected, this]() {
VERIFY_AND_RETURN_SUCCESS(collector_.VerifyEq(expected));
};
EXPECT_TRUE(DecodeHpackExampleAndValidateSeveralWays(
example, ValidateDoneAndEmpty(do_check)));
EXPECT_TRUE(do_check.Run());
EXPECT_TRUE(do_check());
}
// Generate a bunch of HPACK block entries to expect, use those expectations
......@@ -303,11 +283,12 @@ TEST_F(HpackBlockDecoderTest, Computed) {
HpackBlockBuilder hbb;
expected.AppendToHpackBlockBuilder(&hbb);
NoArgValidator do_check = base::Bind(&HpackBlockDecoderTest::VerifyExpected,
base::Unretained(this), expected);
NoArgValidator do_check = [expected, this]() {
VERIFY_AND_RETURN_SUCCESS(collector_.VerifyEq(expected));
};
EXPECT_TRUE(
DecodeAndValidateSeveralWays(hbb, ValidateDoneAndEmpty(do_check)));
EXPECT_TRUE(do_check.Run());
EXPECT_TRUE(do_check());
}
} // namespace
......
......@@ -6,8 +6,6 @@
// Tests of HpackEntryDecoder.
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "net/http2/hpack/decoder/hpack_entry_collector.h"
#include "net/http2/hpack/tools/hpack_block_builder.h"
#include "net/http2/tools/failure.h"
......@@ -23,25 +21,6 @@ namespace test {
namespace {
class HpackEntryDecoderTest : public RandomDecoderTest {
public:
AssertionResult ValidateIndexedHeader(uint32_t ndx) {
VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(ndx));
}
AssertionResult ValidateForIndexedLiteralValue_Literal() {
VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralValueHeader(
HpackEntryType::kIndexedLiteralHeader, 0x40, false, "custom-header"));
}
AssertionResult ValidateForIndexedLiteralNameValue_Literal() {
VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralNameValueHeader(
HpackEntryType::kIndexedLiteralHeader, false, "custom-key", false,
"custom-header"));
}
AssertionResult ValidateForDynamicTableSizeUpdate_Literal() {
VERIFY_AND_RETURN_SUCCESS(collector_.ValidateDynamicTableSizeUpdate(31));
}
protected:
HpackEntryDecoderTest() : listener_(&collector_) {}
......@@ -79,34 +58,34 @@ TEST_F(HpackEntryDecoderTest, IndexedHeader_Literals) {
{
const char input[] = {0x82u}; // == Index 2 ==
DecodeBuffer b(input);
NoArgValidator do_check =
base::Bind(&HpackEntryDecoderTest::ValidateIndexedHeader,
base::Unretained(this), 2);
NoArgValidator do_check = [this]() {
VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(2));
};
EXPECT_TRUE(
DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check)));
EXPECT_TRUE(do_check.Run());
EXPECT_TRUE(do_check());
}
collector_.Clear();
{
const char input[] = {0xfeu}; // == Index 126 ==
DecodeBuffer b(input);
NoArgValidator do_check =
base::Bind(&HpackEntryDecoderTest::ValidateIndexedHeader,
base::Unretained(this), 126);
NoArgValidator do_check = [this]() {
VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(126));
};
EXPECT_TRUE(
DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check)));
EXPECT_TRUE(do_check.Run());
EXPECT_TRUE(do_check());
}
collector_.Clear();
{
const char input[] = {0xffu, 0x00}; // == Index 127 ==
DecodeBuffer b(input);
NoArgValidator do_check =
base::Bind(&HpackEntryDecoderTest::ValidateIndexedHeader,
base::Unretained(this), 127);
NoArgValidator do_check = [this]() {
VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(127));
};
EXPECT_TRUE(
DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check)));
EXPECT_TRUE(do_check.Run());
EXPECT_TRUE(do_check());
}
}
......@@ -116,12 +95,12 @@ TEST_F(HpackEntryDecoderTest, IndexedHeader_Various) {
HpackBlockBuilder hbb;
hbb.AppendIndexedHeader(ndx);
NoArgValidator do_check =
base::Bind(&HpackEntryDecoderTest::ValidateIndexedHeader,
base::Unretained(this), ndx);
NoArgValidator do_check = [this, ndx]() {
VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(ndx));
};
EXPECT_TRUE(
DecodeAndValidateSeveralWays(hbb, ValidateDoneAndEmpty(do_check)));
EXPECT_TRUE(do_check.Run());
EXPECT_TRUE(do_check());
}
}
......@@ -132,11 +111,12 @@ TEST_F(HpackEntryDecoderTest, IndexedLiteralValue_Literal) {
"\x0d" // Value length (13)
"custom-header"; // Value
DecodeBuffer b(input, sizeof input - 1);
NoArgValidator do_check =
base::Bind(&HpackEntryDecoderTest::ValidateForIndexedLiteralValue_Literal,
base::Unretained(this));
NoArgValidator do_check = [this]() {
VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralValueHeader(
HpackEntryType::kIndexedLiteralHeader, 0x40, false, "custom-header"));
};
EXPECT_TRUE(DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check)));
EXPECT_TRUE(do_check.Run());
EXPECT_TRUE(do_check());
}
TEST_F(HpackEntryDecoderTest, IndexedLiteralNameValue_Literal) {
......@@ -148,45 +128,29 @@ TEST_F(HpackEntryDecoderTest, IndexedLiteralNameValue_Literal) {
"custom-header"; // Value
DecodeBuffer b(input, sizeof input - 1);
NoArgValidator do_check = base::Bind(
&HpackEntryDecoderTest::ValidateForIndexedLiteralNameValue_Literal,
base::Unretained(this));
NoArgValidator do_check = [this]() {
VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralNameValueHeader(
HpackEntryType::kIndexedLiteralHeader, false, "custom-key", false,
"custom-header"));
};
EXPECT_TRUE(DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check)));
EXPECT_TRUE(do_check.Run());
EXPECT_TRUE(do_check());
}
TEST_F(HpackEntryDecoderTest, DynamicTableSizeUpdate_Literal) {
// Size update, length 31.
const char input[] = "\x3f\x00";
DecodeBuffer b(input, 2);
NoArgValidator do_check = base::Bind(
&HpackEntryDecoderTest::ValidateForDynamicTableSizeUpdate_Literal,
base::Unretained(this));
NoArgValidator do_check = [this]() {
VERIFY_AND_RETURN_SUCCESS(collector_.ValidateDynamicTableSizeUpdate(31));
};
EXPECT_TRUE(DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check)));
EXPECT_TRUE(do_check.Run());
EXPECT_TRUE(do_check());
}
class HpackLiteralEntryDecoderTest
: public HpackEntryDecoderTest,
public ::testing::WithParamInterface<HpackEntryType> {
public:
AssertionResult ValidateForRandNameIndexAndLiteralValue(
uint32_t ndx,
bool value_is_huffman_encoded,
const string& value) {
VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralValueHeader(
entry_type_, ndx, value_is_huffman_encoded, value));
}
AssertionResult ValidateForRandLiteralNameAndValue(
bool name_is_huffman_encoded,
const string& name,
bool value_is_huffman_encoded,
const string& value) {
VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralNameValueHeader(
entry_type_, name_is_huffman_encoded, name, value_is_huffman_encoded,
value));
}
protected:
HpackLiteralEntryDecoderTest() : entry_type_(GetParam()) {}
......@@ -209,12 +173,14 @@ TEST_P(HpackLiteralEntryDecoderTest, RandNameIndexAndLiteralValue) {
HpackBlockBuilder hbb;
hbb.AppendNameIndexAndLiteralValue(entry_type_, ndx,
value_is_huffman_encoded, value);
NoArgValidator do_check = base::Bind(
&HpackLiteralEntryDecoderTest::ValidateForRandNameIndexAndLiteralValue,
base::Unretained(this), ndx, value_is_huffman_encoded, value);
NoArgValidator do_check = [this, ndx, value_is_huffman_encoded,
value]() -> AssertionResult {
VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralValueHeader(
entry_type_, ndx, value_is_huffman_encoded, value));
};
EXPECT_TRUE(
DecodeAndValidateSeveralWays(hbb, ValidateDoneAndEmpty(do_check)));
EXPECT_TRUE(do_check.Run());
EXPECT_TRUE(do_check());
}
}
......@@ -229,13 +195,16 @@ TEST_P(HpackLiteralEntryDecoderTest, RandLiteralNameAndValue) {
HpackBlockBuilder hbb;
hbb.AppendLiteralNameAndValue(entry_type_, name_is_huffman_encoded, name,
value_is_huffman_encoded, value);
NoArgValidator do_check = base::Bind(
&HpackLiteralEntryDecoderTest::ValidateForRandLiteralNameAndValue,
base::Unretained(this), name_is_huffman_encoded, name,
value_is_huffman_encoded, value);
NoArgValidator do_check = [this, name_is_huffman_encoded, name,
value_is_huffman_encoded,
value]() -> AssertionResult {
VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralNameValueHeader(
entry_type_, name_is_huffman_encoded, name, value_is_huffman_encoded,
value));
};
EXPECT_TRUE(
DecodeAndValidateSeveralWays(hbb, ValidateDoneAndEmpty(do_check)));
EXPECT_TRUE(do_check.Run());
EXPECT_TRUE(do_check());
}
}
......
......@@ -6,8 +6,6 @@
#include <vector>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "net/http2/hpack/tools/hpack_block_builder.h"
#include "net/http2/tools/failure.h"
......@@ -24,19 +22,6 @@ namespace {
const bool kReturnNonZeroOnFirst = true;
class HpackEntryTypeDecoderTest : public RandomDecoderTest {
public:
AssertionResult ValidatorForDynamicTableSizeUpdate(uint32_t size) {
VERIFY_EQ(HpackEntryType::kDynamicTableSizeUpdate, decoder_.entry_type());
VERIFY_EQ(size, decoder_.varint());
return AssertionSuccess();
}
AssertionResult ValidatorForHeaderWithIndex(const HpackEntryType entry_type,
uint32_t index) {
VERIFY_EQ(entry_type, decoder_.entry_type());
VERIFY_EQ(index, decoder_.varint());
return AssertionSuccess();
}
protected:
DecodeStatus StartDecoding(DecodeBuffer* b) override {
......@@ -56,15 +41,17 @@ TEST_F(HpackEntryTypeDecoderTest, DynamicTableSizeUpdate) {
HpackBlockBuilder bb;
bb.AppendDynamicTableSizeUpdate(size);
DecodeBuffer db(bb.buffer());
NoArgValidator validator = base::Bind(
&HpackEntryTypeDecoderTest::ValidatorForDynamicTableSizeUpdate,
base::Unretained(this), size);
NoArgValidator validator = [size, this]() -> AssertionResult {
VERIFY_EQ(HpackEntryType::kDynamicTableSizeUpdate, decoder_.entry_type());
VERIFY_EQ(size, decoder_.varint());
return AssertionSuccess();
};
EXPECT_TRUE(DecodeAndValidateSeveralWays(&db, kReturnNonZeroOnFirst,
ValidateDoneAndEmpty(validator)))
<< "\nentry_type=kDynamicTableSizeUpdate, size=" << size;
// Run the validator again to make sure that DecodeAndValidateSeveralWays
// did the right thing.
EXPECT_TRUE(validator.Run());
EXPECT_TRUE(validator());
}
}
......@@ -80,15 +67,18 @@ TEST_F(HpackEntryTypeDecoderTest, HeaderWithIndex) {
HpackBlockBuilder bb;
bb.AppendEntryTypeAndVarint(entry_type, index);
DecodeBuffer db(bb.buffer());
NoArgValidator validator =
base::Bind(&HpackEntryTypeDecoderTest::ValidatorForHeaderWithIndex,
base::Unretained(this), entry_type, index);
NoArgValidator validator = [entry_type, index,
this]() -> AssertionResult {
VERIFY_EQ(entry_type, decoder_.entry_type());
VERIFY_EQ(index, decoder_.varint());
return AssertionSuccess();
};
EXPECT_TRUE(DecodeAndValidateSeveralWays(&db, kReturnNonZeroOnFirst,
ValidateDoneAndEmpty(validator)))
<< "\nentry_type=" << entry_type << ", index=" << index;
// Run the validator again to make sure that DecodeAndValidateSeveralWays
// did the right thing.
EXPECT_TRUE(validator.Run());
EXPECT_TRUE(validator());
}
}
}
......
......@@ -6,8 +6,6 @@
// Tests of HpackStringDecoder.
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/strings/string_piece.h"
#include "net/http2/hpack/decoder/hpack_string_collector.h"
#include "net/http2/hpack/decoder/hpack_string_decoder_listener.h"
......@@ -74,32 +72,27 @@ class HpackStringDecoderTest
return collector_.Collected(s, huffman_encoded);
}
// Note that base::Bind() makes a copy of |expected_str| even though it is
// taken as a constant reference, so even if MakeValidator is called with a
// C-style string that is cast to a temporary std::string that gets destroyed
// after the call to MakeValidator, |expected_str| is still valid later when
// the Validator is run.
AssertionResult StringValidator(const string& expected_str,
bool expected_huffman,
const DecodeBuffer& input,
DecodeStatus status) {
AssertionResult result = Collected(expected_str, expected_huffman);
if (result) {
VERIFY_EQ(collector_,
HpackStringCollector(expected_str, expected_huffman));
} else {
VERIFY_NE(collector_,
HpackStringCollector(expected_str, expected_huffman));
}
VLOG(2) << collector_.ToString();
collector_.Clear();
VLOG(2) << collector_;
return result;
}
// expected_str is a string rather than a const string& or StringPiece so that
// the lambda makes a copy of the string, and thus the string to be passed to
// Collected outlives the call to MakeValidator.
Validator MakeValidator(const string& expected_str, bool expected_huffman) {
return base::Bind(&HpackStringDecoderTest::StringValidator,
base::Unretained(this), expected_str, expected_huffman);
return
[expected_str, expected_huffman, this](
const DecodeBuffer& input, DecodeStatus status) -> AssertionResult {
AssertionResult result = Collected(expected_str, expected_huffman);
if (result) {
VERIFY_EQ(collector_,
HpackStringCollector(expected_str, expected_huffman));
} else {
VERIFY_NE(collector_,
HpackStringCollector(expected_str, expected_huffman));
}
VLOG(2) << collector_.ToString();
collector_.Clear();
VLOG(2) << collector_;
return result;
};
}
const StartMethod start_method_;
......
......@@ -15,8 +15,6 @@
#include <sstream>
#include <vector>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
......@@ -38,16 +36,6 @@ namespace test {
namespace {
class HpackVarintDecoderTest : public RandomDecoderTest {
public:
AssertionResult ValidatorForValueTooLarge(bool* validated,
uint32_t expected_offset,
const DecodeBuffer& db,
DecodeStatus status) {
*validated = true;
VERIFY_EQ(DecodeStatus::kDecodeError, status);
VERIFY_EQ(expected_offset, db.Offset());
return AssertionSuccess();
}
protected:
DecodeStatus StartDecoding(DecodeBuffer* b) override {
......@@ -61,24 +49,19 @@ class HpackVarintDecoderTest : public RandomDecoderTest {
return decoder_.Resume(b);
}
AssertionResult ValidatorForDecodeSeveralWays(uint32_t expected_value,
const DecodeBuffer& db,
DecodeStatus status) {
if (decoder_.value() != expected_value) {
return AssertionFailure()
<< "Value doesn't match expected: " << decoder_.value()
<< " != " << expected_value;
}
return AssertionSuccess();
}
void DecodeSeveralWays(uint32_t expected_value, uint32_t expected_offset) {
// The validator is called after each of the several times that the input
// DecodeBuffer is decoded, each with a different segmentation of the input.
// Validate that decoder_.value() matches the expected value.
Validator validator =
base::Bind(&HpackVarintDecoderTest::ValidatorForDecodeSeveralWays,
base::Unretained(this), expected_value);
Validator validator = [expected_value, this](
const DecodeBuffer& db, DecodeStatus status) -> AssertionResult {
if (decoder_.value() != expected_value) {
return AssertionFailure()
<< "Value doesn't match expected: " << decoder_.value()
<< " != " << expected_value;
}
return AssertionSuccess();
};
// First validate that decoding is done and that we've advanced the cursor
// the expected amount.
......@@ -375,9 +358,13 @@ TEST_F(HpackVarintDecoderTest, ValueTooLarge) {
// DecodeBuffer is decoded, each with a different segmentation of the input.
// Validate that decoder_.value() matches the expected value.
bool validated = false;
Validator validator =
base::Bind(&HpackVarintDecoderTest::ValidatorForValueTooLarge,
base::Unretained(this), &validated, expected_offset);
Validator validator = [&validated, expected_offset](
const DecodeBuffer& db, DecodeStatus status) -> AssertionResult {
validated = true;
VERIFY_EQ(DecodeStatus::kDecodeError, status);
VERIFY_EQ(expected_offset, db.Offset());
return AssertionSuccess();
};
// StartDecoding, above, requires the DecodeBuffer be non-empty so that it
// can call Start with the prefix byte.
......
......@@ -9,8 +9,6 @@
#include <iostream>
#include <string>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/macros.h"
#include "base/strings/string_piece.h"
#include "net/http2/decoder/decode_buffer.h"
......@@ -202,25 +200,19 @@ class HpackHuffmanDecoderTest
return false;
}
AssertionResult ValidatorForHuffmanDecodeAndValidateSeveralWays(
StringPiece expected_plain) {
VERIFY_EQ(output_buffer_.size(), expected_plain.size());
VERIFY_EQ(output_buffer_, expected_plain);
return AssertionSuccess();
}
AssertionResult HuffmanDecodeAndValidateSeveralWays(
StringPiece encoded,
StringPiece expected_plain) {
input_bytes_expected_ = encoded.size();
NoArgValidator validator = [expected_plain, this]() -> AssertionResult {
VERIFY_EQ(output_buffer_.size(), expected_plain.size());
VERIFY_EQ(output_buffer_, expected_plain);
return AssertionSuccess();
};
DecodeBuffer db(encoded);
bool return_non_zero_on_first = false;
return DecodeAndValidateSeveralWays(
&db, return_non_zero_on_first,
ValidateDoneAndEmpty(
base::Bind(&HpackHuffmanDecoderTest::
ValidatorForHuffmanDecodeAndValidateSeveralWays,
base::Unretained(this), expected_plain)));
return DecodeAndValidateSeveralWays(&db, return_non_zero_on_first,
ValidateDoneAndEmpty(validator));
}
HpackHuffmanDecoder decoder_;
......
......@@ -127,8 +127,7 @@ AssertionResult RandomDecoderTest::DecodeAndValidateSeveralWays(
DecodeBuffer input(original->cursor(), original_remaining);
VLOG(2) << "DecodeSegmentsAndValidate with SelectRandom";
VERIFY_SUCCESS(DecodeSegmentsAndValidate(
&input, RandomDecoderTest::SelectRandom(return_non_zero_on_first),
validator))
&input, SelectRandom(return_non_zero_on_first), validator))
<< "\nFailed with SelectRandom; input.Offset=" << input.Offset()
<< "; input.Remaining=" << input.Remaining();
VERIFY_EQ(first_consumed, input.Offset()) << "\nFailed with SelectRandom";
......
......@@ -12,12 +12,11 @@
#include <stddef.h>
#include <functional>
#include <memory>
#include <string>
#include <type_traits>
#include "base/bind.h"
#include "base/callback.h"
#include "base/logging.h"
#include "base/strings/string_piece.h"
#include "base/template_util.h"
......@@ -71,10 +70,10 @@ class RandomDecoderTest : public ::testing::Test {
// Validator returns an AssertionResult so test can do:
// EXPECT_THAT(DecodeAndValidate(..., validator));
typedef ::testing::AssertionResult AssertionResult;
typedef base::Callback<AssertionResult(const DecodeBuffer& input,
DecodeStatus status)>
typedef std::function<AssertionResult(const DecodeBuffer& input,
DecodeStatus status)>
Validator;
typedef base::Callback<AssertionResult()> NoArgValidator;
typedef std::function<AssertionResult()> NoArgValidator;
RandomDecoderTest();
......@@ -120,7 +119,7 @@ class RandomDecoderTest : public ::testing::Test {
const SelectSize& select_size,
const Validator& validator) {
DecodeStatus status = DecodeSegments(original, select_size);
VERIFY_AND_RETURN_SUCCESS(validator.Run(*original, status));
VERIFY_AND_RETURN_SUCCESS(validator(*original, status));
}
// Returns a SelectSize function for fast decoding, i.e. passing all that
......@@ -152,21 +151,26 @@ class RandomDecoderTest : public ::testing::Test {
bool return_non_zero_on_first,
const Validator& validator);
static AssertionResult SucceedingValidator(const DecodeBuffer& input,
DecodeStatus status) {
return ::testing::AssertionSuccess();
static Validator ToValidator(std::nullptr_t) {
return [](const DecodeBuffer& input, DecodeStatus status) {
return ::testing::AssertionSuccess();
};
}
static Validator ToValidator(const Validator& validator) { return validator; }
static AssertionResult RunNoArgValidator(const NoArgValidator& validator,
const DecodeBuffer& input,
DecodeStatus status) {
return validator.Run();
static Validator ToValidator(const Validator& validator) {
if (validator == nullptr) {
return ToValidator(nullptr);
}
return validator;
}
static Validator ToValidator(const NoArgValidator& validator) {
return base::Bind(&RunNoArgValidator, validator);
if (validator == nullptr) {
return ToValidator(nullptr);
}
return [validator](const DecodeBuffer& input, DecodeStatus status) {
return validator();
};
}
// Wraps a validator with another validator
......@@ -175,29 +179,31 @@ class RandomDecoderTest : public ::testing::Test {
// TODO(jamessynge): Replace this overload with the next, as using this method
// usually means that the wrapped function doesn't need to be passed the
// DecodeBuffer nor the DecodeStatus.
static AssertionResult ValidateDoneAndEmptyImpl(const Validator& wrapped,
const DecodeBuffer& input,
DecodeStatus status) {
VERIFY_EQ(status, DecodeStatus::kDecodeDone);
VERIFY_EQ(0u, input.Remaining()) << "\nOffset=" << input.Offset();
return wrapped.Run(input, status);
}
static Validator ValidateDoneAndEmpty(const Validator& wrapped) {
return base::Bind(&ValidateDoneAndEmptyImpl, wrapped);
}
static AssertionResult ValidateDoneAndEmptyNoArgImpl(
const NoArgValidator& wrapped,
const DecodeBuffer& input,
DecodeStatus status) {
VERIFY_EQ(status, DecodeStatus::kDecodeDone);
VERIFY_EQ(0u, input.Remaining()) << "\nOffset=" << input.Offset();
return wrapped.Run();
return [wrapped](const DecodeBuffer& input,
DecodeStatus status) -> AssertionResult {
VERIFY_EQ(status, DecodeStatus::kDecodeDone);
VERIFY_EQ(0u, input.Remaining()) << "\nOffset=" << input.Offset();
if (wrapped) {
return wrapped(input, status);
}
return ::testing::AssertionSuccess();
};
}
static Validator ValidateDoneAndEmpty(const NoArgValidator& wrapped) {
return base::Bind(&ValidateDoneAndEmptyNoArgImpl, wrapped);
static Validator ValidateDoneAndEmpty(NoArgValidator wrapped) {
return [wrapped](const DecodeBuffer& input,
DecodeStatus status) -> AssertionResult {
VERIFY_EQ(status, DecodeStatus::kDecodeDone);
VERIFY_EQ(0u, input.Remaining()) << "\nOffset=" << input.Offset();
if (wrapped) {
return wrapped();
}
return ::testing::AssertionSuccess();
};
}
static Validator ValidateDoneAndEmpty() {
return ValidateDoneAndEmpty(base::Bind(&SucceedingValidator));
NoArgValidator validator;
return ValidateDoneAndEmpty(validator);
}
// Wraps a validator with another validator
......@@ -206,39 +212,32 @@ class RandomDecoderTest : public ::testing::Test {
// TODO(jamessynge): Replace this overload with the next, as using this method
// usually means that the wrapped function doesn't need to be passed the
// DecodeBuffer nor the DecodeStatus.
static AssertionResult ValidateDoneAndOffsetImpl(uint32_t offset,
const Validator& wrapped,
const DecodeBuffer& input,
DecodeStatus status) {
VERIFY_EQ(status, DecodeStatus::kDecodeDone);
VERIFY_EQ(offset, input.Offset()) << "\nRemaining=" << input.Remaining();
return wrapped.Run(input, status);
}
static Validator ValidateDoneAndOffset(uint32_t offset,
const Validator& wrapped) {
// Make a copy of |wrapped| (by not using base::ConstRef) to avoid lifetime
// issues if this method is called with a temporary Validator.
return base::Bind(&ValidateDoneAndOffsetImpl, offset, wrapped);
}
static AssertionResult ValidateDoneAndOffsetNoArgImpl(
uint32_t offset,
const NoArgValidator& wrapped,
const DecodeBuffer& input,
DecodeStatus status) {
VERIFY_EQ(status, DecodeStatus::kDecodeDone);
VERIFY_EQ(offset, input.Offset()) << "\nRemaining=" << input.Remaining();
return wrapped.Run();
static Validator ValidateDoneAndOffset(uint32_t offset, Validator wrapped) {
return [wrapped, offset](const DecodeBuffer& input,
DecodeStatus status) -> AssertionResult {
VERIFY_EQ(status, DecodeStatus::kDecodeDone);
VERIFY_EQ(offset, input.Offset()) << "\nRemaining=" << input.Remaining();
if (wrapped) {
return wrapped(input, status);
}
return ::testing::AssertionSuccess();
};
}
static Validator ValidateDoneAndOffset(uint32_t offset,
const NoArgValidator& wrapped) {
// Make a copy of |wrapped| (by not using base::ConstRef) to avoid lifetime
// issues if this method is called with a temporary Validator.
return base::Bind(&ValidateDoneAndOffsetNoArgImpl, offset, wrapped);
NoArgValidator wrapped) {
return [wrapped, offset](const DecodeBuffer& input,
DecodeStatus status) -> AssertionResult {
VERIFY_EQ(status, DecodeStatus::kDecodeDone);
VERIFY_EQ(offset, input.Offset()) << "\nRemaining=" << input.Remaining();
if (wrapped) {
return wrapped();
}
return ::testing::AssertionSuccess();
};
}
static Validator ValidateDoneAndOffset(uint32_t offset) {
// Make a copy of |wrapped| (by not using base::ConstRef) to avoid lifetime
// issues if this method is called with a temporary Validator.
return ValidateDoneAndOffset(offset, base::Bind(&SucceedingValidator));
NoArgValidator validator;
return ValidateDoneAndOffset(offset, validator);
}
// Expose |random_| as RandomBase so callers do not have to care about which
......
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