Chromium Code Reviews| Index: net/http/http_network_transaction_unittest.cc |
| diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc |
| index d71ac60ce810d9a05d046f4892d231c71b89958e..2391c4b77dd46957cd7ef8761a5af8b5db3709c2 100644 |
| --- a/net/http/http_network_transaction_unittest.cc |
| +++ b/net/http/http_network_transaction_unittest.cc |
| @@ -4135,6 +4135,138 @@ TEST_F(HttpNetworkTransactionTest, |
| session->CloseAllConnections(); |
| } |
| +// A more nuanced test than GenerateAuthToken test which asserts that |
| +// ERR_INVALID_AUTH_CREDENTIALS does not cause the auth scheme to be |
| +// unnecessarily invalidated, and that if the server co-operates, the |
| +// authentication handshake can continue with the same scheme but with a |
| +// different identity. |
| +TEST_F(HttpNetworkTransactionTest, NonPermanentGenerateAuthTokenError) { |
| + HttpRequestInfo request; |
| + request.method = "GET"; |
| + request.url = GURL("http://www.example.org/"); |
| + |
| + std::unique_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory( |
| + new HttpAuthHandlerMock::Factory()); |
| + auth_handler_factory->set_do_init_from_challenge(true); |
| + |
| + // First handler. Uses default credentials, but barfs at generate auth token. |
| + std::unique_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock()); |
| + mock_handler->set_allows_default_credentials(true); |
| + mock_handler->set_allows_explicit_credentials(true); |
| + mock_handler->set_connection_based(true); |
| + mock_handler->SetGenerateExpectation(true, ERR_INVALID_AUTH_CREDENTIALS); |
| + auth_handler_factory->AddMockHandler(mock_handler.release(), |
| + HttpAuth::AUTH_SERVER); |
| + |
| + // Add another handler for the second challenge. It supports default |
| + // credentials, but they shouldn't be used, since they were already tried. |
| + mock_handler.reset(new HttpAuthHandlerMock()); |
| + mock_handler->set_allows_default_credentials(true); |
| + mock_handler->set_allows_explicit_credentials(true); |
| + mock_handler->set_connection_based(true); |
| + auth_handler_factory->AddMockHandler(mock_handler.release(), |
| + HttpAuth::AUTH_SERVER); |
| + session_deps_.http_auth_handler_factory = std::move(auth_handler_factory); |
| + |
| + std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_); |
| + |
| + MockWrite data_writes1[] = { |
| + MockWrite("GET / HTTP/1.1\r\n" |
| + "Host: www.example.org\r\n" |
| + "Connection: keep-alive\r\n\r\n"), |
| + }; |
| + |
| + MockRead data_reads1[] = { |
| + MockRead("HTTP/1.1 401 Authentication Required\r\n" |
| + "WWW-Authenticate: Mock\r\n" |
| + "Connection: keep-alive\r\n\r\n"), |
| + }; |
| + |
| + // Identical to data_writes1[]. The AuthHandler encounters a |
| + // ERR_INVALID_AUTH_CREDENTIALS during the GenerateAuthToken stage, so the |
| + // transaction procceds without an authorization header. |
| + MockWrite data_writes2[] = { |
| + MockWrite("GET / HTTP/1.1\r\n" |
| + "Host: www.example.org\r\n" |
| + "Connection: keep-alive\r\n\r\n"), |
| + }; |
| + |
| + MockRead data_reads2[] = { |
| + MockRead("HTTP/1.1 401 Authentication Required\r\n" |
| + "WWW-Authenticate: Mock\r\n" |
| + "Connection: keep-alive\r\n\r\n"), |
| + }; |
| + |
| + MockWrite data_writes3[] = { |
| + MockWrite("GET / HTTP/1.1\r\n" |
| + "Host: www.example.org\r\n" |
| + "Connection: keep-alive\r\n" |
| + "Authorization: auth_token\r\n\r\n"), |
| + }; |
| + |
| + MockRead data_reads3[] = { |
| + MockRead("HTTP/1.1 200 OK\r\n" |
| + "Content-Length: 5\r\n" |
| + "Content-Type: text/plain\r\n" |
| + "Connection: keep-alive\r\n\r\n" |
| + "Hello"), |
| + }; |
| + |
| + StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), |
| + data_writes1, arraysize(data_writes1)); |
| + session_deps_.socket_factory->AddSocketDataProvider(&data1); |
| + |
| + StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), |
| + data_writes2, arraysize(data_writes2)); |
| + session_deps_.socket_factory->AddSocketDataProvider(&data2); |
| + |
| + StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3), |
| + data_writes3, arraysize(data_writes3)); |
| + session_deps_.socket_factory->AddSocketDataProvider(&data3); |
| + |
| + std::unique_ptr<HttpNetworkTransaction> trans( |
| + new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); |
| + |
| + TestCompletionCallback callback; |
| + int rv = trans->Start(&request, callback.callback(), NetLogWithSource()); |
| + EXPECT_THAT(callback.GetResult(rv), IsOk()); |
| + |
| + const HttpResponseInfo* response = trans->GetResponseInfo(); |
| + ASSERT_TRUE(response); |
| + ASSERT_TRUE(response->headers); |
| + EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); |
| + |
| + // The following three tests assert that an authentication challenge was |
| + // received and that the stack is ready to respond to the challenge using |
| + // ambient credentials. |
| + EXPECT_EQ(401, response->headers->response_code()); |
| + EXPECT_TRUE(trans->IsReadyToRestartForAuth()); |
| + EXPECT_FALSE(response->auth_challenge); |
| + |
| + rv = trans->RestartWithAuth(AuthCredentials(), callback.callback()); |
| + EXPECT_THAT(callback.GetResult(rv), IsOk()); |
| + response = trans->GetResponseInfo(); |
| + ASSERT_TRUE(response); |
| + ASSERT_TRUE(response->headers); |
| + |
| + // The following three tests assert that an authentication challenge was |
| + // received and that the stack needs explicit credentials before it is ready |
| + // to respond to the challenge. |
| + EXPECT_EQ(401, response->headers->response_code()); |
| + EXPECT_FALSE(trans->IsReadyToRestartForAuth()); |
| + EXPECT_TRUE(response->auth_challenge); |
| + |
| + rv = trans->RestartWithAuth(AuthCredentials(), callback.callback()); |
| + EXPECT_THAT(callback.GetResult(rv), IsOk()); |
| + response = trans->GetResponseInfo(); |
| + ASSERT_TRUE(response); |
| + ASSERT_TRUE(response->headers); |
| + EXPECT_EQ(200, response->headers->response_code()); |
| + |
| + trans.reset(); |
| + session->CloseAllConnections(); |
| +} |
| + |
| // Test the load timing for HTTPS requests with an HTTP proxy. |
| TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) { |
| HttpRequestInfo request1; |
| @@ -11395,7 +11527,7 @@ TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) { |
| int server_auth_rv; |
| int num_auth_rounds; |
| int first_ssl_round; |
| - TestRound rounds[3]; |
| + TestRound rounds[4]; |
| } test_configs[] = { |
| // Non-authenticating HTTP server with a direct connection. |
| {NULL, |
| @@ -11426,8 +11558,25 @@ TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) { |
| ERR_INVALID_AUTH_CREDENTIALS, |
| 2, |
| kNoSSL, |
| - {TestRound(kGet, kServerChallenge, OK), |
| - TestRound(kGetAuth, kFailure, ERR_INVALID_AUTH_CREDENTIALS)}}, |
| + {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}}, |
|
mmenke
2016/10/10 21:06:09
Should we still have a test that hard fails here?
mmenke
2016/10/10 21:06:09
More typically, we'd see another TestRound(kGet, k
asanka
2016/10/11 19:47:26
The test fixture will need some minor tweaking, bu
|
| + {NULL, |
| + AUTH_NONE, |
| + OK, |
| + kServer, |
| + AUTH_SYNC, |
| + ERR_UNSUPPORTED_AUTH_SCHEME, |
| + 2, |
| + kNoSSL, |
| + {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}}, |
|
mmenke
2016/10/10 21:06:10
More typically, we'd see another TestRound(kGet, k
asanka
2016/10/11 19:47:26
Added another round. The new test round verifies t
|
| + {NULL, |
| + AUTH_NONE, |
| + OK, |
| + kServer, |
| + AUTH_SYNC, |
| + ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS, |
| + 2, |
| + kNoSSL, |
| + {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}}, |
| {NULL, |
| AUTH_NONE, |
| OK, |
| @@ -11446,8 +11595,7 @@ TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) { |
| ERR_INVALID_AUTH_CREDENTIALS, |
| 2, |
| kNoSSL, |
| - {TestRound(kGet, kServerChallenge, OK), |
| - TestRound(kGetAuth, kFailure, ERR_INVALID_AUTH_CREDENTIALS)}}, |
| + {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}}, |
| // Non-authenticating HTTP server through a non-authenticating proxy. |
| {kProxy, |
| AUTH_NONE, |
| @@ -11478,8 +11626,7 @@ TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) { |
| 2, |
| kNoSSL, |
| {TestRound(kGetProxy, kServerChallenge, OK), |
| - TestRound(kGetAuthThroughProxy, kFailure, |
| - ERR_INVALID_AUTH_CREDENTIALS)}}, |
| + TestRound(kGetProxy, kSuccess, OK)}}, |
| {kProxy, |
| AUTH_NONE, |
| OK, |
| @@ -11499,8 +11646,7 @@ TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) { |
| 2, |
| kNoSSL, |
| {TestRound(kGetProxy, kServerChallenge, OK), |
| - TestRound(kGetAuthThroughProxy, kFailure, |
| - ERR_INVALID_AUTH_CREDENTIALS)}}, |
| + TestRound(kGetProxy, kSuccess, OK)}}, |
| // Non-authenticating HTTP server through an authenticating proxy. |
| {kProxy, |
| AUTH_SYNC, |
| @@ -11521,7 +11667,7 @@ TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) { |
| 2, |
| kNoSSL, |
| {TestRound(kGetProxy, kProxyChallenge, OK), |
| - TestRound(kGetProxyAuth, kFailure, ERR_INVALID_AUTH_CREDENTIALS)}}, |
| + TestRound(kGetProxy, kSuccess, OK)}}, |
| {kProxy, |
| AUTH_ASYNC, |
| OK, |
| @@ -11541,7 +11687,7 @@ TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) { |
| 2, |
| kNoSSL, |
| {TestRound(kGetProxy, kProxyChallenge, OK), |
| - TestRound(kGetProxyAuth, kFailure, ERR_INVALID_AUTH_CREDENTIALS)}}, |
| + TestRound(kGetProxy, kSuccess, OK)}}, |
| // Authenticating HTTP server through an authenticating proxy. |
| {kProxy, |
| AUTH_SYNC, |
| @@ -11564,8 +11710,7 @@ TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) { |
| kNoSSL, |
| {TestRound(kGetProxy, kProxyChallenge, OK), |
| TestRound(kGetProxyAuth, kServerChallenge, OK), |
| - TestRound(kGetAuthWithProxyAuth, kFailure, |
| - ERR_INVALID_AUTH_CREDENTIALS)}}, |
| + TestRound(kGetProxyAuth, kSuccess, OK)}}, |
| {kProxy, |
| AUTH_ASYNC, |
| OK, |
| @@ -11587,8 +11732,7 @@ TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) { |
| kNoSSL, |
| {TestRound(kGetProxy, kProxyChallenge, OK), |
| TestRound(kGetProxyAuth, kServerChallenge, OK), |
| - TestRound(kGetAuthWithProxyAuth, kFailure, |
| - ERR_INVALID_AUTH_CREDENTIALS)}}, |
| + TestRound(kGetProxyAuth, kSuccess, OK)}}, |
| {kProxy, |
| AUTH_SYNC, |
| OK, |
| @@ -11610,8 +11754,7 @@ TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) { |
| kNoSSL, |
| {TestRound(kGetProxy, kProxyChallenge, OK), |
| TestRound(kGetProxyAuth, kServerChallenge, OK), |
| - TestRound(kGetAuthWithProxyAuth, kFailure, |
| - ERR_INVALID_AUTH_CREDENTIALS)}}, |
| + TestRound(kGetProxyAuth, kSuccess, OK)}}, |
| {kProxy, |
| AUTH_ASYNC, |
| OK, |
| @@ -11633,8 +11776,7 @@ TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) { |
| kNoSSL, |
| {TestRound(kGetProxy, kProxyChallenge, OK), |
| TestRound(kGetProxyAuth, kServerChallenge, OK), |
| - TestRound(kGetAuthWithProxyAuth, kFailure, |
| - ERR_INVALID_AUTH_CREDENTIALS)}}, |
| + TestRound(kGetProxyAuth, kSuccess, OK)}}, |
| // Non-authenticating HTTPS server with a direct connection. |
| {NULL, |
| AUTH_NONE, |
| @@ -11664,8 +11806,7 @@ TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) { |
| ERR_INVALID_AUTH_CREDENTIALS, |
| 2, |
| 0, |
| - {TestRound(kGet, kServerChallenge, OK), |
| - TestRound(kGetAuth, kFailure, ERR_INVALID_AUTH_CREDENTIALS)}}, |
| + {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}}, |
| {NULL, |
| AUTH_NONE, |
| OK, |
| @@ -11684,8 +11825,7 @@ TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) { |
| ERR_INVALID_AUTH_CREDENTIALS, |
| 2, |
| 0, |
| - {TestRound(kGet, kServerChallenge, OK), |
| - TestRound(kGetAuth, kFailure, ERR_INVALID_AUTH_CREDENTIALS)}}, |
| + {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}}, |
| // Non-authenticating HTTPS server with a non-authenticating proxy. |
| {kProxy, |
| AUTH_NONE, |
| @@ -11716,7 +11856,7 @@ TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) { |
| 2, |
| 0, |
| {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge), |
| - TestRound(kGetAuth, kFailure, ERR_INVALID_AUTH_CREDENTIALS)}}, |
| + TestRound(kGet, kSuccess, OK)}}, |
| {kProxy, |
| AUTH_NONE, |
| OK, |
| @@ -11736,7 +11876,7 @@ TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) { |
| 2, |
| 0, |
| {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge), |
| - TestRound(kGetAuth, kFailure, ERR_INVALID_AUTH_CREDENTIALS)}}, |
| + TestRound(kGet, kSuccess, OK)}}, |
| // Non-Authenticating HTTPS server through an authenticating proxy. |
| {kProxy, |
| AUTH_SYNC, |
| @@ -11757,7 +11897,27 @@ TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) { |
| 2, |
| kNoSSL, |
| {TestRound(kConnect, kProxyChallenge, OK), |
| - TestRound(kConnectProxyAuth, kFailure, ERR_INVALID_AUTH_CREDENTIALS)}}, |
| + TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}}, |
| + {kProxy, |
| + AUTH_SYNC, |
| + ERR_UNSUPPORTED_AUTH_SCHEME, |
| + kSecureServer, |
| + AUTH_NONE, |
| + OK, |
| + 2, |
| + kNoSSL, |
| + {TestRound(kConnect, kProxyChallenge, OK), |
| + TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}}, |
| + {kProxy, |
| + AUTH_SYNC, |
| + ERR_UNEXPECTED, |
| + kSecureServer, |
| + AUTH_NONE, |
| + OK, |
| + 2, |
| + kNoSSL, |
| + {TestRound(kConnect, kProxyChallenge, OK), |
| + TestRound(kConnect, kProxyConnected, ERR_UNEXPECTED)}}, |
| {kProxy, |
| AUTH_ASYNC, |
| OK, |
| @@ -11777,7 +11937,7 @@ TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) { |
| 2, |
| kNoSSL, |
| {TestRound(kConnect, kProxyChallenge, OK), |
| - TestRound(kConnectProxyAuth, kFailure, ERR_INVALID_AUTH_CREDENTIALS)}}, |
| + TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}}, |
| // Authenticating HTTPS server through an authenticating proxy. |
| {kProxy, |
| AUTH_SYNC, |
| @@ -11802,7 +11962,7 @@ TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) { |
| {TestRound(kConnect, kProxyChallenge, OK), |
| TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, |
| &kServerChallenge), |
| - TestRound(kGetAuth, kFailure, ERR_INVALID_AUTH_CREDENTIALS)}}, |
| + TestRound(kGet, kSuccess, OK)}}, |
| {kProxy, |
| AUTH_ASYNC, |
| OK, |
| @@ -11826,7 +11986,7 @@ TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) { |
| {TestRound(kConnect, kProxyChallenge, OK), |
| TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, |
| &kServerChallenge), |
| - TestRound(kGetAuth, kFailure, ERR_INVALID_AUTH_CREDENTIALS)}}, |
| + TestRound(kGet, kSuccess, OK)}}, |
| {kProxy, |
| AUTH_SYNC, |
| OK, |
| @@ -11850,7 +12010,7 @@ TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) { |
| {TestRound(kConnect, kProxyChallenge, OK), |
| TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, |
| &kServerChallenge), |
| - TestRound(kGetAuth, kFailure, ERR_INVALID_AUTH_CREDENTIALS)}}, |
| + TestRound(kGet, kSuccess, OK)}}, |
| {kProxy, |
| AUTH_ASYNC, |
| OK, |
| @@ -11874,10 +12034,11 @@ TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) { |
| {TestRound(kConnect, kProxyChallenge, OK), |
| TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, |
| &kServerChallenge), |
| - TestRound(kGetAuth, kFailure, ERR_INVALID_AUTH_CREDENTIALS)}}, |
| + TestRound(kGet, kSuccess, OK)}}, |
| }; |
| for (size_t i = 0; i < arraysize(test_configs); ++i) { |
| + SCOPED_TRACE(::testing::Message() << "Test config " << i); |
| HttpAuthHandlerMock::Factory* auth_factory( |
| new HttpAuthHandlerMock::Factory()); |
| session_deps_.http_auth_handler_factory.reset(auth_factory); |