diff options
Diffstat (limited to 'net/http/http_network_transaction_unittest.cc')
-rw-r--r-- | net/http/http_network_transaction_unittest.cc | 198 |
1 files changed, 197 insertions, 1 deletions
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index aa18df5..b9458d5 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc @@ -65,7 +65,6 @@ ProxyService* CreateFixedProxyService(const std::string& proxy) { return ProxyService::CreateFixed(proxy_config); } - HttpNetworkSession* CreateSession(SessionDependencies* session_deps) { return new HttpNetworkSession(NULL, session_deps->host_resolver, @@ -4679,4 +4678,201 @@ TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) { EXPECT_EQ("hello world", response_data); } +// MockAuthHandlerCanonical is used by the ResolveCanonicalName +// HttpNetworkTransaction unit test below. Callers set up expectations for +// whether the canonical name needs to be resolved. +class MockAuthHandlerCanonical : public HttpAuthHandler { + public: + enum Resolve { + RESOLVE_INIT, + RESOLVE_SKIP, + RESOLVE_SYNC, + RESOLVE_ASYNC, + RESOLVE_TESTED, + }; + + MockAuthHandlerCanonical() : resolve_(RESOLVE_INIT), user_callback_(NULL) {} + virtual ~MockAuthHandlerCanonical() {} + + void SetResolveExpectation(Resolve resolve) { + EXPECT_EQ(RESOLVE_INIT, resolve_); + resolve_ = resolve; + } + + void ResetResolveExpectation() { + EXPECT_EQ(RESOLVE_TESTED, resolve_); + resolve_ = RESOLVE_INIT; + } + + virtual bool NeedsCanonicalName() { + switch (resolve_) { + case RESOLVE_SYNC: + case RESOLVE_ASYNC: + return true; + case RESOLVE_SKIP: + resolve_ = RESOLVE_TESTED; + return false; + default: + NOTREACHED(); + return false; + } + } + + virtual int ResolveCanonicalName(HostResolver* host_resolver, + CompletionCallback* callback, + const BoundNetLog& net_log) { + EXPECT_NE(RESOLVE_TESTED, resolve_); + int rv = OK; + switch (resolve_) { + case RESOLVE_SYNC: + resolve_ = RESOLVE_TESTED; + break; + case RESOLVE_ASYNC: + EXPECT_TRUE(user_callback_ == NULL); + rv = ERR_IO_PENDING; + user_callback_ = callback; + MessageLoop::current()->PostTask( + FROM_HERE, + NewRunnableMethod( + this, &MockAuthHandlerCanonical::OnResolveCanonicalName)); + break; + default: + NOTREACHED(); + break; + } + return rv; + } + + void OnResolveCanonicalName() { + EXPECT_EQ(RESOLVE_ASYNC, resolve_); + EXPECT_TRUE(user_callback_ != NULL); + resolve_ = RESOLVE_TESTED; + CompletionCallback* callback = user_callback_; + user_callback_ = NULL; + callback->Run(OK); + } + + virtual bool Init(HttpAuth::ChallengeTokenizer* challenge) { + scheme_ = "mock"; + score_ = 1; + properties_ = 0; + return true; + } + + virtual int GenerateAuthToken(const std::wstring& username, + const std::wstring& password, + const HttpRequestInfo* request, + const ProxyInfo* proxy, + std::string* auth_token) { + auth_token->assign("Mock AUTH myserver.example.com"); + return OK; + } + + virtual int GenerateDefaultAuthToken(const HttpRequestInfo* request, + const ProxyInfo* proxy, + std::string* auth_token) { + auth_token->assign("Mock DEFAULT_AUTH myserver.example.com"); + return OK; + } + + // The Factory class simply returns the same handler each time + // CreateAuthHandler is called. + class Factory : public HttpAuthHandlerFactory { + public: + Factory() {} + virtual ~Factory() {} + + void set_mock_handler(MockAuthHandlerCanonical* mock_handler) { + mock_handler_ = mock_handler; + } + MockAuthHandlerCanonical* mock_handler() const { + return mock_handler_.get(); + } + + virtual int CreateAuthHandler(HttpAuth::ChallengeTokenizer* challenge, + HttpAuth::Target target, + const GURL& origin, + scoped_refptr<HttpAuthHandler>* handler) { + *handler = mock_handler_; + return OK; + } + + private: + scoped_refptr<MockAuthHandlerCanonical> mock_handler_; + }; + + private: + Resolve resolve_; + CompletionCallback* user_callback_; +}; + +// Tests that ResolveCanonicalName is handled correctly by the +// HttpNetworkTransaction. +TEST_F(HttpNetworkTransactionTest, ResolveCanonicalName) { + SessionDependencies session_deps; + scoped_refptr<MockAuthHandlerCanonical> auth_handler( + new MockAuthHandlerCanonical()); + auth_handler->Init(NULL); + MockAuthHandlerCanonical::Factory* auth_factory( + new MockAuthHandlerCanonical::Factory()); + auth_factory->set_mock_handler(auth_handler); + session_deps.http_auth_handler_factory.reset(auth_factory); + + for (int i = 0; i < 2; ++i) { + scoped_ptr<HttpTransaction> trans( + new HttpNetworkTransaction(CreateSession(&session_deps))); + + // Set up expectations for this pass of the test. Many of the EXPECT calls + // are contained inside the MockAuthHandlerCanonical codebase in response to + // the expectations. + MockAuthHandlerCanonical::Resolve resolve = (i == 0) ? + MockAuthHandlerCanonical::RESOLVE_SYNC : + MockAuthHandlerCanonical::RESOLVE_ASYNC; + auth_handler->SetResolveExpectation(resolve); + HttpRequestInfo request; + request.method = "GET"; + request.url = GURL("http://myserver/"); + request.load_flags = 0; + + MockWrite data_writes1[] = { + MockWrite("GET / HTTP/1.1\r\n" + "Host: myserver\r\n" + "Connection: keep-alive\r\n\r\n"), + }; + + MockRead data_reads1[] = { + MockRead("HTTP/1.1 401 Unauthorized\r\n"), + MockRead("WWW-Authenticate: Mock myserver.example.com\r\n"), + MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), + MockRead("Content-Length: 14\r\n\r\n"), + MockRead("Unauthorized\r\n"), + }; + + StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), + data_writes1, arraysize(data_writes1)); + session_deps.socket_factory.AddSocketDataProvider(&data1); + + TestCompletionCallback callback1; + + int rv = trans->Start(&request, &callback1, NULL); + EXPECT_EQ(ERR_IO_PENDING, rv); + + rv = callback1.WaitForResult(); + EXPECT_EQ(OK, rv); + + const HttpResponseInfo* response = trans->GetResponseInfo(); + EXPECT_FALSE(response == NULL); + + // The password prompt is set after the canonical name is resolved. + // If it isn't present or is incorrect, it indicates that the scheme + // did not complete correctly. + EXPECT_FALSE(response->auth_challenge.get() == NULL); + + EXPECT_EQ(L"myserver:80", response->auth_challenge->host_and_port); + EXPECT_EQ(L"", response->auth_challenge->realm); + EXPECT_EQ(L"mock", response->auth_challenge->scheme); + auth_handler->ResetResolveExpectation(); + } +} + } // namespace net |