Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 bool TestUsedThenDisconnectedWithNoData() { | |
|
mmenke
2017/01/20 18:20:57
Rather than a bool, suggest:
void ExpectUsedThenD
Maks Orlovich
2017/01/20 19:00:20
Done.
| |
| 137 // Check that the socket was opened... | |
| 138 if (!socket_->WasEverUsed()) { | |
| 139 return false; | |
| 140 } | |
|
mmenke
2017/01/20 18:20:57
nit: No braces when if + body take up one line ea
Maks Orlovich
2017/01/20 19:00:20
Made moot by above.
| |
| 141 | |
| 142 // ...then closed when the server disconnected. Verify that the socket was | |
| 143 // closed by checking that a Read() fails. | |
| 144 std::string response; | |
| 145 if (Read(&response, 1u)) { | |
| 146 return false; | |
| 147 } | |
|
mmenke
2017/01/20 18:20:57
nit: --braces
Maks Orlovich
2017/01/20 19:00:20
Likewise
| |
| 148 | |
| 149 return response.empty(); | |
| 150 } | |
| 151 | |
| 136 TCPClientSocket& socket() { return *socket_; } | 152 TCPClientSocket& socket() { return *socket_; } |
| 137 | 153 |
| 138 private: | 154 private: |
| 139 void OnConnect(const base::Closure& quit_loop, int result) { | 155 void OnConnect(const base::Closure& quit_loop, int result) { |
| 140 connect_result_ = result; | 156 connect_result_ = result; |
| 141 quit_loop.Run(); | 157 quit_loop.Run(); |
| 142 } | 158 } |
| 143 | 159 |
| 144 void Write() { | 160 void Write() { |
| 145 int result = socket_->Write( | 161 int result = socket_->Write( |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 184 scoped_refptr<DrainableIOBuffer> write_buffer_; | 200 scoped_refptr<DrainableIOBuffer> write_buffer_; |
| 185 std::unique_ptr<TCPClientSocket> socket_; | 201 std::unique_ptr<TCPClientSocket> socket_; |
| 186 int connect_result_; | 202 int connect_result_; |
| 187 }; | 203 }; |
| 188 | 204 |
| 189 } // namespace | 205 } // namespace |
| 190 | 206 |
| 191 class HttpServerTest : public testing::Test, | 207 class HttpServerTest : public testing::Test, |
| 192 public HttpServer::Delegate { | 208 public HttpServer::Delegate { |
| 193 public: | 209 public: |
| 194 HttpServerTest() : quit_after_request_count_(0) {} | 210 HttpServerTest() |
| 211 : quit_after_request_count_(0), quit_on_close_connection_(-1) {} | |
| 195 | 212 |
| 196 void SetUp() override { | 213 void SetUp() override { |
| 197 std::unique_ptr<ServerSocket> server_socket( | 214 std::unique_ptr<ServerSocket> server_socket( |
| 198 new TCPServerSocket(NULL, NetLogSource())); | 215 new TCPServerSocket(NULL, NetLogSource())); |
| 199 server_socket->ListenWithAddressAndPort("127.0.0.1", 0, 1); | 216 server_socket->ListenWithAddressAndPort("127.0.0.1", 0, 1); |
| 200 server_.reset(new HttpServer(std::move(server_socket), this)); | 217 server_.reset(new HttpServer(std::move(server_socket), this)); |
| 201 ASSERT_THAT(server_->GetLocalAddress(&server_address_), IsOk()); | 218 ASSERT_THAT(server_->GetLocalAddress(&server_address_), IsOk()); |
| 202 } | 219 } |
| 203 | 220 |
| 221 void TearDown() override { | |
| 222 // We need to run the event loop some to make sure that the memory | |
|
mmenke
2017/01/20 18:20:57
nit: Avoid "we" in comments - it's a bit ambiguou
Maks Orlovich
2017/01/20 19:00:20
Done.
| |
| 223 // handed over to DeleteSoon gets fully freed. | |
| 224 base::RunLoop().RunUntilIdle(); | |
| 225 } | |
| 226 | |
| 204 void OnConnect(int connection_id) override { | 227 void OnConnect(int connection_id) override { |
| 205 DCHECK(connection_map_.find(connection_id) == connection_map_.end()); | 228 DCHECK(connection_map_.find(connection_id) == connection_map_.end()); |
| 206 connection_map_[connection_id] = true; | 229 connection_map_[connection_id] = true; |
| 207 } | 230 } |
| 208 | 231 |
| 209 void OnHttpRequest(int connection_id, | 232 void OnHttpRequest(int connection_id, |
| 210 const HttpServerRequestInfo& info) override { | 233 const HttpServerRequestInfo& info) override { |
| 211 requests_.push_back(std::make_pair(info, connection_id)); | 234 requests_.push_back(std::make_pair(info, connection_id)); |
| 212 if (requests_.size() == quit_after_request_count_) | 235 if (requests_.size() == quit_after_request_count_) |
| 213 run_loop_quit_func_.Run(); | 236 run_loop_quit_func_.Run(); |
| 214 } | 237 } |
| 215 | 238 |
| 216 void OnWebSocketRequest(int connection_id, | 239 void OnWebSocketRequest(int connection_id, |
| 217 const HttpServerRequestInfo& info) override { | 240 const HttpServerRequestInfo& info) override { |
| 218 NOTREACHED(); | 241 NOTREACHED(); |
| 219 } | 242 } |
| 220 | 243 |
| 221 void OnWebSocketMessage(int connection_id, const std::string& data) override { | 244 void OnWebSocketMessage(int connection_id, const std::string& data) override { |
| 222 NOTREACHED(); | 245 NOTREACHED(); |
| 223 } | 246 } |
| 224 | 247 |
| 225 void OnClose(int connection_id) override { | 248 void OnClose(int connection_id) override { |
| 226 DCHECK(connection_map_.find(connection_id) != connection_map_.end()); | 249 DCHECK(connection_map_.find(connection_id) != connection_map_.end()); |
| 227 connection_map_[connection_id] = false; | 250 connection_map_[connection_id] = false; |
| 251 if (connection_id == quit_on_close_connection_) { | |
| 252 run_loop_quit_func_.Run(); | |
| 253 } | |
|
mmenke
2017/01/20 18:20:57
nit: --braces
Maks Orlovich
2017/01/20 19:00:20
Done.
| |
| 228 } | 254 } |
| 229 | 255 |
| 230 bool RunUntilRequestsReceived(size_t count) { | 256 bool RunUntilRequestsReceived(size_t count) { |
| 231 quit_after_request_count_ = count; | 257 quit_after_request_count_ = count; |
| 232 if (requests_.size() == count) | 258 if (requests_.size() == count) |
| 233 return true; | 259 return true; |
| 234 | 260 |
| 235 base::RunLoop run_loop; | 261 base::RunLoop run_loop; |
| 236 run_loop_quit_func_ = run_loop.QuitClosure(); | 262 run_loop_quit_func_ = run_loop.QuitClosure(); |
| 237 bool success = RunLoopWithTimeout(&run_loop); | 263 bool success = RunLoopWithTimeout(&run_loop); |
| 238 run_loop_quit_func_.Reset(); | 264 run_loop_quit_func_.Reset(); |
| 239 return success; | 265 return success; |
| 240 } | 266 } |
| 241 | 267 |
| 268 bool RunUntilConnectionIdClosed(int connection_id) { | |
| 269 quit_on_close_connection_ = connection_id; | |
| 270 auto iter = connection_map_.find(connection_id); | |
| 271 if (iter != connection_map_.end() && !iter->second) { | |
| 272 // Already disconnected | |
|
mmenke
2017/01/20 18:20:57
nit: Predominant style is to send more comment-y
Maks Orlovich
2017/01/20 19:00:20
Done.
| |
| 273 return true; | |
| 274 } | |
| 275 | |
| 276 base::RunLoop run_loop; | |
| 277 run_loop_quit_func_ = run_loop.QuitClosure(); | |
| 278 bool success = RunLoopWithTimeout(&run_loop); | |
| 279 run_loop_quit_func_.Reset(); | |
| 280 return success; | |
| 281 } | |
| 282 | |
| 242 HttpServerRequestInfo GetRequest(size_t request_index) { | 283 HttpServerRequestInfo GetRequest(size_t request_index) { |
| 243 return requests_[request_index].first; | 284 return requests_[request_index].first; |
| 244 } | 285 } |
| 245 | 286 |
| 287 size_t num_requests() const { return requests_.size(); } | |
| 288 | |
| 246 int GetConnectionId(size_t request_index) { | 289 int GetConnectionId(size_t request_index) { |
| 247 return requests_[request_index].second; | 290 return requests_[request_index].second; |
| 248 } | 291 } |
| 249 | 292 |
| 250 void HandleAcceptResult(std::unique_ptr<StreamSocket> socket) { | 293 void HandleAcceptResult(std::unique_ptr<StreamSocket> socket) { |
| 251 server_->accepted_socket_ = std::move(socket); | 294 server_->accepted_socket_ = std::move(socket); |
| 252 server_->HandleAcceptResult(OK); | 295 server_->HandleAcceptResult(OK); |
| 253 } | 296 } |
| 254 | 297 |
| 255 std::unordered_map<int, bool>& connection_map() { return connection_map_; } | 298 std::unordered_map<int, bool>& connection_map() { return connection_map_; } |
| 256 | 299 |
| 257 protected: | 300 protected: |
| 258 std::unique_ptr<HttpServer> server_; | 301 std::unique_ptr<HttpServer> server_; |
| 259 IPEndPoint server_address_; | 302 IPEndPoint server_address_; |
| 260 base::Closure run_loop_quit_func_; | 303 base::Closure run_loop_quit_func_; |
| 261 std::vector<std::pair<HttpServerRequestInfo, int> > requests_; | 304 std::vector<std::pair<HttpServerRequestInfo, int> > requests_; |
| 262 std::unordered_map<int /* connection_id */, bool /* connected */> | 305 std::unordered_map<int /* connection_id */, bool /* connected */> |
| 263 connection_map_; | 306 connection_map_; |
| 264 | 307 |
| 265 private: | 308 private: |
| 266 size_t quit_after_request_count_; | 309 size_t quit_after_request_count_; |
| 310 int quit_on_close_connection_; | |
| 267 }; | 311 }; |
| 268 | 312 |
| 269 namespace { | 313 namespace { |
| 270 | 314 |
| 271 class WebSocketTest : public HttpServerTest { | 315 class WebSocketTest : public HttpServerTest { |
| 272 void OnHttpRequest(int connection_id, | 316 void OnHttpRequest(int connection_id, |
| 273 const HttpServerRequestInfo& info) override { | 317 const HttpServerRequestInfo& info) override { |
| 274 NOTREACHED(); | 318 NOTREACHED(); |
| 275 } | 319 } |
| 276 | 320 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 289 client.Send("GET /test HTTP/1.1\r\n\r\n"); | 333 client.Send("GET /test HTTP/1.1\r\n\r\n"); |
| 290 ASSERT_TRUE(RunUntilRequestsReceived(1)); | 334 ASSERT_TRUE(RunUntilRequestsReceived(1)); |
| 291 ASSERT_EQ("GET", GetRequest(0).method); | 335 ASSERT_EQ("GET", GetRequest(0).method); |
| 292 ASSERT_EQ("/test", GetRequest(0).path); | 336 ASSERT_EQ("/test", GetRequest(0).path); |
| 293 ASSERT_EQ("", GetRequest(0).data); | 337 ASSERT_EQ("", GetRequest(0).data); |
| 294 ASSERT_EQ(0u, GetRequest(0).headers.size()); | 338 ASSERT_EQ(0u, GetRequest(0).headers.size()); |
| 295 ASSERT_TRUE(base::StartsWith(GetRequest(0).peer.ToString(), "127.0.0.1", | 339 ASSERT_TRUE(base::StartsWith(GetRequest(0).peer.ToString(), "127.0.0.1", |
| 296 base::CompareCase::SENSITIVE)); | 340 base::CompareCase::SENSITIVE)); |
| 297 } | 341 } |
| 298 | 342 |
| 343 TEST_F(HttpServerTest, RequestBrokenTermination) { | |
| 344 TestHttpClient client; | |
| 345 ASSERT_THAT(client.ConnectAndWait(server_address_), IsOk()); | |
| 346 client.Send("GET /test HTTP/1.1\r\n\r)"); | |
| 347 ASSERT_TRUE(RunUntilConnectionIdClosed(1)); | |
| 348 EXPECT_EQ(0u, num_requests()); | |
| 349 EXPECT_TRUE(client.TestUsedThenDisconnectedWithNoData()); | |
| 350 } | |
| 351 | |
| 299 TEST_F(HttpServerTest, RequestWithHeaders) { | 352 TEST_F(HttpServerTest, RequestWithHeaders) { |
| 300 TestHttpClient client; | 353 TestHttpClient client; |
| 301 ASSERT_THAT(client.ConnectAndWait(server_address_), IsOk()); | 354 ASSERT_THAT(client.ConnectAndWait(server_address_), IsOk()); |
| 302 const char* const kHeaders[][3] = { | 355 const char* const kHeaders[][3] = { |
| 303 {"Header", ": ", "1"}, | 356 {"Header", ": ", "1"}, |
| 304 {"HeaderWithNoWhitespace", ":", "1"}, | 357 {"HeaderWithNoWhitespace", ":", "1"}, |
| 305 {"HeaderWithWhitespace", " : \t ", "1 1 1 \t "}, | 358 {"HeaderWithWhitespace", " : \t ", "1 1 1 \t "}, |
| 306 {"HeaderWithColon", ": ", "1:1"}, | 359 {"HeaderWithColon", ": ", "1:1"}, |
| 307 {"EmptyHeader", ":", ""}, | 360 {"EmptyHeader", ":", ""}, |
| 308 {"EmptyHeaderWithWhitespace", ": \t ", ""}, | 361 {"EmptyHeaderWithWhitespace", ": \t ", ""}, |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 496 TestHttpClient client; | 549 TestHttpClient client; |
| 497 ASSERT_THAT(client.ConnectAndWait(server_address_), IsOk()); | 550 ASSERT_THAT(client.ConnectAndWait(server_address_), IsOk()); |
| 498 | 551 |
| 499 client.Send(kBadProtocolRequests[i]); | 552 client.Send(kBadProtocolRequests[i]); |
| 500 ASSERT_FALSE(RunUntilRequestsReceived(1)); | 553 ASSERT_FALSE(RunUntilRequestsReceived(1)); |
| 501 | 554 |
| 502 // Assert that the delegate was updated properly. | 555 // Assert that the delegate was updated properly. |
| 503 ASSERT_EQ(1u, connection_map().size()); | 556 ASSERT_EQ(1u, connection_map().size()); |
| 504 ASSERT_FALSE(connection_map().begin()->second); | 557 ASSERT_FALSE(connection_map().begin()->second); |
| 505 | 558 |
| 506 // Assert that the socket was opened... | 559 ASSERT_TRUE(client.TestUsedThenDisconnectedWithNoData()); |
| 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 | 560 |
| 515 // Reset the state of the connection map. | 561 // Reset the state of the connection map. |
| 516 connection_map().clear(); | 562 connection_map().clear(); |
| 517 } | 563 } |
| 518 } | 564 } |
| 519 | 565 |
| 520 class MockStreamSocket : public StreamSocket { | 566 class MockStreamSocket : public StreamSocket { |
| 521 public: | 567 public: |
| 522 MockStreamSocket() | 568 MockStreamSocket() |
| 523 : connected_(true), | 569 : connected_(true), |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 699 ASSERT_THAT(client.ConnectAndWait(server_address_), IsOk()); | 745 ASSERT_THAT(client.ConnectAndWait(server_address_), IsOk()); |
| 700 client.Send("GET / HTTP/1.1\r\n\r\n"); | 746 client.Send("GET / HTTP/1.1\r\n\r\n"); |
| 701 ASSERT_FALSE(RunUntilRequestsReceived(1)); | 747 ASSERT_FALSE(RunUntilRequestsReceived(1)); |
| 702 ASSERT_EQ(1ul, connection_ids_.size()); | 748 ASSERT_EQ(1ul, connection_ids_.size()); |
| 703 ASSERT_EQ(0ul, requests_.size()); | 749 ASSERT_EQ(0ul, requests_.size()); |
| 704 } | 750 } |
| 705 | 751 |
| 706 } // namespace | 752 } // namespace |
| 707 | 753 |
| 708 } // namespace net | 754 } // namespace net |
| OLD | NEW |