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

Side by Side Diff: net/server/http_server_unittest.cc

Issue 2648553002: HttpServer::ParseHeaders: don't DCHECK on bogus headers termination (Closed)
Patch Set: More refinements based on review feedback. Created 3 years, 11 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/server/http_server.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 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/server/http_server.h" 5 #include "net/server/http_server.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <memory> 10 #include <memory>
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 return false; 126 return false;
127 while (!IsCompleteResponse(*message)) { 127 while (!IsCompleteResponse(*message)) {
128 std::string chunk; 128 std::string chunk;
129 if (!Read(&chunk, 1)) 129 if (!Read(&chunk, 1))
130 return false; 130 return false;
131 message->append(chunk); 131 message->append(chunk);
132 } 132 }
133 return true; 133 return true;
134 } 134 }
135 135
136 void ExpectUsedThenDisconnectedWithNoData() {
137 // Check that the socket was opened...
138 ASSERT_TRUE(socket_->WasEverUsed());
139
140 // ...then closed when the server disconnected. Verify that the socket was
141 // closed by checking that a Read() fails.
142 std::string response;
143 ASSERT_FALSE(Read(&response, 1u));
144 ASSERT_TRUE(response.empty());
145 }
146
136 TCPClientSocket& socket() { return *socket_; } 147 TCPClientSocket& socket() { return *socket_; }
137 148
138 private: 149 private:
139 void OnConnect(const base::Closure& quit_loop, int result) { 150 void OnConnect(const base::Closure& quit_loop, int result) {
140 connect_result_ = result; 151 connect_result_ = result;
141 quit_loop.Run(); 152 quit_loop.Run();
142 } 153 }
143 154
144 void Write() { 155 void Write() {
145 int result = socket_->Write( 156 int result = socket_->Write(
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 scoped_refptr<DrainableIOBuffer> write_buffer_; 195 scoped_refptr<DrainableIOBuffer> write_buffer_;
185 std::unique_ptr<TCPClientSocket> socket_; 196 std::unique_ptr<TCPClientSocket> socket_;
186 int connect_result_; 197 int connect_result_;
187 }; 198 };
188 199
189 } // namespace 200 } // namespace
190 201
191 class HttpServerTest : public testing::Test, 202 class HttpServerTest : public testing::Test,
192 public HttpServer::Delegate { 203 public HttpServer::Delegate {
193 public: 204 public:
194 HttpServerTest() : quit_after_request_count_(0) {} 205 HttpServerTest()
206 : quit_after_request_count_(0), quit_on_close_connection_(-1) {}
195 207
196 void SetUp() override { 208 void SetUp() override {
197 std::unique_ptr<ServerSocket> server_socket( 209 std::unique_ptr<ServerSocket> server_socket(
198 new TCPServerSocket(NULL, NetLogSource())); 210 new TCPServerSocket(NULL, NetLogSource()));
199 server_socket->ListenWithAddressAndPort("127.0.0.1", 0, 1); 211 server_socket->ListenWithAddressAndPort("127.0.0.1", 0, 1);
200 server_.reset(new HttpServer(std::move(server_socket), this)); 212 server_.reset(new HttpServer(std::move(server_socket), this));
201 ASSERT_THAT(server_->GetLocalAddress(&server_address_), IsOk()); 213 ASSERT_THAT(server_->GetLocalAddress(&server_address_), IsOk());
202 } 214 }
203 215
216 void TearDown() override {
217 // Run the event loop some to make sure that the memory handed over to
218 // DeleteSoon gets fully freed.
219 base::RunLoop().RunUntilIdle();
220 }
221
204 void OnConnect(int connection_id) override { 222 void OnConnect(int connection_id) override {
205 DCHECK(connection_map_.find(connection_id) == connection_map_.end()); 223 DCHECK(connection_map_.find(connection_id) == connection_map_.end());
206 connection_map_[connection_id] = true; 224 connection_map_[connection_id] = true;
207 } 225 }
208 226
209 void OnHttpRequest(int connection_id, 227 void OnHttpRequest(int connection_id,
210 const HttpServerRequestInfo& info) override { 228 const HttpServerRequestInfo& info) override {
211 requests_.push_back(std::make_pair(info, connection_id)); 229 requests_.push_back(std::make_pair(info, connection_id));
212 if (requests_.size() == quit_after_request_count_) 230 if (requests_.size() == quit_after_request_count_)
213 run_loop_quit_func_.Run(); 231 run_loop_quit_func_.Run();
214 } 232 }
215 233
216 void OnWebSocketRequest(int connection_id, 234 void OnWebSocketRequest(int connection_id,
217 const HttpServerRequestInfo& info) override { 235 const HttpServerRequestInfo& info) override {
218 NOTREACHED(); 236 NOTREACHED();
219 } 237 }
220 238
221 void OnWebSocketMessage(int connection_id, const std::string& data) override { 239 void OnWebSocketMessage(int connection_id, const std::string& data) override {
222 NOTREACHED(); 240 NOTREACHED();
223 } 241 }
224 242
225 void OnClose(int connection_id) override { 243 void OnClose(int connection_id) override {
226 DCHECK(connection_map_.find(connection_id) != connection_map_.end()); 244 DCHECK(connection_map_.find(connection_id) != connection_map_.end());
227 connection_map_[connection_id] = false; 245 connection_map_[connection_id] = false;
246 if (connection_id == quit_on_close_connection_)
247 run_loop_quit_func_.Run();
228 } 248 }
229 249
230 bool RunUntilRequestsReceived(size_t count) { 250 bool RunUntilRequestsReceived(size_t count) {
231 quit_after_request_count_ = count; 251 quit_after_request_count_ = count;
232 if (requests_.size() == count) 252 if (requests_.size() == count)
233 return true; 253 return true;
234 254
235 base::RunLoop run_loop; 255 base::RunLoop run_loop;
236 run_loop_quit_func_ = run_loop.QuitClosure(); 256 run_loop_quit_func_ = run_loop.QuitClosure();
237 bool success = RunLoopWithTimeout(&run_loop); 257 bool success = RunLoopWithTimeout(&run_loop);
238 run_loop_quit_func_.Reset(); 258 run_loop_quit_func_.Reset();
239 return success; 259 return success;
240 } 260 }
241 261
262 bool RunUntilConnectionIdClosed(int connection_id) {
263 quit_on_close_connection_ = connection_id;
264 auto iter = connection_map_.find(connection_id);
265 if (iter != connection_map_.end() && !iter->second) {
266 // Already disconnected.
267 return true;
268 }
269
270 base::RunLoop run_loop;
271 run_loop_quit_func_ = run_loop.QuitClosure();
272 bool success = RunLoopWithTimeout(&run_loop);
273 run_loop_quit_func_.Reset();
274 return success;
275 }
276
242 HttpServerRequestInfo GetRequest(size_t request_index) { 277 HttpServerRequestInfo GetRequest(size_t request_index) {
243 return requests_[request_index].first; 278 return requests_[request_index].first;
244 } 279 }
245 280
281 size_t num_requests() const { return requests_.size(); }
282
246 int GetConnectionId(size_t request_index) { 283 int GetConnectionId(size_t request_index) {
247 return requests_[request_index].second; 284 return requests_[request_index].second;
248 } 285 }
249 286
250 void HandleAcceptResult(std::unique_ptr<StreamSocket> socket) { 287 void HandleAcceptResult(std::unique_ptr<StreamSocket> socket) {
251 server_->accepted_socket_ = std::move(socket); 288 server_->accepted_socket_ = std::move(socket);
252 server_->HandleAcceptResult(OK); 289 server_->HandleAcceptResult(OK);
253 } 290 }
254 291
255 std::unordered_map<int, bool>& connection_map() { return connection_map_; } 292 std::unordered_map<int, bool>& connection_map() { return connection_map_; }
256 293
257 protected: 294 protected:
258 std::unique_ptr<HttpServer> server_; 295 std::unique_ptr<HttpServer> server_;
259 IPEndPoint server_address_; 296 IPEndPoint server_address_;
260 base::Closure run_loop_quit_func_; 297 base::Closure run_loop_quit_func_;
261 std::vector<std::pair<HttpServerRequestInfo, int> > requests_; 298 std::vector<std::pair<HttpServerRequestInfo, int> > requests_;
262 std::unordered_map<int /* connection_id */, bool /* connected */> 299 std::unordered_map<int /* connection_id */, bool /* connected */>
263 connection_map_; 300 connection_map_;
264 301
265 private: 302 private:
266 size_t quit_after_request_count_; 303 size_t quit_after_request_count_;
304 int quit_on_close_connection_;
267 }; 305 };
268 306
269 namespace { 307 namespace {
270 308
271 class WebSocketTest : public HttpServerTest { 309 class WebSocketTest : public HttpServerTest {
272 void OnHttpRequest(int connection_id, 310 void OnHttpRequest(int connection_id,
273 const HttpServerRequestInfo& info) override { 311 const HttpServerRequestInfo& info) override {
274 NOTREACHED(); 312 NOTREACHED();
275 } 313 }
276 314
(...skipping 12 matching lines...) Expand all
289 client.Send("GET /test HTTP/1.1\r\n\r\n"); 327 client.Send("GET /test HTTP/1.1\r\n\r\n");
290 ASSERT_TRUE(RunUntilRequestsReceived(1)); 328 ASSERT_TRUE(RunUntilRequestsReceived(1));
291 ASSERT_EQ("GET", GetRequest(0).method); 329 ASSERT_EQ("GET", GetRequest(0).method);
292 ASSERT_EQ("/test", GetRequest(0).path); 330 ASSERT_EQ("/test", GetRequest(0).path);
293 ASSERT_EQ("", GetRequest(0).data); 331 ASSERT_EQ("", GetRequest(0).data);
294 ASSERT_EQ(0u, GetRequest(0).headers.size()); 332 ASSERT_EQ(0u, GetRequest(0).headers.size());
295 ASSERT_TRUE(base::StartsWith(GetRequest(0).peer.ToString(), "127.0.0.1", 333 ASSERT_TRUE(base::StartsWith(GetRequest(0).peer.ToString(), "127.0.0.1",
296 base::CompareCase::SENSITIVE)); 334 base::CompareCase::SENSITIVE));
297 } 335 }
298 336
337 TEST_F(HttpServerTest, RequestBrokenTermination) {
338 TestHttpClient client;
339 ASSERT_THAT(client.ConnectAndWait(server_address_), IsOk());
340 client.Send("GET /test HTTP/1.1\r\n\r)");
341 ASSERT_TRUE(RunUntilConnectionIdClosed(1));
342 EXPECT_EQ(0u, num_requests());
343 client.ExpectUsedThenDisconnectedWithNoData();
344 }
345
299 TEST_F(HttpServerTest, RequestWithHeaders) { 346 TEST_F(HttpServerTest, RequestWithHeaders) {
300 TestHttpClient client; 347 TestHttpClient client;
301 ASSERT_THAT(client.ConnectAndWait(server_address_), IsOk()); 348 ASSERT_THAT(client.ConnectAndWait(server_address_), IsOk());
302 const char* const kHeaders[][3] = { 349 const char* const kHeaders[][3] = {
303 {"Header", ": ", "1"}, 350 {"Header", ": ", "1"},
304 {"HeaderWithNoWhitespace", ":", "1"}, 351 {"HeaderWithNoWhitespace", ":", "1"},
305 {"HeaderWithWhitespace", " : \t ", "1 1 1 \t "}, 352 {"HeaderWithWhitespace", " : \t ", "1 1 1 \t "},
306 {"HeaderWithColon", ": ", "1:1"}, 353 {"HeaderWithColon", ": ", "1:1"},
307 {"EmptyHeader", ":", ""}, 354 {"EmptyHeader", ":", ""},
308 {"EmptyHeaderWithWhitespace", ": \t ", ""}, 355 {"EmptyHeaderWithWhitespace", ": \t ", ""},
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 TestHttpClient client; 543 TestHttpClient client;
497 ASSERT_THAT(client.ConnectAndWait(server_address_), IsOk()); 544 ASSERT_THAT(client.ConnectAndWait(server_address_), IsOk());
498 545
499 client.Send(kBadProtocolRequests[i]); 546 client.Send(kBadProtocolRequests[i]);
500 ASSERT_FALSE(RunUntilRequestsReceived(1)); 547 ASSERT_FALSE(RunUntilRequestsReceived(1));
501 548
502 // Assert that the delegate was updated properly. 549 // Assert that the delegate was updated properly.
503 ASSERT_EQ(1u, connection_map().size()); 550 ASSERT_EQ(1u, connection_map().size());
504 ASSERT_FALSE(connection_map().begin()->second); 551 ASSERT_FALSE(connection_map().begin()->second);
505 552
506 // Assert that the socket was opened... 553 client.ExpectUsedThenDisconnectedWithNoData();
507 ASSERT_TRUE(client.socket().WasEverUsed());
508
509 // ...then closed when the server disconnected. Verify that the socket was
510 // closed by checking that a Read() fails.
511 std::string response;
512 ASSERT_FALSE(client.Read(&response, 1u));
513 ASSERT_EQ(std::string(), response);
514 554
515 // Reset the state of the connection map. 555 // Reset the state of the connection map.
516 connection_map().clear(); 556 connection_map().clear();
517 } 557 }
518 } 558 }
519 559
520 class MockStreamSocket : public StreamSocket { 560 class MockStreamSocket : public StreamSocket {
521 public: 561 public:
522 MockStreamSocket() 562 MockStreamSocket()
523 : connected_(true), 563 : connected_(true),
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
699 ASSERT_THAT(client.ConnectAndWait(server_address_), IsOk()); 739 ASSERT_THAT(client.ConnectAndWait(server_address_), IsOk());
700 client.Send("GET / HTTP/1.1\r\n\r\n"); 740 client.Send("GET / HTTP/1.1\r\n\r\n");
701 ASSERT_FALSE(RunUntilRequestsReceived(1)); 741 ASSERT_FALSE(RunUntilRequestsReceived(1));
702 ASSERT_EQ(1ul, connection_ids_.size()); 742 ASSERT_EQ(1ul, connection_ids_.size());
703 ASSERT_EQ(0ul, requests_.size()); 743 ASSERT_EQ(0ul, requests_.size());
704 } 744 }
705 745
706 } // namespace 746 } // namespace
707 747
708 } // namespace net 748 } // namespace net
OLDNEW
« no previous file with comments | « net/server/http_server.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698