1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "quiche/http2/decoder/payload_decoders/priority_update_payload_decoder.h"
6 
7 #include <stddef.h>
8 
9 #include <string>
10 
11 #include "quiche/http2/decoder/http2_frame_decoder_listener.h"
12 #include "quiche/http2/http2_constants.h"
13 #include "quiche/http2/test_tools/frame_parts.h"
14 #include "quiche/http2/test_tools/frame_parts_collector.h"
15 #include "quiche/http2/test_tools/http2_frame_builder.h"
16 #include "quiche/http2/test_tools/http2_random.h"
17 #include "quiche/http2/test_tools/http2_structures_test_util.h"
18 #include "quiche/http2/test_tools/payload_decoder_base_test_util.h"
19 #include "quiche/http2/test_tools/random_decoder_test_base.h"
20 #include "quiche/common/platform/api/quiche_logging.h"
21 #include "quiche/common/platform/api/quiche_test.h"
22 
23 namespace http2 {
24 namespace test {
25 
26 class PriorityUpdatePayloadDecoderPeer {
27  public:
FrameType()28   static constexpr Http2FrameType FrameType() {
29     return Http2FrameType::PRIORITY_UPDATE;
30   }
31 
32   // Returns the mask of flags that affect the decoding of the payload (i.e.
33   // flags that that indicate the presence of certain fields or padding).
FlagsAffectingPayloadDecoding()34   static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; }
35 };
36 
37 namespace {
38 
39 struct Listener : public FramePartsCollector {
OnPriorityUpdateStarthttp2::test::__anon9c52c85f0111::Listener40   void OnPriorityUpdateStart(
41       const Http2FrameHeader& header,
42       const Http2PriorityUpdateFields& priority_update) override {
43     QUICHE_VLOG(1) << "OnPriorityUpdateStart header: " << header
44                    << "; priority_update: " << priority_update;
45     StartFrame(header)->OnPriorityUpdateStart(header, priority_update);
46   }
47 
OnPriorityUpdatePayloadhttp2::test::__anon9c52c85f0111::Listener48   void OnPriorityUpdatePayload(const char* data, size_t len) override {
49     QUICHE_VLOG(1) << "OnPriorityUpdatePayload: len=" << len;
50     CurrentFrame()->OnPriorityUpdatePayload(data, len);
51   }
52 
OnPriorityUpdateEndhttp2::test::__anon9c52c85f0111::Listener53   void OnPriorityUpdateEnd() override {
54     QUICHE_VLOG(1) << "OnPriorityUpdateEnd";
55     EndFrame()->OnPriorityUpdateEnd();
56   }
57 
OnFrameSizeErrorhttp2::test::__anon9c52c85f0111::Listener58   void OnFrameSizeError(const Http2FrameHeader& header) override {
59     QUICHE_VLOG(1) << "OnFrameSizeError: " << header;
60     FrameError(header)->OnFrameSizeError(header);
61   }
62 };
63 
64 class PriorityUpdatePayloadDecoderTest
65     : public AbstractPayloadDecoderTest<PriorityUpdatePayloadDecoder,
66                                         PriorityUpdatePayloadDecoderPeer,
67                                         Listener> {};
68 
69 // Confirm we get an error if the payload is not long enough to hold
70 // Http2PriorityUpdateFields.
TEST_F(PriorityUpdatePayloadDecoderTest,Truncated)71 TEST_F(PriorityUpdatePayloadDecoderTest, Truncated) {
72   auto approve_size = [](size_t size) {
73     return size != Http2PriorityUpdateFields::EncodedSize();
74   };
75   Http2FrameBuilder fb;
76   fb.Append(Http2PriorityUpdateFields(123));
77   EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size));
78 }
79 
80 class PriorityUpdatePayloadLengthTests
81     : public AbstractPayloadDecoderTest<PriorityUpdatePayloadDecoder,
82                                         PriorityUpdatePayloadDecoderPeer,
83                                         Listener>,
84       public ::testing::WithParamInterface<uint32_t> {
85  protected:
PriorityUpdatePayloadLengthTests()86   PriorityUpdatePayloadLengthTests() : length_(GetParam()) {
87     QUICHE_VLOG(1) << "################  length_=" << length_
88                    << "  ################";
89   }
90 
91   const uint32_t length_;
92 };
93 
94 INSTANTIATE_TEST_SUITE_P(VariousLengths, PriorityUpdatePayloadLengthTests,
95                          ::testing::Values(0, 1, 2, 3, 4, 5, 6));
96 
TEST_P(PriorityUpdatePayloadLengthTests,ValidLength)97 TEST_P(PriorityUpdatePayloadLengthTests, ValidLength) {
98   Http2PriorityUpdateFields priority_update;
99   Randomize(&priority_update, RandomPtr());
100   std::string priority_field_value = Random().RandString(length_);
101   Http2FrameBuilder fb;
102   fb.Append(priority_update);
103   fb.Append(priority_field_value);
104   Http2FrameHeader header(fb.size(), Http2FrameType::PRIORITY_UPDATE,
105                           RandFlags(), RandStreamId());
106   set_frame_header(header);
107   FrameParts expected(header, priority_field_value);
108   expected.SetOptPriorityUpdate(Http2PriorityUpdateFields{priority_update});
109   ASSERT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected));
110 }
111 
112 }  // namespace
113 }  // namespace test
114 }  // namespace http2
115