| 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 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |