OLD | NEW |
| (Empty) |
1 // Copyright 2016 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 "net/http2/decoder/payload_decoders/settings_payload_decoder.h" | |
6 | |
7 #include <stddef.h> | |
8 | |
9 #include <vector> | |
10 | |
11 #include "base/bind.h" | |
12 #include "base/logging.h" | |
13 #include "net/http2/decoder/frame_parts.h" | |
14 #include "net/http2/decoder/frame_parts_collector.h" | |
15 #include "net/http2/decoder/http2_frame_decoder_listener.h" | |
16 #include "net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h" | |
17 #include "net/http2/http2_constants.h" | |
18 #include "net/http2/http2_constants_test_util.h" | |
19 #include "net/http2/http2_structures_test_util.h" | |
20 #include "net/http2/tools/http2_frame_builder.h" | |
21 #include "net/http2/tools/http2_random.h" | |
22 #include "net/http2/tools/random_decoder_test.h" | |
23 #include "testing/gtest/include/gtest/gtest.h" | |
24 | |
25 namespace net { | |
26 namespace test { | |
27 | |
28 class SettingsPayloadDecoderPeer { | |
29 public: | |
30 static constexpr Http2FrameType FrameType() { | |
31 return Http2FrameType::SETTINGS; | |
32 } | |
33 | |
34 // Returns the mask of flags that affect the decoding of the payload (i.e. | |
35 // flags that that indicate the presence of certain fields or padding). | |
36 static constexpr uint8_t FlagsAffectingPayloadDecoding() { | |
37 return Http2FrameFlag::FLAG_ACK; | |
38 } | |
39 | |
40 static void Randomize(SettingsPayloadDecoder* p, RandomBase* rng) { | |
41 VLOG(1) << "SettingsPayloadDecoderPeer::Randomize"; | |
42 test::Randomize(&p->setting_fields_, rng); | |
43 } | |
44 }; | |
45 | |
46 namespace { | |
47 | |
48 struct Listener : public FramePartsCollector { | |
49 void OnSettingsStart(const Http2FrameHeader& header) override { | |
50 VLOG(1) << "OnSettingsStart: " << header; | |
51 EXPECT_EQ(Http2FrameType::SETTINGS, header.type) << header; | |
52 EXPECT_EQ(Http2FrameFlag(), header.flags) << header; | |
53 StartFrame(header)->OnSettingsStart(header); | |
54 } | |
55 | |
56 void OnSetting(const Http2SettingFields& setting_fields) override { | |
57 VLOG(1) << "Http2SettingFields: setting_fields=" << setting_fields; | |
58 CurrentFrame()->OnSetting(setting_fields); | |
59 } | |
60 | |
61 void OnSettingsEnd() override { | |
62 VLOG(1) << "OnSettingsEnd"; | |
63 EndFrame()->OnSettingsEnd(); | |
64 } | |
65 | |
66 void OnSettingsAck(const Http2FrameHeader& header) override { | |
67 VLOG(1) << "OnSettingsAck: " << header; | |
68 StartAndEndFrame(header)->OnSettingsAck(header); | |
69 } | |
70 | |
71 void OnFrameSizeError(const Http2FrameHeader& header) override { | |
72 VLOG(1) << "OnFrameSizeError: " << header; | |
73 FrameError(header)->OnFrameSizeError(header); | |
74 } | |
75 }; | |
76 | |
77 class SettingsPayloadDecoderTest | |
78 : public AbstractPayloadDecoderTest<SettingsPayloadDecoder, | |
79 SettingsPayloadDecoderPeer, | |
80 Listener> { | |
81 public: | |
82 static bool ApproveSizeForSettingsWrongSize(size_t size) { | |
83 // Should get an error if size is not an integral multiple of the size | |
84 // of one setting. | |
85 return 0 != (size % Http2SettingFields::EncodedSize()); | |
86 } | |
87 | |
88 static bool ApproveSizeForSettingsAkcWrongSize(size_t size) { | |
89 return size != 0; | |
90 } | |
91 | |
92 protected: | |
93 Http2SettingFields RandSettingsFields() { | |
94 Http2SettingFields fields; | |
95 test::Randomize(&fields, RandomPtr()); | |
96 return fields; | |
97 } | |
98 }; | |
99 | |
100 // Confirm we get an error if the SETTINGS payload is not the correct size | |
101 // to hold exactly zero or more whole Http2SettingFields. | |
102 TEST_F(SettingsPayloadDecoderTest, SettingsWrongSize) { | |
103 Http2FrameBuilder fb; | |
104 fb.Append(RandSettingsFields()); | |
105 fb.Append(RandSettingsFields()); | |
106 fb.Append(RandSettingsFields()); | |
107 EXPECT_TRUE(VerifyDetectsFrameSizeError( | |
108 0, fb.buffer(), | |
109 base::Bind( | |
110 &SettingsPayloadDecoderTest::ApproveSizeForSettingsWrongSize))); | |
111 } | |
112 | |
113 // Confirm we get an error if the SETTINGS ACK payload is not empty. | |
114 TEST_F(SettingsPayloadDecoderTest, SettingsAkcWrongSize) { | |
115 Http2FrameBuilder fb; | |
116 fb.Append(RandSettingsFields()); | |
117 fb.Append(RandSettingsFields()); | |
118 fb.Append(RandSettingsFields()); | |
119 EXPECT_TRUE(VerifyDetectsFrameSizeError( | |
120 Http2FrameFlag::FLAG_ACK, fb.buffer(), | |
121 base::Bind( | |
122 &SettingsPayloadDecoderTest::ApproveSizeForSettingsAkcWrongSize))); | |
123 } | |
124 | |
125 // SETTINGS must have stream_id==0, but the payload decoder doesn't check that. | |
126 TEST_F(SettingsPayloadDecoderTest, SettingsAck) { | |
127 for (int stream_id = 0; stream_id < 3; ++stream_id) { | |
128 Http2FrameHeader header(0, Http2FrameType::SETTINGS, | |
129 RandFlags() | Http2FrameFlag::FLAG_ACK, stream_id); | |
130 set_frame_header(header); | |
131 FrameParts expected(header); | |
132 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays("", expected)); | |
133 } | |
134 } | |
135 | |
136 // Try several values of each known SETTINGS parameter. | |
137 TEST_F(SettingsPayloadDecoderTest, OneRealSetting) { | |
138 std::vector<uint32_t> values = {0, 1, 0xffffffff, Random().Rand32()}; | |
139 for (auto param : AllHttp2SettingsParameters()) { | |
140 for (uint32_t value : values) { | |
141 Http2SettingFields fields(param, value); | |
142 Http2FrameBuilder fb; | |
143 fb.Append(fields); | |
144 Http2FrameHeader header(fb.size(), Http2FrameType::SETTINGS, RandFlags(), | |
145 RandStreamId()); | |
146 set_frame_header(header); | |
147 FrameParts expected(header); | |
148 expected.settings.push_back(fields); | |
149 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected)); | |
150 } | |
151 } | |
152 } | |
153 | |
154 // Decode a SETTINGS frame with lots of fields. | |
155 TEST_F(SettingsPayloadDecoderTest, ManySettings) { | |
156 const uint32_t num_settings = 100; | |
157 const uint32_t size = Http2SettingFields::EncodedSize() * num_settings; | |
158 Http2FrameHeader header(size, Http2FrameType::SETTINGS, | |
159 RandFlags(), // & ~Http2FrameFlag::FLAG_ACK, | |
160 RandStreamId()); | |
161 set_frame_header(header); | |
162 FrameParts expected(header); | |
163 Http2FrameBuilder fb; | |
164 for (size_t n = 0; n < num_settings; ++n) { | |
165 Http2SettingFields fields(static_cast<Http2SettingsParameter>(n), | |
166 Random().Rand32()); | |
167 fb.Append(fields); | |
168 expected.settings.push_back(fields); | |
169 } | |
170 ASSERT_EQ(size, fb.size()); | |
171 EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected)); | |
172 } | |
173 | |
174 } // namespace | |
175 } // namespace test | |
176 } // namespace net | |
OLD | NEW |