blob: 2b8f6162c6d13ecd4599331c4a7942f5555d1aff [file] [log] [blame]
// 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 "quiche/http2/test_tools/frame_parts_collector.h"
#include <utility>
#include "quiche/http2/test_tools/http2_structures_test_util.h"
#include "quiche/common/platform/api/quiche_logging.h"
#include "quiche/common/platform/api/quiche_test.h"
namespace http2 {
namespace test {
FramePartsCollector::FramePartsCollector() = default;
FramePartsCollector::~FramePartsCollector() = default;
void FramePartsCollector::Reset() {
current_frame_.reset();
collected_frames_.clear();
expected_header_set_ = false;
}
const FrameParts* FramePartsCollector::frame(size_t n) const {
if (n < size()) {
return collected_frames_.at(n).get();
}
QUICHE_CHECK(n == size());
return current_frame();
}
void FramePartsCollector::ExpectFrameHeader(const Http2FrameHeader& header) {
EXPECT_FALSE(IsInProgress());
EXPECT_FALSE(expected_header_set_)
<< "expected_header_: " << expected_header_;
expected_header_ = header;
expected_header_set_ = true;
// OnFrameHeader is called before the flags are scrubbed, but the other
// methods are called after, so scrub the invalid flags from expected_header_.
ScrubFlagsOfHeader(&expected_header_);
}
void FramePartsCollector::TestExpectedHeader(const Http2FrameHeader& header) {
if (expected_header_set_) {
EXPECT_EQ(header, expected_header_);
expected_header_set_ = false;
}
}
Http2FrameDecoderListener* FramePartsCollector::StartFrame(
const Http2FrameHeader& header) {
TestExpectedHeader(header);
EXPECT_FALSE(IsInProgress());
if (current_frame_ == nullptr) {
current_frame_ = std::make_unique<FrameParts>(header);
}
return current_frame();
}
Http2FrameDecoderListener* FramePartsCollector::StartAndEndFrame(
const Http2FrameHeader& header) {
TestExpectedHeader(header);
EXPECT_FALSE(IsInProgress());
if (current_frame_ == nullptr) {
current_frame_ = std::make_unique<FrameParts>(header);
}
Http2FrameDecoderListener* result = current_frame();
collected_frames_.push_back(std::move(current_frame_));
return result;
}
Http2FrameDecoderListener* FramePartsCollector::CurrentFrame() {
EXPECT_TRUE(IsInProgress());
if (current_frame_ == nullptr) {
return &failing_listener_;
}
return current_frame();
}
Http2FrameDecoderListener* FramePartsCollector::EndFrame() {
EXPECT_TRUE(IsInProgress());
if (current_frame_ == nullptr) {
return &failing_listener_;
}
Http2FrameDecoderListener* result = current_frame();
collected_frames_.push_back(std::move(current_frame_));
return result;
}
Http2FrameDecoderListener* FramePartsCollector::FrameError(
const Http2FrameHeader& header) {
TestExpectedHeader(header);
if (current_frame_ == nullptr) {
// The decoder may detect an error before making any calls to the listener
// regarding the frame, in which case current_frame_==nullptr and we need
// to create a FrameParts instance.
current_frame_ = std::make_unique<FrameParts>(header);
} else {
// Similarly, the decoder may have made calls to the listener regarding the
// frame before detecting the error; for example, the DATA payload decoder
// calls OnDataStart before it can detect padding errors, hence before it
// can call OnPaddingTooLong.
EXPECT_EQ(header, current_frame_->GetFrameHeader());
}
Http2FrameDecoderListener* result = current_frame();
collected_frames_.push_back(std::move(current_frame_));
return result;
}
} // namespace test
} // namespace http2