|  | // 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 "http2/test_tools/frame_parts_collector.h" | 
|  |  | 
|  | #include <utility> | 
|  |  | 
|  | #include "http2/http2_structures_test_util.h" | 
|  | #include "http2/platform/api/http2_logging.h" | 
|  | #include "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 |