Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2011 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 #include <string> | |
| 6 | |
| 7 #include "base/memory/ref_counted.h" | |
| 8 #include "base/memory/scoped_vector.h" | |
| 9 #include "base/stringprintf.h" | |
| 10 #include "base/utf_string_conversions.h" | |
| 11 #include "net/base/address_list.h" | |
| 12 #include "net/base/host_cache.h" | |
| 13 #include "net/base/io_buffer.h" | |
| 14 #include "net/base/mock_host_resolver.h" | |
| 15 #include "net/base/net_errors.h" | |
| 16 #include "net/base/net_util.h" | |
| 17 #include "net/base/request_priority.h" | |
| 18 #include "net/base/ssl_config_service_defaults.h" | |
| 19 #include "net/http/http_auth_handler_mock.h" | |
| 20 #include "net/http/http_network_session.h" | |
| 21 #include "net/http/http_network_transaction.h" | |
| 22 #include "net/http/http_request_info.h" | |
| 23 #include "net/http/http_server_properties_impl.h" | |
| 24 #include "net/proxy/proxy_service.h" | |
| 25 #include "net/socket/client_socket_handle.h" | |
| 26 #include "net/socket/client_socket_pool_histograms.h" | |
| 27 #include "net/socket/socket_test_util.h" | |
| 28 #include "testing/gmock/include/gmock/gmock.h" | |
| 29 #include "testing/gtest/include/gtest/gtest.h" | |
| 30 | |
| 31 using testing::StrEq; | |
| 32 | |
| 33 namespace net { | |
|
mmenke
2011/11/09 16:10:58
nit: It's more common in Chrome code to have a li
James Simonsen
2011/11/09 22:17:50
Done.
| |
| 34 namespace { | |
| 35 | |
| 36 class HttpPipelinedNetworkTransactionTest : public testing::Test { | |
| 37 public: | |
| 38 HttpPipelinedNetworkTransactionTest() | |
| 39 : histograms_("a"), | |
| 40 pool_(1, 1, &histograms_, &factory_) { | |
| 41 } | |
| 42 | |
| 43 virtual void SetUp() OVERRIDE { | |
| 44 default_pipelining_enabled_ = HttpStreamFactory::http_pipelining_enabled(); | |
| 45 HttpStreamFactory::set_http_pipelining_enabled(true); | |
| 46 } | |
| 47 | |
| 48 virtual void TearDown() OVERRIDE { | |
| 49 MessageLoop::current()->RunAllPending(); | |
| 50 HttpStreamFactory::set_http_pipelining_enabled(default_pipelining_enabled_); | |
| 51 } | |
| 52 | |
| 53 void Initialize() { | |
| 54 proxy_service_.reset(ProxyService::CreateDirect()); | |
| 55 mock_resolver_.reset(new MockHostResolver); | |
| 56 ssl_config_ = new SSLConfigServiceDefaults; | |
| 57 auth_handler_factory_.reset(new HttpAuthHandlerMock::Factory()); | |
| 58 http_server_properties_.reset(new HttpServerPropertiesImpl); | |
| 59 | |
| 60 HttpNetworkSession::Params session_params; | |
| 61 session_params.client_socket_factory = &factory_; | |
| 62 session_params.proxy_service = proxy_service_.get(); | |
| 63 session_params.host_resolver = mock_resolver_.get(); | |
| 64 session_params.ssl_config_service = ssl_config_.get(); | |
| 65 session_params.http_auth_handler_factory = auth_handler_factory_.get(); | |
| 66 session_params.http_server_properties = http_server_properties_.get(); | |
| 67 session_ = new HttpNetworkSession(session_params); | |
| 68 } | |
| 69 | |
| 70 void AddExpectedConnection(MockRead* reads, size_t reads_count, | |
| 71 MockWrite* writes, size_t writes_count) { | |
| 72 DeterministicSocketData* data = new DeterministicSocketData( | |
| 73 reads, reads_count, writes, writes_count); | |
| 74 data->set_connect_data(MockConnect(false, 0)); | |
| 75 if (reads_count || writes_count) { | |
| 76 data->StopAfter(reads_count + writes_count); | |
| 77 } | |
| 78 factory_.AddSocketDataProvider(data); | |
| 79 data_vector_.push_back(data); | |
| 80 } | |
| 81 | |
| 82 const HttpRequestInfo* GetRequestInfo(const char* filename) { | |
| 83 std::string url = StringPrintf("http://localhost/%s", filename); | |
| 84 HttpRequestInfo* request_info = new HttpRequestInfo; | |
| 85 request_info->url = GURL(url); | |
| 86 request_info->method = "GET"; | |
| 87 request_info_vector_.push_back(request_info); | |
| 88 return request_info; | |
| 89 } | |
| 90 | |
| 91 void ExpectResponse(const std::string& expected, | |
| 92 HttpNetworkTransaction& transaction) { | |
| 93 scoped_refptr<IOBuffer> buffer(new IOBuffer(expected.size())); | |
| 94 EXPECT_EQ(static_cast<int>(expected.size()), | |
| 95 transaction.Read(buffer.get(), expected.size(), &callback_)); | |
| 96 std::string actual(buffer->data(), expected.size()); | |
| 97 EXPECT_THAT(actual, StrEq(expected)); | |
| 98 EXPECT_EQ(OK, transaction.Read(buffer.get(), expected.size(), &callback_)); | |
| 99 } | |
| 100 | |
| 101 void CompleteTwoRequests() { | |
| 102 scoped_ptr<HttpNetworkTransaction> one_transaction( | |
| 103 new HttpNetworkTransaction(session_.get())); | |
| 104 TestOldCompletionCallback one_callback; | |
| 105 EXPECT_EQ(ERR_IO_PENDING, | |
| 106 one_transaction->Start(GetRequestInfo("one.html"), &one_callback, | |
| 107 BoundNetLog())); | |
| 108 EXPECT_EQ(OK, one_callback.WaitForResult()); | |
| 109 | |
| 110 HttpNetworkTransaction two_transaction(session_.get()); | |
| 111 TestOldCompletionCallback two_callback; | |
| 112 EXPECT_EQ(ERR_IO_PENDING, | |
| 113 two_transaction.Start(GetRequestInfo("two.html"), &two_callback, | |
| 114 BoundNetLog())); | |
| 115 | |
| 116 TestOldCompletionCallback one_read_callback; | |
| 117 scoped_refptr<IOBuffer> buffer(new IOBuffer(8)); | |
| 118 EXPECT_EQ(ERR_IO_PENDING, | |
| 119 one_transaction->Read(buffer.get(), 8, &one_read_callback)); | |
| 120 | |
| 121 data_vector_[0]->RunFor(2); | |
| 122 EXPECT_EQ(8, one_read_callback.WaitForResult()); | |
| 123 std::string actual(buffer->data(), 8); | |
| 124 EXPECT_THAT(actual, StrEq("one.html")); | |
| 125 one_transaction.reset(); | |
|
mmenke
2011/11/09 16:10:58
Why is this needed now, but wasn't before?
James Simonsen
2011/11/09 22:17:50
Good point. I forgot to copy the second Read() fro
| |
| 126 | |
| 127 data_vector_[0]->SetStop(10); | |
| 128 EXPECT_EQ(OK, two_callback.WaitForResult()); | |
| 129 ExpectResponse("two.html", two_transaction); | |
| 130 } | |
| 131 | |
| 132 DeterministicMockClientSocketFactory factory_; | |
| 133 ClientSocketPoolHistograms histograms_; | |
| 134 MockTransportClientSocketPool pool_; | |
| 135 std::vector<scoped_refptr<DeterministicSocketData> > data_vector_; | |
| 136 TestOldCompletionCallback callback_; | |
| 137 ScopedVector<HttpRequestInfo> request_info_vector_; | |
| 138 bool default_pipelining_enabled_; | |
| 139 | |
| 140 scoped_ptr<ProxyService> proxy_service_; | |
| 141 scoped_ptr<MockHostResolver> mock_resolver_; | |
| 142 scoped_refptr<SSLConfigService> ssl_config_; | |
| 143 scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory_; | |
| 144 scoped_ptr<HttpServerPropertiesImpl> http_server_properties_; | |
| 145 scoped_refptr<HttpNetworkSession> session_; | |
| 146 }; | |
| 147 | |
| 148 TEST_F(HttpPipelinedNetworkTransactionTest, OneRequest) { | |
| 149 Initialize(); | |
| 150 | |
| 151 MockWrite writes[] = { | |
| 152 MockWrite(false, 0, "GET /test.html HTTP/1.1\r\n" | |
| 153 "Host: localhost\r\n" | |
| 154 "Connection: keep-alive\r\n\r\n"), | |
| 155 }; | |
| 156 MockRead reads[] = { | |
| 157 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"), | |
| 158 MockRead(false, 2, "Content-Length: 9\r\n\r\n"), | |
| 159 MockRead(false, 3, "test.html"), | |
| 160 }; | |
| 161 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); | |
| 162 | |
| 163 HttpNetworkTransaction transaction(session_.get()); | |
| 164 EXPECT_EQ(ERR_IO_PENDING, | |
| 165 transaction.Start(GetRequestInfo("test.html"), &callback_, | |
| 166 BoundNetLog())); | |
| 167 EXPECT_EQ(OK, callback_.WaitForResult()); | |
| 168 ExpectResponse("test.html", transaction); | |
| 169 } | |
| 170 | |
| 171 TEST_F(HttpPipelinedNetworkTransactionTest, ReusePipeline) { | |
| 172 Initialize(); | |
| 173 | |
| 174 MockWrite writes[] = { | |
| 175 MockWrite(false, 0, "GET /one.html HTTP/1.1\r\n" | |
| 176 "Host: localhost\r\n" | |
| 177 "Connection: keep-alive\r\n\r\n"), | |
| 178 MockWrite(false, 3, "GET /two.html HTTP/1.1\r\n" | |
| 179 "Host: localhost\r\n" | |
| 180 "Connection: keep-alive\r\n\r\n"), | |
| 181 }; | |
| 182 MockRead reads[] = { | |
| 183 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"), | |
| 184 MockRead(false, 2, "Content-Length: 8\r\n\r\n"), | |
| 185 MockRead(true, 4, "one.html"), | |
| 186 MockRead(false, 5, "HTTP/1.1 200 OK\r\n"), | |
| 187 MockRead(false, 6, "Content-Length: 8\r\n\r\n"), | |
| 188 MockRead(false, 7, "two.html"), | |
| 189 }; | |
| 190 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); | |
| 191 | |
| 192 CompleteTwoRequests(); | |
| 193 } | |
| 194 | |
| 195 TEST_F(HttpPipelinedNetworkTransactionTest, ReusesOnSpaceAvailable) { | |
| 196 int old_max_sockets = ClientSocketPoolManager::max_sockets_per_group(); | |
| 197 ClientSocketPoolManager::set_max_sockets_per_group(1); | |
| 198 Initialize(); | |
| 199 | |
| 200 MockWrite writes[] = { | |
| 201 MockWrite(false, 0, "GET /one.html HTTP/1.1\r\n" | |
| 202 "Host: localhost\r\n" | |
| 203 "Connection: keep-alive\r\n\r\n"), | |
| 204 MockWrite(false, 4, "GET /two.html HTTP/1.1\r\n" | |
| 205 "Host: localhost\r\n" | |
| 206 "Connection: keep-alive\r\n\r\n"), | |
| 207 MockWrite(false, 7, "GET /three.html HTTP/1.1\r\n" | |
| 208 "Host: localhost\r\n" | |
| 209 "Connection: keep-alive\r\n\r\n"), | |
| 210 MockWrite(false, 12, "GET /four.html HTTP/1.1\r\n" | |
| 211 "Host: localhost\r\n" | |
| 212 "Connection: keep-alive\r\n\r\n"), | |
| 213 }; | |
| 214 MockRead reads[] = { | |
| 215 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"), | |
| 216 MockRead(false, 2, "Content-Length: 8\r\n\r\n"), | |
| 217 MockRead(false, 3, "one.html"), | |
| 218 MockRead(false, 5, "HTTP/1.1 200 OK\r\n"), | |
| 219 MockRead(false, 6, "Content-Length: 8\r\n\r\n"), | |
| 220 MockRead(false, 8, "two.html"), | |
| 221 MockRead(false, 9, "HTTP/1.1 200 OK\r\n"), | |
| 222 MockRead(false, 10, "Content-Length: 10\r\n\r\n"), | |
| 223 MockRead(false, 11, "three.html"), | |
| 224 MockRead(false, 13, "HTTP/1.1 200 OK\r\n"), | |
| 225 MockRead(false, 14, "Content-Length: 9\r\n\r\n"), | |
| 226 MockRead(false, 15, "four.html"), | |
| 227 }; | |
| 228 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); | |
| 229 | |
| 230 scoped_ptr<HttpNetworkTransaction> one_transaction( | |
| 231 new HttpNetworkTransaction(session_.get())); | |
| 232 TestOldCompletionCallback one_callback; | |
| 233 EXPECT_EQ(ERR_IO_PENDING, | |
| 234 one_transaction->Start(GetRequestInfo("one.html"), &one_callback, | |
| 235 BoundNetLog())); | |
| 236 EXPECT_EQ(OK, one_callback.WaitForResult()); | |
| 237 | |
| 238 HttpNetworkTransaction two_transaction(session_.get()); | |
| 239 TestOldCompletionCallback two_callback; | |
| 240 EXPECT_EQ(ERR_IO_PENDING, | |
| 241 two_transaction.Start(GetRequestInfo("two.html"), &two_callback, | |
| 242 BoundNetLog())); | |
| 243 | |
| 244 HttpNetworkTransaction three_transaction(session_.get()); | |
| 245 TestOldCompletionCallback three_callback; | |
| 246 EXPECT_EQ(ERR_IO_PENDING, | |
| 247 three_transaction.Start(GetRequestInfo("three.html"), | |
| 248 &three_callback, BoundNetLog())); | |
| 249 | |
| 250 HttpNetworkTransaction four_transaction(session_.get()); | |
| 251 TestOldCompletionCallback four_callback; | |
| 252 EXPECT_EQ(ERR_IO_PENDING, | |
| 253 four_transaction.Start(GetRequestInfo("four.html"), &four_callback, | |
| 254 BoundNetLog())); | |
| 255 | |
| 256 ExpectResponse("one.html", *one_transaction.get()); | |
| 257 EXPECT_EQ(OK, two_callback.WaitForResult()); | |
| 258 ExpectResponse("two.html", two_transaction); | |
| 259 EXPECT_EQ(OK, three_callback.WaitForResult()); | |
| 260 ExpectResponse("three.html", three_transaction); | |
| 261 | |
| 262 one_transaction.reset(); | |
| 263 EXPECT_EQ(OK, four_callback.WaitForResult()); | |
| 264 ExpectResponse("four.html", four_transaction); | |
| 265 | |
| 266 ClientSocketPoolManager::set_max_sockets_per_group(old_max_sockets); | |
| 267 } | |
| 268 | |
| 269 TEST_F(HttpPipelinedNetworkTransactionTest, UnknownSizeEvictsToNewPipeline) { | |
| 270 Initialize(); | |
| 271 | |
| 272 MockWrite writes[] = { | |
| 273 MockWrite(false, 0, "GET /one.html HTTP/1.1\r\n" | |
| 274 "Host: localhost\r\n" | |
| 275 "Connection: keep-alive\r\n\r\n"), | |
| 276 MockWrite(false, 2, "GET /two.html HTTP/1.1\r\n" | |
| 277 "Host: localhost\r\n" | |
| 278 "Connection: keep-alive\r\n\r\n"), | |
| 279 }; | |
| 280 MockRead reads[] = { | |
| 281 MockRead(false, 1, "HTTP/1.1 200 OK\r\n\r\n"), | |
| 282 MockRead(true, 3, "one.html"), | |
| 283 MockRead(false, OK, 4), | |
| 284 }; | |
| 285 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); | |
| 286 | |
| 287 MockWrite writes2[] = { | |
| 288 MockWrite(false, 0, "GET /two.html HTTP/1.1\r\n" | |
| 289 "Host: localhost\r\n" | |
| 290 "Connection: keep-alive\r\n\r\n"), | |
| 291 }; | |
| 292 MockRead reads2[] = { | |
| 293 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"), | |
| 294 MockRead(false, 2, "Content-Length: 8\r\n\r\n"), | |
| 295 MockRead(false, 3, "two.html"), | |
| 296 }; | |
| 297 AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2)); | |
| 298 | |
| 299 CompleteTwoRequests(); | |
| 300 } | |
| 301 | |
| 302 TEST_F(HttpPipelinedNetworkTransactionTest, ConnectionCloseEvictToNewPipeline) { | |
| 303 Initialize(); | |
| 304 | |
| 305 MockWrite writes[] = { | |
| 306 MockWrite(false, 0, "GET /one.html HTTP/1.1\r\n" | |
| 307 "Host: localhost\r\n" | |
| 308 "Connection: keep-alive\r\n\r\n"), | |
| 309 MockWrite(false, 3, "GET /two.html HTTP/1.1\r\n" | |
| 310 "Host: localhost\r\n" | |
| 311 "Connection: keep-alive\r\n\r\n"), | |
| 312 }; | |
| 313 MockRead reads[] = { | |
| 314 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"), | |
| 315 MockRead(false, 2, "Content-Length: 8\r\n\r\n"), | |
| 316 MockRead(true, 4, "one.html"), | |
| 317 MockRead(false, ERR_SOCKET_NOT_CONNECTED, 5), | |
| 318 }; | |
| 319 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); | |
| 320 | |
| 321 MockWrite writes2[] = { | |
| 322 MockWrite(false, 0, "GET /two.html HTTP/1.1\r\n" | |
| 323 "Host: localhost\r\n" | |
| 324 "Connection: keep-alive\r\n\r\n"), | |
| 325 }; | |
| 326 MockRead reads2[] = { | |
| 327 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"), | |
| 328 MockRead(false, 2, "Content-Length: 8\r\n\r\n"), | |
| 329 MockRead(false, 3, "two.html"), | |
| 330 }; | |
| 331 AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2)); | |
| 332 | |
| 333 CompleteTwoRequests(); | |
| 334 } | |
| 335 | |
| 336 TEST_F(HttpPipelinedNetworkTransactionTest, ErrorEvictsToNewPipeline) { | |
| 337 Initialize(); | |
| 338 | |
| 339 MockWrite writes[] = { | |
| 340 MockWrite(false, 0, "GET /one.html HTTP/1.1\r\n" | |
| 341 "Host: localhost\r\n" | |
| 342 "Connection: keep-alive\r\n\r\n"), | |
| 343 MockWrite(false, 3, "GET /two.html HTTP/1.1\r\n" | |
| 344 "Host: localhost\r\n" | |
| 345 "Connection: keep-alive\r\n\r\n"), | |
| 346 }; | |
| 347 MockRead reads[] = { | |
| 348 MockRead(false, 1, "HTTP/1.1 200 OK\r\n\r\n"), | |
| 349 MockRead(false, ERR_FAILED, 2), | |
| 350 }; | |
| 351 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); | |
| 352 | |
| 353 MockWrite writes2[] = { | |
| 354 MockWrite(false, 0, "GET /two.html HTTP/1.1\r\n" | |
| 355 "Host: localhost\r\n" | |
| 356 "Connection: keep-alive\r\n\r\n"), | |
| 357 }; | |
| 358 MockRead reads2[] = { | |
| 359 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"), | |
| 360 MockRead(false, 2, "Content-Length: 8\r\n\r\n"), | |
| 361 MockRead(false, 3, "two.html"), | |
| 362 }; | |
| 363 AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2)); | |
| 364 | |
| 365 HttpNetworkTransaction one_transaction(session_.get()); | |
| 366 TestOldCompletionCallback one_callback; | |
| 367 EXPECT_EQ(ERR_IO_PENDING, | |
| 368 one_transaction.Start(GetRequestInfo("one.html"), &one_callback, | |
| 369 BoundNetLog())); | |
| 370 EXPECT_EQ(OK, one_callback.WaitForResult()); | |
| 371 | |
| 372 HttpNetworkTransaction two_transaction(session_.get()); | |
| 373 TestOldCompletionCallback two_callback; | |
| 374 EXPECT_EQ(ERR_IO_PENDING, | |
| 375 two_transaction.Start(GetRequestInfo("two.html"), &two_callback, | |
| 376 BoundNetLog())); | |
| 377 | |
| 378 scoped_refptr<IOBuffer> buffer(new IOBuffer(1)); | |
| 379 EXPECT_EQ(ERR_FAILED, one_transaction.Read(buffer.get(), 1, &callback_)); | |
| 380 EXPECT_EQ(OK, two_callback.WaitForResult()); | |
| 381 ExpectResponse("two.html", two_transaction); | |
| 382 } | |
| 383 | |
| 384 TEST_F(HttpPipelinedNetworkTransactionTest, SendErrorEvictsToNewPipeline) { | |
| 385 Initialize(); | |
| 386 | |
| 387 MockWrite writes[] = { | |
| 388 MockWrite(true, ERR_FAILED, 0), | |
| 389 }; | |
| 390 AddExpectedConnection(NULL, 0, writes, arraysize(writes)); | |
| 391 | |
| 392 MockWrite writes2[] = { | |
| 393 MockWrite(false, 0, "GET /two.html HTTP/1.1\r\n" | |
| 394 "Host: localhost\r\n" | |
| 395 "Connection: keep-alive\r\n\r\n"), | |
| 396 }; | |
| 397 MockRead reads2[] = { | |
| 398 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"), | |
| 399 MockRead(false, 2, "Content-Length: 8\r\n\r\n"), | |
| 400 MockRead(false, 3, "two.html"), | |
| 401 }; | |
| 402 AddExpectedConnection(reads2, arraysize(reads2), writes2, arraysize(writes2)); | |
| 403 | |
| 404 HttpNetworkTransaction one_transaction(session_.get()); | |
| 405 TestOldCompletionCallback one_callback; | |
| 406 EXPECT_EQ(ERR_IO_PENDING, | |
| 407 one_transaction.Start(GetRequestInfo("one.html"), &one_callback, | |
| 408 BoundNetLog())); | |
| 409 | |
| 410 HttpNetworkTransaction two_transaction(session_.get()); | |
| 411 TestOldCompletionCallback two_callback; | |
| 412 EXPECT_EQ(ERR_IO_PENDING, | |
| 413 two_transaction.Start(GetRequestInfo("two.html"), &two_callback, | |
| 414 BoundNetLog())); | |
| 415 | |
| 416 data_vector_[0]->RunFor(1); | |
| 417 EXPECT_EQ(ERR_FAILED, one_callback.WaitForResult()); | |
| 418 | |
| 419 EXPECT_EQ(OK, two_callback.WaitForResult()); | |
| 420 ExpectResponse("two.html", two_transaction); | |
| 421 } | |
| 422 | |
| 423 TEST_F(HttpPipelinedNetworkTransactionTest, BasicHttpAuthentication) { | |
| 424 Initialize(); | |
| 425 | |
| 426 MockWrite writes[] = { | |
| 427 MockWrite(false, 0, "GET /one.html HTTP/1.1\r\n" | |
| 428 "Host: localhost\r\n" | |
| 429 "Connection: keep-alive\r\n\r\n"), | |
| 430 MockWrite(false, 5, "GET /one.html HTTP/1.1\r\n" | |
| 431 "Host: localhost\r\n" | |
| 432 "Connection: keep-alive\r\n" | |
| 433 "Authorization: auth_token\r\n\r\n"), | |
| 434 }; | |
| 435 MockRead reads[] = { | |
| 436 MockRead(false, 1, "HTTP/1.1 401 Authentication Required\r\n"), | |
| 437 MockRead(false, 2, "WWW-Authenticate: Basic realm=\"Secure Area\"\r\n"), | |
| 438 MockRead(false, 3, "Content-Length: 20\r\n\r\n"), | |
| 439 MockRead(false, 4, "needs authentication"), | |
| 440 MockRead(false, 6, "HTTP/1.1 200 OK\r\n"), | |
| 441 MockRead(false, 7, "Content-Length: 8\r\n\r\n"), | |
| 442 MockRead(false, 8, "one.html"), | |
| 443 }; | |
| 444 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes)); | |
| 445 | |
| 446 HttpAuthHandlerMock* mock_auth = new HttpAuthHandlerMock; | |
| 447 std::string challenge_text = "Basic"; | |
| 448 HttpAuth::ChallengeTokenizer challenge(challenge_text.begin(), | |
| 449 challenge_text.end()); | |
| 450 GURL origin("localhost"); | |
| 451 EXPECT_TRUE(mock_auth->InitFromChallenge(&challenge, | |
| 452 HttpAuth::AUTH_SERVER, | |
| 453 origin, | |
| 454 BoundNetLog())); | |
| 455 auth_handler_factory_->AddMockHandler(mock_auth, HttpAuth::AUTH_SERVER); | |
| 456 | |
| 457 HttpNetworkTransaction transaction(session_.get()); | |
| 458 EXPECT_EQ( | |
| 459 ERR_IO_PENDING, | |
| 460 transaction.Start(GetRequestInfo("one.html"), &callback_, BoundNetLog())); | |
| 461 EXPECT_EQ(OK, callback_.WaitForResult()); | |
| 462 | |
| 463 AuthCredentials credentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")); | |
| 464 EXPECT_EQ(OK, transaction.RestartWithAuth(credentials, &callback_)); | |
| 465 | |
| 466 ExpectResponse("one.html", transaction); | |
| 467 } | |
| 468 | |
| 469 } // anonymous namespace | |
| 470 } // namespace net | |
| OLD | NEW |