OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/tools/quic/quic_spdy_server_stream.h" | 5 #include "net/tools/quic/quic_spdy_server_stream.h" |
6 | 6 |
7 #include "base/strings/string_number_conversions.h" | 7 #include "base/strings/string_number_conversions.h" |
8 #include "base/strings/string_piece.h" | 8 #include "base/strings/string_piece.h" |
9 #include "net/quic/quic_connection.h" | 9 #include "net/quic/quic_connection.h" |
10 #include "net/quic/quic_protocol.h" | 10 #include "net/quic/quic_protocol.h" |
(...skipping 28 matching lines...) Expand all Loading... |
39 | 39 |
40 class QuicSpdyServerStreamPeer : public QuicSpdyServerStream { | 40 class QuicSpdyServerStreamPeer : public QuicSpdyServerStream { |
41 public: | 41 public: |
42 QuicSpdyServerStreamPeer(QuicStreamId stream_id, QuicSession* session) | 42 QuicSpdyServerStreamPeer(QuicStreamId stream_id, QuicSession* session) |
43 : QuicSpdyServerStream(stream_id, session) { | 43 : QuicSpdyServerStream(stream_id, session) { |
44 } | 44 } |
45 | 45 |
46 using QuicSpdyServerStream::SendResponse; | 46 using QuicSpdyServerStream::SendResponse; |
47 using QuicSpdyServerStream::SendErrorResponse; | 47 using QuicSpdyServerStream::SendErrorResponse; |
48 | 48 |
49 BalsaHeaders* mutable_headers() { | 49 SpdyHeaderBlock* mutable_headers() { |
50 return &headers_; | 50 return &request_headers_; |
51 } | 51 } |
52 | 52 |
53 static void SendResponse(QuicSpdyServerStream* stream) { | 53 static void SendResponse(QuicSpdyServerStream* stream) { |
54 stream->SendResponse(); | 54 stream->SendResponse(); |
55 } | 55 } |
56 | 56 |
57 static void SendErrorResponse(QuicSpdyServerStream* stream) { | 57 static void SendErrorResponse(QuicSpdyServerStream* stream) { |
58 stream->SendResponse(); | 58 stream->SendResponse(); |
59 } | 59 } |
60 | 60 |
61 static const string& body(QuicSpdyServerStream* stream) { | 61 static const string& body(QuicSpdyServerStream* stream) { |
62 return stream->body_; | 62 return stream->body_; |
63 } | 63 } |
64 | 64 |
65 static const BalsaHeaders& headers(QuicSpdyServerStream* stream) { | 65 static const SpdyHeaderBlock& headers(QuicSpdyServerStream* stream) { |
66 return stream->headers_; | 66 return stream->request_headers_; |
67 } | 67 } |
68 }; | 68 }; |
69 | 69 |
70 namespace { | 70 namespace { |
71 | 71 |
72 class QuicSpdyServerStreamTest : public ::testing::TestWithParam<QuicVersion> { | 72 class QuicSpdyServerStreamTest : public ::testing::TestWithParam<QuicVersion> { |
73 public: | 73 public: |
74 QuicSpdyServerStreamTest() | 74 QuicSpdyServerStreamTest() |
75 : connection_( | 75 : connection_( |
76 new StrictMock<MockConnection>(Perspective::IS_SERVER, | 76 new StrictMock<MockConnection>(Perspective::IS_SERVER, |
77 SupportedVersions(GetParam()))), | 77 SupportedVersions(GetParam()))), |
78 session_(connection_), | 78 session_(connection_), |
79 body_("hello world") { | 79 body_("hello world") { |
80 BalsaHeaders request_headers; | 80 SpdyHeaderBlock request_headers; |
81 request_headers.SetRequestFirstlineFromStringPieces( | 81 request_headers[":host"] = ""; |
82 "POST", "https://www.google.com/", "HTTP/1.1"); | 82 request_headers[":path"] = "/"; |
83 request_headers.ReplaceOrAppendHeader("content-length", "11"); | 83 request_headers[":method"] = "POST"; |
| 84 request_headers[":version"] = "HTTP/1.1"; |
| 85 request_headers["content-length"] = "11"; |
84 | 86 |
85 headers_string_ = SpdyUtils::SerializeRequestHeaders(request_headers); | 87 headers_string_ = SpdyUtils::SerializeUncompressedHeaders(request_headers); |
86 | 88 |
87 // New streams rely on having the peer's flow control receive window | 89 // New streams rely on having the peer's flow control receive window |
88 // negotiated in the config. | 90 // negotiated in the config. |
89 session_.config()->SetInitialStreamFlowControlWindowToSend( | 91 session_.config()->SetInitialStreamFlowControlWindowToSend( |
90 kInitialStreamFlowControlWindowForTest); | 92 kInitialStreamFlowControlWindowForTest); |
91 session_.config()->SetInitialSessionFlowControlWindowToSend( | 93 session_.config()->SetInitialSessionFlowControlWindowToSend( |
92 kInitialSessionFlowControlWindowForTest); | 94 kInitialSessionFlowControlWindowForTest); |
93 stream_.reset(new QuicSpdyServerStreamPeer(3, &session_)); | 95 stream_.reset(new QuicSpdyServerStreamPeer(3, &session_)); |
94 } | |
95 | 96 |
96 static void SetUpTestCase() { | |
97 QuicInMemoryCachePeer::ResetForTests(); | 97 QuicInMemoryCachePeer::ResetForTests(); |
98 } | |
99 | |
100 void SetUp() override { | |
101 QuicInMemoryCache* cache = QuicInMemoryCache::GetInstance(); | |
102 | |
103 BalsaHeaders response_headers; | |
104 StringPiece body("Yum"); | |
105 response_headers.SetRequestFirstlineFromStringPieces("HTTP/1.1", | |
106 "200", | |
107 "OK"); | |
108 response_headers.AppendHeader("content-length", | |
109 base::IntToString(body.length())); | |
110 | 98 |
111 string host = ""; | 99 string host = ""; |
112 string path = "/foo"; | 100 string path = "/foo"; |
113 // Check if response already exists and matches. | 101 SpdyHeaderBlock response_headers; |
114 const QuicInMemoryCache::Response* cached_response = | 102 StringPiece body("Yum"); |
115 cache->GetResponse(host, path); | 103 QuicInMemoryCache::GetInstance()->AddResponse(host, path, response_headers, |
116 if (cached_response != nullptr) { | 104 body); |
117 string cached_response_headers_str, response_headers_str; | 105 } |
118 cached_response->headers().DumpToString(&cached_response_headers_str); | |
119 response_headers.DumpToString(&response_headers_str); | |
120 CHECK_EQ(cached_response_headers_str, response_headers_str); | |
121 CHECK_EQ(cached_response->body(), body); | |
122 return; | |
123 } | |
124 | 106 |
125 cache->AddResponse(host, path, response_headers, body); | 107 ~QuicSpdyServerStreamTest() override { |
| 108 QuicInMemoryCachePeer::ResetForTests(); |
126 } | 109 } |
127 | 110 |
128 const string& StreamBody() { | 111 const string& StreamBody() { |
129 return QuicSpdyServerStreamPeer::body(stream_.get()); | 112 return QuicSpdyServerStreamPeer::body(stream_.get()); |
130 } | 113 } |
131 | 114 |
132 const BalsaHeaders& StreamHeaders() { | 115 const string& StreamHeadersValue(const string& key) { |
133 return QuicSpdyServerStreamPeer::headers(stream_.get()); | 116 return (*stream_->mutable_headers())[key]; |
134 } | 117 } |
135 | 118 |
136 BalsaHeaders response_headers_; | 119 SpdyHeaderBlock response_headers_; |
137 EpollServer eps_; | 120 EpollServer eps_; |
138 StrictMock<MockConnection>* connection_; | 121 StrictMock<MockConnection>* connection_; |
139 StrictMock<MockSession> session_; | 122 StrictMock<MockSession> session_; |
140 scoped_ptr<QuicSpdyServerStreamPeer> stream_; | 123 scoped_ptr<QuicSpdyServerStreamPeer> stream_; |
141 string headers_string_; | 124 string headers_string_; |
142 string body_; | 125 string body_; |
143 }; | 126 }; |
144 | 127 |
145 QuicConsumedData ConsumeAllData( | 128 QuicConsumedData ConsumeAllData( |
146 QuicStreamId id, | 129 QuicStreamId id, |
147 const IOVector& data, | 130 const IOVector& data, |
148 QuicStreamOffset offset, | 131 QuicStreamOffset offset, |
149 bool fin, | 132 bool fin, |
150 FecProtection /*fec_protection_*/, | 133 FecProtection /*fec_protection_*/, |
151 QuicAckNotifier::DelegateInterface* /*ack_notifier_delegate*/) { | 134 QuicAckNotifier::DelegateInterface* /*ack_notifier_delegate*/) { |
152 return QuicConsumedData(data.TotalBufferSize(), fin); | 135 return QuicConsumedData(data.TotalBufferSize(), fin); |
153 } | 136 } |
154 | 137 |
155 INSTANTIATE_TEST_CASE_P(Tests, QuicSpdyServerStreamTest, | 138 INSTANTIATE_TEST_CASE_P(Tests, QuicSpdyServerStreamTest, |
156 ::testing::ValuesIn(QuicSupportedVersions())); | 139 ::testing::ValuesIn(QuicSupportedVersions())); |
157 | 140 |
158 TEST_P(QuicSpdyServerStreamTest, TestFraming) { | 141 TEST_P(QuicSpdyServerStreamTest, TestFraming) { |
159 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(AnyNumber()). | 142 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(AnyNumber()). |
160 WillRepeatedly(Invoke(ConsumeAllData)); | 143 WillRepeatedly(Invoke(ConsumeAllData)); |
161 | 144 stream_->OnStreamHeaders(headers_string_); |
162 EXPECT_EQ(headers_string_.size(), stream_->ProcessData( | 145 stream_->OnStreamHeadersComplete(false, headers_string_.size()); |
163 headers_string_.c_str(), headers_string_.size())); | |
164 EXPECT_EQ(body_.size(), stream_->ProcessData(body_.c_str(), body_.size())); | 146 EXPECT_EQ(body_.size(), stream_->ProcessData(body_.c_str(), body_.size())); |
165 EXPECT_EQ(11u, StreamHeaders().content_length()); | 147 EXPECT_EQ("11", StreamHeadersValue("content-length")); |
166 EXPECT_EQ("https://www.google.com/", StreamHeaders().request_uri()); | 148 EXPECT_EQ("/", StreamHeadersValue(":path")); |
167 EXPECT_EQ("POST", StreamHeaders().request_method()); | 149 EXPECT_EQ("POST", StreamHeadersValue(":method")); |
168 EXPECT_EQ(body_, StreamBody()); | 150 EXPECT_EQ(body_, StreamBody()); |
169 } | 151 } |
170 | 152 |
171 TEST_P(QuicSpdyServerStreamTest, TestFramingOnePacket) { | 153 TEST_P(QuicSpdyServerStreamTest, TestFramingOnePacket) { |
172 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(AnyNumber()). | 154 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(AnyNumber()). |
173 WillRepeatedly(Invoke(ConsumeAllData)); | 155 WillRepeatedly(Invoke(ConsumeAllData)); |
174 | 156 |
175 string message = headers_string_ + body_; | 157 stream_->OnStreamHeaders(headers_string_); |
176 | 158 stream_->OnStreamHeadersComplete(false, headers_string_.size()); |
177 EXPECT_EQ(message.size(), stream_->ProcessData( | 159 EXPECT_EQ(body_.size(), stream_->ProcessData(body_.c_str(), body_.size())); |
178 message.c_str(), message.size())); | 160 EXPECT_EQ("11", StreamHeadersValue("content-length")); |
179 EXPECT_EQ(11u, StreamHeaders().content_length()); | 161 EXPECT_EQ("/", StreamHeadersValue(":path")); |
180 EXPECT_EQ("https://www.google.com/", StreamHeaders().request_uri()); | 162 EXPECT_EQ("POST", StreamHeadersValue(":method")); |
181 EXPECT_EQ("POST", StreamHeaders().request_method()); | |
182 EXPECT_EQ(body_, StreamBody()); | 163 EXPECT_EQ(body_, StreamBody()); |
183 } | 164 } |
184 | 165 |
185 TEST_P(QuicSpdyServerStreamTest, TestFramingExtraData) { | 166 TEST_P(QuicSpdyServerStreamTest, TestFramingExtraData) { |
186 string large_body = "hello world!!!!!!"; | 167 string large_body = "hello world!!!!!!"; |
187 | 168 |
188 // We'll automatically write out an error (headers + body) | 169 // We'll automatically write out an error (headers + body) |
189 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(AnyNumber()). | 170 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(AnyNumber()). |
190 WillRepeatedly(Invoke(ConsumeAllData)); | 171 WillRepeatedly(Invoke(ConsumeAllData)); |
191 | 172 |
192 EXPECT_EQ(headers_string_.size(), stream_->ProcessData( | 173 stream_->OnStreamHeaders(headers_string_); |
193 headers_string_.c_str(), headers_string_.size())); | 174 stream_->OnStreamHeadersComplete(false, headers_string_.size()); |
| 175 EXPECT_EQ(body_.size(), stream_->ProcessData(body_.c_str(), body_.size())); |
194 // Content length is still 11. This will register as an error and we won't | 176 // Content length is still 11. This will register as an error and we won't |
195 // accept the bytes. | 177 // accept the bytes. |
196 stream_->ProcessData(large_body.c_str(), large_body.size()); | 178 stream_->ProcessData(large_body.c_str(), large_body.size()); |
197 EXPECT_EQ(11u, StreamHeaders().content_length()); | 179 EXPECT_EQ("11", StreamHeadersValue("content-length")); |
198 EXPECT_EQ("https://www.google.com/", StreamHeaders().request_uri()); | 180 EXPECT_EQ("/", StreamHeadersValue(":path")); |
199 EXPECT_EQ("POST", StreamHeaders().request_method()); | 181 EXPECT_EQ("POST", StreamHeadersValue(":method")); |
200 } | 182 } |
201 | 183 |
202 TEST_P(QuicSpdyServerStreamTest, TestSendResponse) { | 184 TEST_P(QuicSpdyServerStreamTest, TestSendResponse) { |
203 BalsaHeaders* request_headers = stream_->mutable_headers(); | 185 SpdyHeaderBlock* request_headers = stream_->mutable_headers(); |
204 request_headers->SetRequestFirstlineFromStringPieces( | 186 (*request_headers)[":path"] = "/foo"; |
205 "GET", | 187 (*request_headers)[":host"] = ""; |
206 "https://www.google.com/foo", | 188 (*request_headers)[":version"] = "HTTP/1.1"; |
207 "HTTP/1.1"); | 189 (*request_headers)[":method"] = "GET"; |
208 | 190 |
209 response_headers_.SetResponseFirstlineFromStringPieces( | 191 response_headers_[":version"] = "HTTP/1.1"; |
210 "HTTP/1.1", "200", "OK"); | 192 response_headers_[":status"] = "200 OK"; |
211 response_headers_.ReplaceOrAppendHeader("content-length", "3"); | 193 response_headers_["content-length"] = "3"; |
212 | 194 |
213 InSequence s; | 195 InSequence s; |
214 EXPECT_CALL(session_, WritevData(kHeadersStreamId, _, 0, false, _, nullptr)); | 196 EXPECT_CALL(session_, WritevData(kHeadersStreamId, _, 0, false, _, nullptr)); |
215 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(1). | 197 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(1). |
216 WillOnce(Return(QuicConsumedData(3, true))); | 198 WillOnce(Return(QuicConsumedData(3, true))); |
217 | 199 |
218 QuicSpdyServerStreamPeer::SendResponse(stream_.get()); | 200 QuicSpdyServerStreamPeer::SendResponse(stream_.get()); |
219 EXPECT_TRUE(stream_->read_side_closed()); | 201 EXPECT_TRUE(stream_->read_side_closed()); |
220 EXPECT_TRUE(stream_->write_side_closed()); | 202 EXPECT_TRUE(stream_->write_side_closed()); |
221 } | 203 } |
222 | 204 |
223 TEST_P(QuicSpdyServerStreamTest, TestSendErrorResponse) { | 205 TEST_P(QuicSpdyServerStreamTest, TestSendErrorResponse) { |
224 response_headers_.SetResponseFirstlineFromStringPieces( | 206 response_headers_[":version"] = "HTTP/1.1"; |
225 "HTTP/1.1", "500", "Server Error"); | 207 response_headers_[":status"] = "500 Server Error"; |
226 response_headers_.ReplaceOrAppendHeader("content-length", "3"); | 208 response_headers_["content-length"] = "3"; |
227 | 209 |
228 InSequence s; | 210 InSequence s; |
229 EXPECT_CALL(session_, WritevData(kHeadersStreamId, _, 0, false, _, nullptr)); | 211 EXPECT_CALL(session_, WritevData(kHeadersStreamId, _, 0, false, _, nullptr)); |
230 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(1). | 212 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(1). |
231 WillOnce(Return(QuicConsumedData(3, true))); | 213 WillOnce(Return(QuicConsumedData(3, true))); |
232 | 214 |
233 QuicSpdyServerStreamPeer::SendErrorResponse(stream_.get()); | 215 QuicSpdyServerStreamPeer::SendErrorResponse(stream_.get()); |
234 EXPECT_TRUE(stream_->read_side_closed()); | 216 EXPECT_TRUE(stream_->read_side_closed()); |
235 EXPECT_TRUE(stream_->write_side_closed()); | 217 EXPECT_TRUE(stream_->write_side_closed()); |
236 } | 218 } |
(...skipping 25 matching lines...) Expand all Loading... |
262 StringPiece data(arr, arraysize(arr)); | 244 StringPiece data(arr, arraysize(arr)); |
263 QuicStreamFrame frame(stream_->id(), true, 0, MakeIOVector(data)); | 245 QuicStreamFrame frame(stream_->id(), true, 0, MakeIOVector(data)); |
264 // Verify that we don't crash when we get a invalid headers in stream frame. | 246 // Verify that we don't crash when we get a invalid headers in stream frame. |
265 stream_->OnStreamFrame(frame); | 247 stream_->OnStreamFrame(frame); |
266 } | 248 } |
267 | 249 |
268 } // namespace | 250 } // namespace |
269 } // namespace test | 251 } // namespace test |
270 } // namespace tools | 252 } // namespace tools |
271 } // namespace net | 253 } // namespace net |
OLD | NEW |