Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(161)

Side by Side Diff: net/spdy/spdy_deframer_visitor.h

Issue 2832973003: Split net/spdy into core and chromium subdirectories. (Closed)
Patch Set: Fix some more build rules. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/spdy/spdy_bug_tracker.h ('k') | net/spdy/spdy_deframer_visitor.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 #ifndef NET_SPDY_SPDY_DEFRAMER_VISITOR_H_
6 #define NET_SPDY_SPDY_DEFRAMER_VISITOR_H_
7
8 // Supports testing by converting callbacks to SpdyFramerVisitorInterface into
9 // callbacks to SpdyDeframerVisitorInterface, whose arguments are generally
10 // SpdyFrameIR instances. This enables a test client or test backend to operate
11 // at a level between the low-level callbacks of SpdyFramerVisitorInterface and
12 // the much higher level of entire messages (i.e. headers, body, trailers).
13 // Where possible the converter (SpdyTestDeframer) tries to preserve information
14 // that might be useful to tests (e.g. the order of headers or the amount of
15 // padding); the design also aims to allow tests to be concise, ideally
16 // supporting gMock style EXPECT_CALL(visitor, OnHeaders(...matchers...))
17 // without too much boilerplate.
18 //
19 // Only supports HTTP/2 for the moment.
20 //
21 // Example of usage:
22 //
23 // SpdyFramer framer(HTTP2);
24 //
25 // // Need to call SpdyTestDeframer::AtFrameEnd() after processing each
26 // // frame, so tell SpdyFramer to stop after each.
27 // framer.set_process_single_input_frame(true);
28 //
29 // // Need the new OnHeader callbacks.
30 // framer.set_use_new_methods_for_test(true);
31 //
32 // // Create your visitor, a subclass of SpdyDeframerVisitorInterface.
33 // // For example, using DeframerCallbackCollector to collect frames:
34 // std::vector<CollectedFrame> collected_frames;
35 // auto your_visitor = gtl::MakeUnique<DeframerCallbackCollector>(
36 // &collected_frames);
37 //
38 // // Transfer ownership of your visitor to the converter, which ensures that
39 // // your visitor stays alive while the converter needs to call it.
40 // auto the_deframer = SpdyTestDeframer::CreateConverter(
41 // std::move(your_visitor));
42 //
43 // // Tell the framer to notify SpdyTestDeframer of the decoded frame
44 // // details.
45 // framer.set_visitor(the_deframer.get());
46 //
47 // // Process frames.
48 // SpdyStringPiece input = ...
49 // while (!input.empty() && !framer.HasError()) {
50 // size_t consumed = framer.ProcessInput(input.data(), input.size());
51 // input.remove_prefix(consumed);
52 // if (framer.state() == SpdyFramer::SPDY_READY_FOR_FRAME) {
53 // the_deframer->AtFrameEnd();
54 // }
55 // }
56 //
57 // // Make sure that the correct frames were received. For example:
58 // ASSERT_EQ(collected_frames.size(), 3);
59 //
60 // SpdyDataIR expected1(7 /*stream_id*/, "Data Payload");
61 // expected1.set_padding_len(17);
62 // EXPECT_TRUE(collected_frames[0].VerifyEquals(expected1));
63 //
64 // // Repeat for the other frames.
65 //
66 // Note that you could also seed the subclass of SpdyDeframerVisitorInterface
67 // with the expected frames, which it would pop-off the list as its expectations
68 // are met.
69
70 #include <stdint.h>
71
72 #include <memory>
73 #include <type_traits>
74 #include <utility>
75 #include <vector>
76
77 #include "base/logging.h"
78 #include "base/macros.h"
79 #include "net/spdy/platform/api/spdy_string.h"
80 #include "net/spdy/spdy_framer.h"
81 #include "net/spdy/spdy_protocol.h"
82 #include "net/spdy/spdy_protocol_test_utils.h"
83 #include "net/spdy/spdy_test_utils.h"
84
85 namespace net {
86 namespace test {
87
88 // Non-lossy representation of a SETTINGS frame payload.
89 typedef std::vector<std::pair<SpdySettingsIds, uint32_t>> SettingVector;
90
91 // StringPairVector is used to record information lost by SpdyHeaderBlock, in
92 // particular the order of each header entry, though it doesn't expose the
93 // inner details of the HPACK block, such as the type of encoding selected
94 // for each header entry, nor dynamic table size changes.
95 typedef std::pair<SpdyString, SpdyString> StringPair;
96 typedef std::vector<StringPair> StringPairVector;
97
98 // Forward decl.
99 class SpdyTestDeframer;
100
101 // Note that this only roughly captures the frames, as padding bytes are lost,
102 // continuation frames are combined with their leading HEADERS or PUSH_PROMISE,
103 // the details of the HPACK encoding are lost, leaving
104 // only the list of header entries (name and value strings). If really helpful,
105 // we could add a SpdyRawDeframerVisitorInterface that gets the HPACK bytes,
106 // and receives continuation frames. For more info we'd need to improve
107 // SpdyFramerVisitorInterface.
108 class SpdyDeframerVisitorInterface {
109 public:
110 virtual ~SpdyDeframerVisitorInterface() {}
111
112 // Wrap a visitor in another SpdyDeframerVisitorInterface that will
113 // DVLOG each call, and will then forward the calls to the wrapped visitor
114 // (if provided; nullptr is OK). Takes ownership of the wrapped visitor.
115 static std::unique_ptr<SpdyDeframerVisitorInterface> LogBeforeVisiting(
116 std::unique_ptr<SpdyDeframerVisitorInterface> wrapped_visitor);
117
118 virtual void OnAltSvc(std::unique_ptr<SpdyAltSvcIR> frame) {}
119 virtual void OnData(std::unique_ptr<SpdyDataIR> frame) {}
120 virtual void OnGoAway(std::unique_ptr<SpdyGoAwayIR> frame) {}
121
122 // SpdyHeadersIR and SpdyPushPromiseIR each has a SpdyHeaderBlock which
123 // significantly modifies the headers, so the actual header entries (name
124 // and value strings) are provided in a vector.
125 virtual void OnHeaders(std::unique_ptr<SpdyHeadersIR> frame,
126 std::unique_ptr<StringPairVector> headers) {}
127
128 virtual void OnPing(std::unique_ptr<SpdyPingIR> frame) {}
129 virtual void OnPingAck(std::unique_ptr<SpdyPingIR> frame);
130 virtual void OnPriority(std::unique_ptr<SpdyPriorityIR> frame) {}
131
132 // SpdyHeadersIR and SpdyPushPromiseIR each has a SpdyHeaderBlock which
133 // significantly modifies the headers, so the actual header entries (name
134 // and value strings) are provided in a vector.
135 virtual void OnPushPromise(std::unique_ptr<SpdyPushPromiseIR> frame,
136 std::unique_ptr<StringPairVector> headers) {}
137
138 virtual void OnRstStream(std::unique_ptr<SpdyRstStreamIR> frame) {}
139
140 // SpdySettingsIR has a map for settings, so loses info about the order of
141 // settings, and whether the same setting appeared more than once, so the
142 // the actual settings (parameter and value) are provided in a vector.
143 virtual void OnSettings(std::unique_ptr<SpdySettingsIR> frame,
144 std::unique_ptr<SettingVector> settings) {}
145
146 // A settings frame with an ACK has no content, but for uniformity passing
147 // a frame with the ACK flag set.
148 virtual void OnSettingsAck(std::unique_ptr<SpdySettingsIR> frame);
149
150 virtual void OnWindowUpdate(std::unique_ptr<SpdyWindowUpdateIR> frame) {}
151
152 // The SpdyFramer will not process any more data at this point.
153 virtual void OnError(SpdyFramer* framer, SpdyTestDeframer* deframer) {}
154 };
155
156 class SpdyTestDeframer : public SpdyFramerVisitorInterface {
157 public:
158 ~SpdyTestDeframer() override {}
159
160 // Creates a SpdyFramerVisitorInterface that builds SpdyFrameIR concrete
161 // instances based on the callbacks it receives; when an entire frame is
162 // decoded/reconstructed it calls the passed in SpdyDeframerVisitorInterface.
163 // Transfers ownership of visitor to the new SpdyTestDeframer, which ensures
164 // that it continues to exist while the SpdyTestDeframer exists.
165 static std::unique_ptr<SpdyTestDeframer> CreateConverter(
166 std::unique_ptr<SpdyDeframerVisitorInterface> visitor);
167
168 // Call to notify the deframer that the SpdyFramer has returned after reaching
169 // the end of decoding a frame. This is used to flush info about some frame
170 // types where we don't get a clear end signal; others are flushed (i.e. the
171 // appropriate call to the SpdyDeframerVisitorInterface method is invoked)
172 // as they're decoded by SpdyFramer and it calls the deframer. See the
173 // example in the comments at the top of this file.
174 virtual bool AtFrameEnd() = 0;
175
176 protected:
177 SpdyTestDeframer() {}
178
179 private:
180 DISALLOW_COPY_AND_ASSIGN(SpdyTestDeframer);
181 };
182
183 // CollectedFrame holds the result of one call to SpdyDeframerVisitorInterface,
184 // as recorded by DeframerCallbackCollector.
185 struct CollectedFrame {
186 CollectedFrame();
187 CollectedFrame(CollectedFrame&& other);
188 ~CollectedFrame();
189 CollectedFrame& operator=(CollectedFrame&& other);
190
191 // Compare a SpdyFrameIR sub-class instance, expected_ir, against the
192 // collected SpdyFrameIR.
193 template <class T,
194 typename X =
195 typename std::enable_if<std::is_base_of<SpdyFrameIR, T>::value>>
196 ::testing::AssertionResult VerifyHasFrame(const T& expected_ir) const {
197 return VerifySpdyFrameIREquals(expected_ir, frame_ir.get())
198 ? ::testing::AssertionSuccess()
199 : ::testing::AssertionFailure();
200 }
201
202 // Compare the collected headers against a StringPairVector. Ignores
203 // this->frame_ir.
204 ::testing::AssertionResult VerifyHasHeaders(
205 const StringPairVector& expected_headers) const;
206
207 // Compare the collected settings (parameter and value pairs) against
208 // expected_settings. Ignores this->frame_ir.
209 ::testing::AssertionResult VerifyHasSettings(
210 const SettingVector& expected_settings) const;
211
212 std::unique_ptr<SpdyFrameIR> frame_ir;
213 std::unique_ptr<StringPairVector> headers;
214 std::unique_ptr<SettingVector> settings;
215 bool error_reported = false;
216 };
217
218 // Creates a CollectedFrame instance for each callback, storing it in the
219 // vector provided to the constructor.
220 class DeframerCallbackCollector : public SpdyDeframerVisitorInterface {
221 public:
222 explicit DeframerCallbackCollector(
223 std::vector<CollectedFrame>* collected_frames);
224 ~DeframerCallbackCollector() override {}
225
226 void OnAltSvc(std::unique_ptr<SpdyAltSvcIR> frame_ir) override;
227 void OnData(std::unique_ptr<SpdyDataIR> frame_ir) override;
228 void OnGoAway(std::unique_ptr<SpdyGoAwayIR> frame_ir) override;
229 void OnHeaders(std::unique_ptr<SpdyHeadersIR> frame_ir,
230 std::unique_ptr<StringPairVector> headers) override;
231 void OnPing(std::unique_ptr<SpdyPingIR> frame_ir) override;
232 void OnPingAck(std::unique_ptr<SpdyPingIR> frame_ir) override;
233 void OnPriority(std::unique_ptr<SpdyPriorityIR> frame_ir) override;
234 void OnPushPromise(std::unique_ptr<SpdyPushPromiseIR> frame_ir,
235 std::unique_ptr<StringPairVector> headers) override;
236 void OnRstStream(std::unique_ptr<SpdyRstStreamIR> frame_ir) override;
237 void OnSettings(std::unique_ptr<SpdySettingsIR> frame_ir,
238 std::unique_ptr<SettingVector> settings) override;
239 void OnSettingsAck(std::unique_ptr<SpdySettingsIR> frame_ir) override;
240 void OnWindowUpdate(std::unique_ptr<SpdyWindowUpdateIR> frame_ir) override;
241 void OnError(SpdyFramer* framer, SpdyTestDeframer* deframer) override;
242
243 private:
244 std::vector<CollectedFrame>* collected_frames_;
245 };
246
247 } // namespace test
248 } // namespace net
249
250 #endif // NET_SPDY_SPDY_DEFRAMER_VISITOR_H_
OLDNEW
« no previous file with comments | « net/spdy/spdy_bug_tracker.h ('k') | net/spdy/spdy_deframer_visitor.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698