Index: net/http2/decoder/http2_frame_decoder_test.cc |
diff --git a/net/http2/decoder/http2_frame_decoder_test.cc b/net/http2/decoder/http2_frame_decoder_test.cc |
deleted file mode 100644 |
index c2ec0a0dbc2650b97306d49afd1228c63de49afe..0000000000000000000000000000000000000000 |
--- a/net/http2/decoder/http2_frame_decoder_test.cc |
+++ /dev/null |
@@ -1,946 +0,0 @@ |
-// 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/http2/decoder/http2_frame_decoder.h" |
- |
-// Tests of Http2FrameDecoder. |
- |
-#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" |
-#include "net/http2/http2_constants.h" |
-#include "net/http2/tools/failure.h" |
-#include "net/http2/tools/http2_random.h" |
-#include "net/http2/tools/random_decoder_test.h" |
-#include "testing/gtest/include/gtest/gtest.h" |
- |
-using base::StringPiece; |
-using std::string; |
-using ::testing::AssertionResult; |
-using ::testing::AssertionSuccess; |
- |
-namespace net { |
-namespace test { |
-class Http2FrameDecoderPeer { |
- public: |
- static size_t remaining_total_payload(Http2FrameDecoder* decoder) { |
- return decoder->frame_decoder_state_.remaining_total_payload(); |
- } |
-}; |
- |
-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 { |
- // On any one run of this suite, we'll always choose the same value for |
- // use_default_reconstruct_ because the random seed is the same for each |
- // test case, but across runs the random seed changes. |
- use_default_reconstruct_ = Random().OneIn(2); |
- } |
- |
- DecodeStatus StartDecoding(DecodeBuffer* db) override { |
- DVLOG(2) << "StartDecoding, db->Remaining=" << db->Remaining(); |
- collector_.Reset(); |
- PrepareDecoder(); |
- |
- DecodeStatus status = decoder_.DecodeFrame(db); |
- if (status != DecodeStatus::kDecodeInProgress) { |
- // Keep track of this so that a concrete test can verify that both fast |
- // and slow decoding paths have been tested. |
- ++fast_decode_count_; |
- if (status == DecodeStatus::kDecodeError) { |
- ConfirmDiscardsRemainingPayload(); |
- } |
- } |
- return status; |
- } |
- |
- DecodeStatus ResumeDecoding(DecodeBuffer* db) override { |
- DVLOG(2) << "ResumeDecoding, db->Remaining=" << db->Remaining(); |
- DecodeStatus status = decoder_.DecodeFrame(db); |
- if (status != DecodeStatus::kDecodeInProgress) { |
- // Keep track of this so that a concrete test can verify that both fast |
- // and slow decoding paths have been tested. |
- ++slow_decode_count_; |
- if (status == DecodeStatus::kDecodeError) { |
- ConfirmDiscardsRemainingPayload(); |
- } |
- } |
- return status; |
- } |
- |
- // When an error is returned, the decoder is in state kDiscardPayload, and |
- // stays there until the remaining bytes of the frame's payload have been |
- // skipped over. There are no callbacks for this situation. |
- void ConfirmDiscardsRemainingPayload() { |
- ASSERT_TRUE(decoder_.IsDiscardingPayload()); |
- size_t remaining = |
- Http2FrameDecoderPeer::remaining_total_payload(&decoder_); |
- // The decoder will discard the remaining bytes, but not go beyond that, |
- // which these conditions verify. |
- size_t extra = 10; |
- string junk(remaining + extra, '0'); |
- DecodeBuffer tmp(junk); |
- EXPECT_EQ(DecodeStatus::kDecodeDone, decoder_.DecodeFrame(&tmp)); |
- EXPECT_EQ(remaining, tmp.Offset()); |
- EXPECT_EQ(extra, tmp.Remaining()); |
- EXPECT_FALSE(decoder_.IsDiscardingPayload()); |
- } |
- |
- void PrepareDecoder() { |
- // Save and restore the maximum_payload_size when reconstructing |
- // the decoder. |
- size_t maximum_payload_size = decoder_.maximum_payload_size(); |
- |
- // Alternate which constructor is used. |
- if (use_default_reconstruct_) { |
- decoder_.~Http2FrameDecoder(); |
- new (&decoder_) Http2FrameDecoder; |
- decoder_.set_listener(&collector_); |
- } else { |
- decoder_.~Http2FrameDecoder(); |
- new (&decoder_) Http2FrameDecoder(&collector_); |
- } |
- decoder_.set_maximum_payload_size(maximum_payload_size); |
- |
- use_default_reconstruct_ = !use_default_reconstruct_; |
- } |
- |
- void ResetDecodeSpeedCounters() { |
- fast_decode_count_ = 0; |
- slow_decode_count_ = 0; |
- } |
- |
- AssertionResult VerifyCollected(const FrameParts& expected) { |
- VERIFY_FALSE(collector_.IsInProgress()); |
- VERIFY_EQ(1u, collector_.size()); |
- VERIFY_AND_RETURN_SUCCESS(expected.VerifyEquals(*collector_.frame(0))); |
- } |
- |
- AssertionResult DecodePayloadAndValidateSeveralWays(StringPiece payload, |
- Validator validator) { |
- DecodeBuffer db(payload); |
- bool start_decoding_requires_non_empty = false; |
- return DecodeAndValidateSeveralWays(&db, start_decoding_requires_non_empty, |
- 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 |
- // payload will be decoded several times with different partitionings |
- // of the payload, and after each the validator will be called. |
- AssertionResult DecodePayloadAndValidateSeveralWays( |
- StringPiece payload, |
- const FrameParts& expected) { |
- Validator validator = base::Bind( |
- &Http2FrameDecoderTest::ValidatorForDecodePayloadAndValidateSeveralWays, |
- base::Unretained(this), base::ConstRef(expected)); |
- ResetDecodeSpeedCounters(); |
- VERIFY_SUCCESS(DecodePayloadAndValidateSeveralWays( |
- payload, ValidateDoneAndEmpty(validator))); |
- VERIFY_GT(fast_decode_count_, 0u); |
- VERIFY_GT(slow_decode_count_, 0u); |
- |
- // Repeat with more input; it should stop without reading that input. |
- string next_frame = Random().RandString(10); |
- string input; |
- payload.AppendToString(&input); |
- input += next_frame; |
- |
- ResetDecodeSpeedCounters(); |
- VERIFY_SUCCESS(DecodePayloadAndValidateSeveralWays( |
- payload, ValidateDoneAndOffset(payload.size(), validator))); |
- VERIFY_GT(fast_decode_count_, 0u); |
- VERIFY_GT(slow_decode_count_, 0u); |
- |
- return AssertionSuccess(); |
- } |
- |
- template <size_t N> |
- AssertionResult DecodePayloadAndValidateSeveralWays( |
- const char (&buf)[N], |
- const FrameParts& expected) { |
- return DecodePayloadAndValidateSeveralWays(StringPiece(buf, N), expected); |
- } |
- |
- template <size_t N> |
- AssertionResult DecodePayloadAndValidateSeveralWays( |
- const char (&buf)[N], |
- const Http2FrameHeader& header) { |
- return DecodePayloadAndValidateSeveralWays(StringPiece(buf, N), |
- FrameParts(header)); |
- } |
- |
- template <size_t N> |
- AssertionResult DecodePayloadExpectingError(const char (&buf)[N], |
- const FrameParts& expected) { |
- ResetDecodeSpeedCounters(); |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays( |
- ToStringPiece(buf), |
- base::Bind( |
- &Http2FrameDecoderTest::ValidatorForDecodePayloadExpectingError, |
- base::Unretained(this), expected))); |
- EXPECT_GT(fast_decode_count_, 0u); |
- EXPECT_GT(slow_decode_count_, 0u); |
- return AssertionSuccess(); |
- } |
- |
- template <size_t N> |
- AssertionResult DecodePayloadExpectingFrameSizeError(const char (&buf)[N], |
- FrameParts expected) { |
- expected.has_frame_size_error = true; |
- VERIFY_AND_RETURN_SUCCESS(DecodePayloadExpectingError(buf, expected)); |
- } |
- |
- template <size_t N> |
- AssertionResult DecodePayloadExpectingFrameSizeError( |
- const char (&buf)[N], |
- const Http2FrameHeader& header) { |
- return DecodePayloadExpectingFrameSizeError(buf, FrameParts(header)); |
- } |
- |
- // Count of payloads that are fully decoded by StartDecodingPayload or for |
- // which an error was detected by StartDecodingPayload. |
- size_t fast_decode_count_ = 0; |
- |
- // Count of payloads that required calling ResumeDecodingPayload in order to |
- // decode completely, or for which an error was detected by |
- // ResumeDecodingPayload. |
- size_t slow_decode_count_ = 0; |
- |
- FramePartsCollectorListener collector_; |
- Http2FrameDecoder decoder_; |
- bool use_default_reconstruct_; |
-}; |
- |
-//////////////////////////////////////////////////////////////////////////////// |
-// Tests that pass the minimum allowed size for the frame type, which is often |
-// empty. The tests are in order by frame type value (i.e. 0 for DATA frames). |
- |
-TEST_F(Http2FrameDecoderTest, DataEmpty) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x00, // Payload length: 0 |
- 0x00, // DATA |
- 0x00, // Flags: none |
- 0x00, 0x00, 0x00, 0x00, // Stream ID: 0 (invalid but unchecked here) |
- }; |
- Http2FrameHeader header(0, Http2FrameType::DATA, 0, 0); |
- FrameParts expected(header, ""); |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, HeadersEmpty) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x00, // Payload length: 0 |
- 0x01, // HEADERS |
- 0x00, // Flags: none |
- 0x00, 0x00, 0x00, 0x01, // Stream ID: 0 (REQUIRES ID) |
- }; |
- Http2FrameHeader header(0, Http2FrameType::HEADERS, 0, 1); |
- FrameParts expected(header, ""); |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, Priority) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x05, // Length: 5 |
- 0x02, // Type: PRIORITY |
- 0x00, // Flags: none |
- 0x00, 0x00, 0x00, 0x02, // Stream: 2 |
- 0x80u, 0x00, 0x00, 0x01, // Parent: 1 (Exclusive) |
- 0x10, // Weight: 17 |
- }; |
- Http2FrameHeader header(5, Http2FrameType::PRIORITY, 0, 2); |
- FrameParts expected(header); |
- expected.opt_priority = Http2PriorityFields(1, 17, true); |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, RstStream) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x04, // Length: 4 |
- 0x03, // Type: RST_STREAM |
- 0x00, // Flags: none |
- 0x00, 0x00, 0x00, 0x01, // Stream: 1 |
- 0x00, 0x00, 0x00, 0x01, // Error: PROTOCOL_ERROR |
- }; |
- Http2FrameHeader header(4, Http2FrameType::RST_STREAM, 0, 1); |
- FrameParts expected(header); |
- expected.opt_rst_stream_error_code = Http2ErrorCode::PROTOCOL_ERROR; |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, SettingsEmpty) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x00, // Length: 0 |
- 0x04, // Type: SETTINGS |
- 0x00, // Flags: none |
- 0x00, 0x00, 0x00, 0x01, // Stream: 1 (invalid but unchecked here) |
- }; |
- Http2FrameHeader header(0, Http2FrameType::SETTINGS, 0, 1); |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, header)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, SettingsAck) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x00, // Length: 6 |
- 0x04, // Type: SETTINGS |
- 0x01, // Flags: ACK |
- 0x00, 0x00, 0x00, 0x00, // Stream: 0 |
- }; |
- Http2FrameHeader header(0, Http2FrameType::SETTINGS, Http2FrameFlag::FLAG_ACK, |
- 0); |
- FrameParts expected(header); |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, PushPromiseMinimal) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x04, // Payload length: 4 |
- 0x05, // PUSH_PROMISE |
- 0x04, // Flags: END_HEADERS |
- 0x00, 0x00, 0x00, 0x02, // Stream: 2 (invalid but unchecked here) |
- 0x00, 0x00, 0x00, 0x01, // Promised: 1 (invalid but unchecked here) |
- }; |
- Http2FrameHeader header(4, Http2FrameType::PUSH_PROMISE, |
- Http2FrameFlag::FLAG_END_HEADERS, 2); |
- FrameParts expected(header, ""); |
- expected.opt_push_promise = Http2PushPromiseFields{1}; |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, Ping) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x08, // Length: 8 |
- 0x06, // Type: PING |
- 0xfeu, // Flags: no valid flags |
- 0x00, 0x00, 0x00, 0x00, // Stream: 0 |
- 's', 'o', 'm', 'e', // "some" |
- 'd', 'a', 't', 'a', // "data" |
- }; |
- Http2FrameHeader header(8, Http2FrameType::PING, 0, 0); |
- FrameParts expected(header); |
- expected.opt_ping = Http2PingFields{{'s', 'o', 'm', 'e', 'd', 'a', 't', 'a'}}; |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, PingAck) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x08, // Length: 8 |
- 0x06, // Type: PING |
- 0xffu, // Flags: ACK (plus all invalid flags) |
- 0x00, 0x00, 0x00, 0x00, // Stream: 0 |
- 's', 'o', 'm', 'e', // "some" |
- 'd', 'a', 't', 'a', // "data" |
- }; |
- Http2FrameHeader header(8, Http2FrameType::PING, Http2FrameFlag::FLAG_ACK, 0); |
- FrameParts expected(header); |
- expected.opt_ping = Http2PingFields{{'s', 'o', 'm', 'e', 'd', 'a', 't', 'a'}}; |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, GoAwayMinimal) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x08, // Length: 8 (no opaque data) |
- 0x07, // Type: GOAWAY |
- 0xffu, // Flags: 0xff (no valid flags) |
- 0x00, 0x00, 0x00, 0x01, // Stream: 1 (invalid but unchecked here) |
- 0x80u, 0x00, 0x00, 0xffu, // Last: 255 (plus R bit) |
- 0x00, 0x00, 0x00, 0x09, // Error: COMPRESSION_ERROR |
- }; |
- Http2FrameHeader header(8, Http2FrameType::GOAWAY, 0, 1); |
- FrameParts expected(header); |
- expected.opt_goaway = |
- Http2GoAwayFields(255, Http2ErrorCode::COMPRESSION_ERROR); |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, WindowUpdate) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x04, // Length: 4 |
- 0x08, // Type: WINDOW_UPDATE |
- 0x0f, // Flags: 0xff (no valid flags) |
- 0x00, 0x00, 0x00, 0x01, // Stream: 1 |
- 0x80u, 0x00, 0x04, 0x00, // Incr: 1024 (plus R bit) |
- }; |
- Http2FrameHeader header(4, Http2FrameType::WINDOW_UPDATE, 0, 1); |
- FrameParts expected(header); |
- expected.opt_window_update_increment = 1024; |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, ContinuationEmpty) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x00, // Payload length: 0 |
- 0x09, // CONTINUATION |
- 0x00, // Flags: none |
- 0x00, 0x00, 0x00, 0x00, // Stream ID: 0 (invalid but unchecked here) |
- }; |
- Http2FrameHeader header(0, Http2FrameType::CONTINUATION, 0, 0); |
- FrameParts expected(header); |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, AltSvcMinimal) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x02, // Payload length: 2 |
- 0x0a, // ALTSVC |
- 0xffu, // Flags: none (plus 0xff) |
- 0x00, 0x00, 0x00, 0x00, // Stream ID: 0 (invalid but unchecked here) |
- 0x00, 0x00, // Origin Length: 0 |
- }; |
- Http2FrameHeader header(2, Http2FrameType::ALTSVC, 0, 0); |
- FrameParts expected(header); |
- expected.opt_altsvc_origin_length = 0; |
- expected.opt_altsvc_value_length = 0; |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, UnknownEmpty) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x00, // Payload length: 0 |
- 0x20, // 32 (unknown) |
- 0xffu, // Flags: all |
- 0x00, 0x00, 0x00, 0x00, // Stream ID: 0 |
- }; |
- Http2FrameHeader header(0, static_cast<Http2FrameType>(32), 0xff, 0); |
- FrameParts expected(header); |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); |
-} |
- |
-//////////////////////////////////////////////////////////////////////////////// |
-// Tests of longer payloads, for those frame types that allow longer payloads. |
- |
-TEST_F(Http2FrameDecoderTest, DataPayload) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x03, // Payload length: 7 |
- 0x00, // DATA |
- 0x80u, // Flags: 0x80 |
- 0x00, 0x00, 0x02, 0x02, // Stream ID: 514 |
- 'a', 'b', 'c', // Data |
- }; |
- Http2FrameHeader header(3, Http2FrameType::DATA, 0, 514); |
- FrameParts expected(header, "abc"); |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, HeadersPayload) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x03, // Payload length: 3 |
- 0x01, // HEADERS |
- 0x05, // Flags: END_STREAM | END_HEADERS |
- 0x00, 0x00, 0x00, 0x02, // Stream ID: 0 (REQUIRES ID) |
- 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid) |
- }; |
- Http2FrameHeader header( |
- 3, Http2FrameType::HEADERS, |
- Http2FrameFlag::FLAG_END_STREAM | Http2FrameFlag::FLAG_END_HEADERS, 2); |
- FrameParts expected(header, "abc"); |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, HeadersPriority) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x05, // Payload length: 5 |
- 0x01, // HEADERS |
- 0x20, // Flags: PRIORITY |
- 0x00, 0x00, 0x00, 0x02, // Stream ID: 0 (REQUIRES ID) |
- 0x00, 0x00, 0x00, 0x01, // Parent: 1 (Not Exclusive) |
- 0xffu, // Weight: 256 |
- }; |
- Http2FrameHeader header(5, Http2FrameType::HEADERS, |
- Http2FrameFlag::FLAG_PRIORITY, 2); |
- FrameParts expected(header); |
- expected.opt_priority = Http2PriorityFields(1, 256, false); |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, Settings) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x0c, // Length: 12 |
- 0x04, // Type: SETTINGS |
- 0x00, // Flags: none |
- 0x00, 0x00, 0x00, 0x00, // Stream: 0 |
- 0x00, 0x04, // Param: INITIAL_WINDOW_SIZE |
- 0x0a, 0x0b, 0x0c, 0x0d, // Value: 168496141 |
- 0x00, 0x02, // Param: ENABLE_PUSH |
- 0x00, 0x00, 0x00, 0x03, // Value: 3 (invalid but unchecked here) |
- }; |
- Http2FrameHeader header(12, Http2FrameType::SETTINGS, 0, 0); |
- FrameParts expected(header); |
- expected.settings.push_back(Http2SettingFields( |
- Http2SettingsParameter::INITIAL_WINDOW_SIZE, 168496141)); |
- expected.settings.push_back( |
- Http2SettingFields(Http2SettingsParameter::ENABLE_PUSH, 3)); |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, PushPromisePayload) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 7, // Payload length: 7 |
- 0x05, // PUSH_PROMISE |
- 0x04, // Flags: END_HEADERS |
- 0x00, 0x00, 0x00, 0xffu, // Stream ID: 255 |
- 0x00, 0x00, 0x01, 0x00, // Promised: 256 |
- 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid) |
- }; |
- Http2FrameHeader header(7, Http2FrameType::PUSH_PROMISE, |
- Http2FrameFlag::FLAG_END_HEADERS, 255); |
- FrameParts expected(header, "abc"); |
- expected.opt_push_promise = Http2PushPromiseFields{256}; |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, GoAwayOpaqueData) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x0e, // Length: 14 |
- 0x07, // Type: GOAWAY |
- 0xffu, // Flags: 0xff (no valid flags) |
- 0x80u, 0x00, 0x00, 0x00, // Stream: 0 (plus R bit) |
- 0x00, 0x00, 0x01, 0x00, // Last: 256 |
- 0x00, 0x00, 0x00, 0x03, // Error: FLOW_CONTROL_ERROR |
- 'o', 'p', 'a', 'q', 'u', 'e', |
- }; |
- Http2FrameHeader header(14, Http2FrameType::GOAWAY, 0, 0); |
- FrameParts expected(header, "opaque"); |
- expected.opt_goaway = |
- Http2GoAwayFields(256, Http2ErrorCode::FLOW_CONTROL_ERROR); |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, ContinuationPayload) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x03, // Payload length: 3 |
- 0x09, // CONTINUATION |
- 0xffu, // Flags: END_HEADERS | 0xfb |
- 0x00, 0x00, 0x00, 0x02, // Stream ID: 2 |
- 'a', 'b', 'c', // Data |
- }; |
- Http2FrameHeader header(3, Http2FrameType::CONTINUATION, |
- Http2FrameFlag::FLAG_END_HEADERS, 2); |
- FrameParts expected(header, "abc"); |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, AltSvcPayload) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x08, // Payload length: 3 |
- 0x0a, // ALTSVC |
- 0x00, // Flags: none |
- 0x00, 0x00, 0x00, 0x02, // Stream ID: 2 |
- 0x00, 0x03, // Origin Length: 0 |
- 'a', 'b', 'c', // Origin |
- 'd', 'e', 'f', // Value |
- }; |
- Http2FrameHeader header(8, Http2FrameType::ALTSVC, 0, 2); |
- FrameParts expected(header); |
- expected.SetAltSvcExpected("abc", "def"); |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, UnknownPayload) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x03, // Payload length: 3 |
- 0x30, // 48 (unknown) |
- 0x00, // Flags: none |
- 0x00, 0x00, 0x00, 0x02, // Stream ID: 2 |
- 'a', 'b', 'c', // Payload |
- }; |
- Http2FrameHeader header(3, static_cast<Http2FrameType>(48), 0, 2); |
- FrameParts expected(header, "abc"); |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); |
-} |
- |
-//////////////////////////////////////////////////////////////////////////////// |
-// Tests of padded payloads, for those frame types that allow padding. |
- |
-TEST_F(Http2FrameDecoderTest, DataPayloadAndPadding) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x07, // Payload length: 7 |
- 0x00, // DATA |
- 0x09, // Flags: END_STREAM | PADDED |
- 0x00, 0x00, 0x00, 0x02, // Stream ID: 0 (REQUIRES ID) |
- 0x03, // Pad Len |
- 'a', 'b', 'c', // Data |
- 0x00, 0x00, 0x00, // Padding |
- }; |
- Http2FrameHeader header( |
- 7, Http2FrameType::DATA, |
- Http2FrameFlag::FLAG_END_STREAM | Http2FrameFlag::FLAG_PADDED, 2); |
- size_t total_pad_length = 4; // Including the Pad Length field. |
- FrameParts expected(header, "abc", total_pad_length); |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, HeadersPayloadAndPadding) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x07, // Payload length: 7 |
- 0x01, // HEADERS |
- 0x08, // Flags: PADDED |
- 0x00, 0x00, 0x00, 0x02, // Stream ID: 0 (REQUIRES ID) |
- 0x03, // Pad Len |
- 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid) |
- 0x00, 0x00, 0x00, // Padding |
- }; |
- Http2FrameHeader header(7, Http2FrameType::HEADERS, |
- Http2FrameFlag::FLAG_PADDED, 2); |
- size_t total_pad_length = 4; // Including the Pad Length field. |
- FrameParts expected(header, "abc", total_pad_length); |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, HeadersPayloadPriorityAndPadding) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x0c, // Payload length: 12 |
- 0x01, // HEADERS |
- 0xffu, // Flags: all, including undefined |
- 0x00, 0x00, 0x00, 0x02, // Stream ID: 0 (REQUIRES ID) |
- 0x03, // Pad Len |
- 0x80u, 0x00, 0x00, 0x01, // Parent: 1 (Exclusive) |
- 0x10, // Weight: 17 |
- 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid) |
- 0x00, 0x00, 0x00, // Padding |
- }; |
- Http2FrameHeader header( |
- 12, Http2FrameType::HEADERS, |
- Http2FrameFlag::FLAG_END_STREAM | Http2FrameFlag::FLAG_END_HEADERS | |
- Http2FrameFlag::FLAG_PADDED | Http2FrameFlag::FLAG_PRIORITY, |
- 2); |
- size_t total_pad_length = 4; // Including the Pad Length field. |
- FrameParts expected(header, "abc", total_pad_length); |
- expected.opt_priority = Http2PriorityFields(1, 17, true); |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, PushPromisePayloadAndPadding) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 11, // Payload length: 11 |
- 0x05, // PUSH_PROMISE |
- 0xffu, // Flags: END_HEADERS | PADDED | 0xf3 |
- 0x00, 0x00, 0x00, 0x01, // Stream ID: 1 |
- 0x03, // Pad Len |
- 0x00, 0x00, 0x00, 0x02, // Promised: 2 |
- 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid) |
- 0x00, 0x00, 0x00, // Padding |
- }; |
- Http2FrameHeader header( |
- 11, Http2FrameType::PUSH_PROMISE, |
- Http2FrameFlag::FLAG_END_HEADERS | Http2FrameFlag::FLAG_PADDED, 1); |
- size_t total_pad_length = 4; // Including the Pad Length field. |
- FrameParts expected(header, "abc", total_pad_length); |
- expected.opt_push_promise = Http2PushPromiseFields{2}; |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); |
-} |
- |
-//////////////////////////////////////////////////////////////////////////////// |
-// Payload too short errors. |
- |
-TEST_F(Http2FrameDecoderTest, DataMissingPadLengthField) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x00, // Payload length: 0 |
- 0x00, // DATA |
- 0x08, // Flags: PADDED |
- 0x00, 0x00, 0x00, 0x01, // Stream ID: 1 |
- }; |
- Http2FrameHeader header(0, Http2FrameType::DATA, Http2FrameFlag::FLAG_PADDED, |
- 1); |
- FrameParts expected(header); |
- expected.opt_missing_length = 1; |
- EXPECT_TRUE(DecodePayloadExpectingError(kFrameData, expected)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, HeaderPaddingTooLong) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x02, // Payload length: 0 |
- 0x01, // HEADERS |
- 0x08, // Flags: PADDED |
- 0x00, 0x01, 0x00, 0x00, // Stream ID: 65536 |
- 0xffu, // Pad Len: 255 |
- 0x00, // Only one byte of padding |
- }; |
- Http2FrameHeader header(2, Http2FrameType::HEADERS, |
- Http2FrameFlag::FLAG_PADDED, 65536); |
- FrameParts expected(header); |
- expected.opt_missing_length = 254; |
- EXPECT_TRUE(DecodePayloadExpectingError(kFrameData, expected)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, HeaderMissingPriority) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x04, // Payload length: 0 |
- 0x01, // HEADERS |
- 0x20, // Flags: PRIORITY |
- 0x00, 0x01, 0x00, 0x00, // Stream ID: 65536 |
- 0x00, 0x00, 0x00, 0x00, // Priority (truncated) |
- }; |
- Http2FrameHeader header(4, Http2FrameType::HEADERS, |
- Http2FrameFlag::FLAG_PRIORITY, 65536); |
- EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, PriorityTooShort) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x04, // Length: 5 |
- 0x02, // Type: PRIORITY |
- 0x00, // Flags: none |
- 0x00, 0x00, 0x00, 0x02, // Stream: 2 |
- 0x80u, 0x00, 0x00, 0x01, // Parent: 1 (Exclusive) |
- }; |
- Http2FrameHeader header(4, Http2FrameType::PRIORITY, 0, 2); |
- EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, RstStreamTooShort) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x03, // Length: 4 |
- 0x03, // Type: RST_STREAM |
- 0x00, // Flags: none |
- 0x00, 0x00, 0x00, 0x01, // Stream: 1 |
- 0x00, 0x00, 0x00, // Truncated |
- }; |
- Http2FrameHeader header(3, Http2FrameType::RST_STREAM, 0, 1); |
- EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); |
-} |
- |
-// SETTINGS frames must a multiple of 6 bytes long, so an 9 byte payload is |
-// invalid. |
-TEST_F(Http2FrameDecoderTest, SettingsWrongSize) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x09, // Length: 2 |
- 0x04, // Type: SETTINGS |
- 0x00, // Flags: none |
- 0x00, 0x00, 0x00, 0x00, // Stream: 0 |
- 0x00, 0x02, // Param: ENABLE_PUSH |
- 0x00, 0x00, 0x00, 0x03, // Value: 1 |
- 0x00, 0x04, // Param: INITIAL_WINDOW_SIZE |
- 0x00, // Value: Truncated |
- }; |
- Http2FrameHeader header(9, Http2FrameType::SETTINGS, 0, 0); |
- FrameParts expected(header); |
- expected.settings.push_back( |
- Http2SettingFields(Http2SettingsParameter::ENABLE_PUSH, 3)); |
- EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, expected)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, PushPromiseTooShort) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 3, // Payload length: 3 |
- 0x05, // PUSH_PROMISE |
- 0x00, // Flags: none |
- 0x00, 0x00, 0x00, 0x01, // Stream ID: 1 |
- 0x00, 0x00, 0x00, // Truncated promise id |
- }; |
- Http2FrameHeader header(3, Http2FrameType::PUSH_PROMISE, 0, 1); |
- EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, PushPromisePaddedTruncatedPromise) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 4, // Payload length: 4 |
- 0x05, // PUSH_PROMISE |
- 0x08, // Flags: PADDED |
- 0x00, 0x00, 0x00, 0x01, // Stream ID: 1 |
- 0x00, // Pad Len |
- 0x00, 0x00, 0x00, // Truncated promise id |
- }; |
- Http2FrameHeader header(4, Http2FrameType::PUSH_PROMISE, |
- Http2FrameFlag::FLAG_PADDED, 1); |
- EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, PingTooShort) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x07, // Length: 8 |
- 0x06, // Type: PING |
- 0xfeu, // Flags: no valid flags |
- 0x00, 0x00, 0x00, 0x00, // Stream: 0 |
- 's', 'o', 'm', 'e', // "some" |
- 'd', 'a', 't', // Too little |
- }; |
- Http2FrameHeader header(7, Http2FrameType::PING, 0, 0); |
- EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, GoAwayTooShort) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x00, // Length: 0 |
- 0x07, // Type: GOAWAY |
- 0xffu, // Flags: 0xff (no valid flags) |
- 0x00, 0x00, 0x00, 0x00, // Stream: 0 |
- }; |
- Http2FrameHeader header(0, Http2FrameType::GOAWAY, 0, 0); |
- EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, WindowUpdateTooShort) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x03, // Length: 3 |
- 0x08, // Type: WINDOW_UPDATE |
- 0x0f, // Flags: 0xff (no valid flags) |
- 0x00, 0x00, 0x00, 0x01, // Stream: 1 |
- 0x80u, 0x00, 0x04, // Truncated |
- }; |
- Http2FrameHeader header(3, Http2FrameType::WINDOW_UPDATE, 0, 1); |
- EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, AltSvcTruncatedOriginLength) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x01, // Payload length: 3 |
- 0x0a, // ALTSVC |
- 0x00, // Flags: none |
- 0x00, 0x00, 0x00, 0x02, // Stream ID: 2 |
- 0x00, // Origin Length: truncated |
- }; |
- Http2FrameHeader header(1, Http2FrameType::ALTSVC, 0, 2); |
- EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, AltSvcTruncatedOrigin) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x05, // Payload length: 3 |
- 0x0a, // ALTSVC |
- 0x00, // Flags: none |
- 0x00, 0x00, 0x00, 0x02, // Stream ID: 2 |
- 0x00, 0x04, // Origin Length: 4 (too long) |
- 'a', 'b', 'c', // Origin |
- }; |
- Http2FrameHeader header(5, Http2FrameType::ALTSVC, 0, 2); |
- EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); |
-} |
- |
-//////////////////////////////////////////////////////////////////////////////// |
-// Payload too long errors. |
- |
-// The decoder calls the listener's OnFrameSizeError method if the frame's |
-// payload is longer than the currently configured maximum payload size. |
-TEST_F(Http2FrameDecoderTest, BeyondMaximum) { |
- decoder_.set_maximum_payload_size(2); |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x07, // Payload length: 7 |
- 0x00, // DATA |
- 0x09, // Flags: END_STREAM | PADDED |
- 0x00, 0x00, 0x00, 0x02, // Stream ID: 0 (REQUIRES ID) |
- 0x03, // Pad Len |
- 'a', 'b', 'c', // Data |
- 0x00, 0x00, 0x00, // Padding |
- }; |
- Http2FrameHeader header( |
- 7, Http2FrameType::DATA, |
- Http2FrameFlag::FLAG_END_STREAM | Http2FrameFlag::FLAG_PADDED, 2); |
- FrameParts expected(header); |
- expected.has_frame_size_error = true; |
- ResetDecodeSpeedCounters(); |
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays( |
- ToStringPiece(kFrameData), |
- base::Bind(&Http2FrameDecoderTest::ValidatorForBeyondMaximum, |
- base::Unretained(this), expected))); |
- EXPECT_GT(fast_decode_count_, 0u); |
- EXPECT_GT(slow_decode_count_, 0u); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, PriorityTooLong) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x06, // Length: 5 |
- 0x02, // Type: PRIORITY |
- 0x00, // Flags: none |
- 0x00, 0x00, 0x00, 0x02, // Stream: 2 |
- 0x80u, 0x00, 0x00, 0x01, // Parent: 1 (Exclusive) |
- 0x10, // Weight: 17 |
- 0x00, // Too much |
- }; |
- Http2FrameHeader header(6, Http2FrameType::PRIORITY, 0, 2); |
- EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, RstStreamTooLong) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x05, // Length: 4 |
- 0x03, // Type: RST_STREAM |
- 0x00, // Flags: none |
- 0x00, 0x00, 0x00, 0x01, // Stream: 1 |
- 0x00, 0x00, 0x00, 0x01, // Error: PROTOCOL_ERROR |
- 0x00, // Too much |
- }; |
- Http2FrameHeader header(5, Http2FrameType::RST_STREAM, 0, 1); |
- EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, SettingsAckTooLong) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x06, // Length: 6 |
- 0x04, // Type: SETTINGS |
- 0x01, // Flags: ACK |
- 0x00, 0x00, 0x00, 0x00, // Stream: 0 |
- 0x00, 0x00, // Extra |
- 0x00, 0x00, 0x00, 0x00, // Extra |
- }; |
- Http2FrameHeader header(6, Http2FrameType::SETTINGS, Http2FrameFlag::FLAG_ACK, |
- 0); |
- EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, PingAckTooLong) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x09, // Length: 8 |
- 0x06, // Type: PING |
- 0xffu, // Flags: ACK | 0xfe |
- 0x00, 0x00, 0x00, 0x00, // Stream: 0 |
- 's', 'o', 'm', 'e', // "some" |
- 'd', 'a', 't', 'a', // "data" |
- 0x00, // Too much |
- }; |
- Http2FrameHeader header(9, Http2FrameType::PING, Http2FrameFlag::FLAG_ACK, 0); |
- EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); |
-} |
- |
-TEST_F(Http2FrameDecoderTest, WindowUpdateTooLong) { |
- const char kFrameData[] = { |
- 0x00, 0x00, 0x05, // Length: 5 |
- 0x08, // Type: WINDOW_UPDATE |
- 0x0f, // Flags: 0xff (no valid flags) |
- 0x00, 0x00, 0x00, 0x01, // Stream: 1 |
- 0x80u, 0x00, 0x04, 0x00, // Incr: 1024 (plus R bit) |
- 0x00, // Too much |
- }; |
- Http2FrameHeader header(5, Http2FrameType::WINDOW_UPDATE, 0, 1); |
- EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); |
-} |
- |
-} // namespace |
-} // namespace test |
-} // namespace net |