Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2016 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 "net/http/http_stream_factory_impl_job_controller.h" | |
| 6 | |
| 7 #include <memory> | |
| 8 | |
| 9 #include "net/http/http_basic_stream.h" | |
| 10 #include "net/http/http_stream_factory_impl_job.h" | |
| 11 #include "net/http/http_stream_factory_impl_request.h" | |
| 12 #include "net/http/http_stream_factory_test_util.h" | |
| 13 #include "net/proxy/proxy_info.h" | |
| 14 #include "net/proxy/proxy_service.h" | |
| 15 #include "net/spdy/spdy_test_util_common.h" | |
| 16 #include "net/ssl/ssl_failure_state.h" | |
| 17 #include "testing/gtest/include/gtest/gtest.h" | |
| 18 | |
| 19 using ::testing::_; | |
| 20 | |
| 21 namespace net { | |
| 22 | |
| 23 class HttpStreamFactoryImplJobControllerTest | |
| 24 : public ::testing::Test, | |
| 25 public ::testing::WithParamInterface<NextProto> { | |
| 26 public: | |
| 27 HttpStreamFactoryImplJobControllerTest() | |
| 28 : job_controller_peer_( | |
| 29 new TestJobControllerPeer(GetParam(), &request_delegate_)) {} | |
|
Ryan Hamilton
2016/06/01 18:43:07
where is TestJobControllerPeer defined?
Zhongyi Shi
2016/06/02 20:49:09
Oh, it's defined in test_util.h, but I have moved
| |
| 30 | |
| 31 ~HttpStreamFactoryImplJobControllerTest() {} | |
| 32 | |
| 33 HttpStreamFactoryImpl::JobController* job_controller() { | |
| 34 return job_controller_peer_->job_controller(); | |
| 35 } | |
| 36 | |
| 37 std::unique_ptr<TestJobControllerPeer> job_controller_peer_; | |
|
Ryan Hamilton
2016/06/01 18:43:07
Instead of a unique_ptr, can you just make this a
Zhongyi Shi
2016/06/02 20:49:08
Done.
| |
| 38 TestHttpStreamRequestDelegate request_delegate_; | |
| 39 }; | |
| 40 | |
| 41 INSTANTIATE_TEST_CASE_P(NextProto, | |
| 42 HttpStreamFactoryImplJobControllerTest, | |
| 43 testing::Values(kProtoSPDY31, kProtoHTTP2)); | |
| 44 | |
| 45 TEST_P(HttpStreamFactoryImplJobControllerTest, | |
| 46 OnStreamFailedWithNoAlternativeJob) { | |
| 47 HttpRequestInfo request_info; | |
| 48 request_info.method = "GET"; | |
| 49 request_info.url = GURL("http://www.google.com"); | |
| 50 job_controller_peer_->CreateRequest(request_info); | |
| 51 | |
| 52 HostPortPair server = HostPortPair::FromURL(request_info.url); | |
| 53 GURL original_url = | |
| 54 job_controller_peer_->ApplyHostMappingRules(request_info.url, &server); | |
| 55 | |
| 56 TestHttpStreamFactoryImplJob* main_job = new TestHttpStreamFactoryImplJob( | |
| 57 job_controller(), HttpStreamFactoryImpl::MAIN, | |
| 58 job_controller_peer_->session(), request_info, DEFAULT_PRIORITY, | |
| 59 SSLConfig(), SSLConfig(), server, original_url, nullptr); | |
| 60 job_controller_peer_->SetMainJob(main_job); | |
|
Ryan Hamilton
2016/06/01 18:43:07
It would be better if we didn't have to use a peer
Zhongyi Shi
2016/06/02 20:49:09
I added a JobFactory to impl and pass that in JobC
| |
| 61 | |
| 62 // There's no bound job yet, and no other alternative job. Thus when stream | |
| 63 // failed, it should call BindJob to bind this Job. And then notify Request | |
| 64 // of the stream failure. | |
|
Ryan Hamilton
2016/06/01 18:43:07
I think you can remove references to binding the j
Zhongyi Shi
2016/06/02 20:49:08
All the references to bound_job and job_bound are
| |
| 65 EXPECT_CALL(request_delegate_, | |
| 66 OnStreamFailed(ERR_FAILED, _, SSL_FAILURE_NONE)) | |
| 67 .Times(1); | |
| 68 | |
| 69 job_controller_peer_->OnStreamFailed(main_job, ERR_FAILED, SSLConfig(), | |
| 70 SSL_FAILURE_NONE); | |
| 71 EXPECT_TRUE(job_controller_peer_->job_bound()); | |
| 72 EXPECT_EQ(job_controller_peer_->bound_job(), main_job); | |
| 73 } | |
| 74 | |
| 75 TEST_P(HttpStreamFactoryImplJobControllerTest, | |
| 76 OnStreamReadyWithNoAlternativeJob) { | |
| 77 HttpRequestInfo request_info; | |
| 78 request_info.method = "GET"; | |
| 79 request_info.url = GURL("http://www.google.com"); | |
| 80 job_controller_peer_->CreateRequest(request_info); | |
| 81 | |
| 82 HostPortPair server = HostPortPair::FromURL(request_info.url); | |
| 83 GURL original_url = | |
| 84 job_controller_peer_->ApplyHostMappingRules(request_info.url, &server); | |
| 85 | |
| 86 TestHttpStreamFactoryImplJob* main_job = new TestHttpStreamFactoryImplJob( | |
| 87 job_controller(), HttpStreamFactoryImpl::MAIN, | |
| 88 job_controller_peer_->session(), request_info, DEFAULT_PRIORITY, | |
| 89 SSLConfig(), SSLConfig(), server, original_url, nullptr); | |
| 90 job_controller_peer_->SetMainJob(main_job); | |
| 91 | |
| 92 // There's no bound job yet, and no other alternative job. Thus when stream | |
| 93 // is ready, it should call BindJob to bind this Job. And then notify Request. | |
| 94 HttpStream* http_stream = | |
| 95 new HttpBasicStream(new ClientSocketHandle(), false); | |
| 96 main_job->SetStream(http_stream); | |
| 97 | |
| 98 EXPECT_CALL(request_delegate_, OnStreamReady(_, _, _)).Times(1); | |
| 99 job_controller_peer_->OnStreamReady(main_job, SSLConfig(), ProxyInfo()); | |
| 100 EXPECT_TRUE(job_controller_peer_->job_bound()); | |
| 101 EXPECT_EQ(job_controller_peer_->bound_job(), main_job); | |
| 102 } | |
| 103 | |
| 104 // Test we cancel Job(s) correctly when the Request is explicitly canceled | |
| 105 // before any Job is bound to Request. | |
| 106 TEST_P(HttpStreamFactoryImplJobControllerTest, CancelJobsBeforeBinding) { | |
| 107 HttpRequestInfo request_info; | |
| 108 request_info.method = "GET"; | |
| 109 request_info.url = GURL("http://www.google.com"); | |
| 110 | |
| 111 job_controller_peer_->CreateRequest(request_info); | |
| 112 | |
| 113 HostPortPair server = HostPortPair::FromURL(request_info.url); | |
| 114 GURL original_url = | |
| 115 job_controller_peer_->ApplyHostMappingRules(request_info.url, &server); | |
| 116 | |
| 117 TestHttpStreamFactoryImplJob* main_job = new TestHttpStreamFactoryImplJob( | |
| 118 job_controller(), HttpStreamFactoryImpl::MAIN, | |
| 119 job_controller_peer_->session(), request_info, DEFAULT_PRIORITY, | |
| 120 SSLConfig(), SSLConfig(), server, original_url, nullptr); | |
| 121 job_controller_peer_->SetMainJob(main_job); | |
| 122 | |
| 123 AlternativeService alternative_service(net::NPN_HTTP_2, server); | |
| 124 TestHttpStreamFactoryImplJob* alternative_job = | |
| 125 new TestHttpStreamFactoryImplJob( | |
| 126 job_controller(), HttpStreamFactoryImpl::ALTERNATIVE, | |
| 127 job_controller_peer_->session(), request_info, DEFAULT_PRIORITY, | |
| 128 SSLConfig(), SSLConfig(), server, original_url, alternative_service, | |
| 129 nullptr); | |
| 130 job_controller_peer_->SetAlternativeJob(alternative_job); | |
| 131 | |
| 132 EXPECT_FALSE(job_controller_peer_->job_bound()); | |
| 133 // Reset the Request will cancel all the Job(s) since there's no Job bound | |
| 134 // yet and JobController will notify the factory to delete the it upon | |
| 135 // upon completion. | |
| 136 job_controller_peer_->CancelRequest(); | |
| 137 EXPECT_TRUE(job_controller_peer_->IsJobControllerDeleted()); | |
| 138 } | |
| 139 | |
| 140 TEST_P(HttpStreamFactoryImplJobControllerTest, OnStreamFailedForBothJobs) { | |
| 141 HttpRequestInfo request_info; | |
| 142 request_info.method = "GET"; | |
| 143 request_info.url = GURL("http://www.google.com"); | |
| 144 | |
| 145 job_controller_peer_->CreateRequest(request_info); | |
| 146 | |
| 147 HostPortPair server = HostPortPair::FromURL(request_info.url); | |
| 148 GURL original_url = | |
| 149 job_controller_peer_->ApplyHostMappingRules(request_info.url, &server); | |
| 150 | |
| 151 TestHttpStreamFactoryImplJob* main_job = new TestHttpStreamFactoryImplJob( | |
| 152 job_controller(), HttpStreamFactoryImpl::MAIN, | |
| 153 job_controller_peer_->session(), request_info, DEFAULT_PRIORITY, | |
| 154 SSLConfig(), SSLConfig(), server, original_url, nullptr); | |
| 155 job_controller_peer_->SetMainJob(main_job); | |
| 156 | |
| 157 AlternativeService alternative_service(net::NPN_HTTP_2, server); | |
| 158 TestHttpStreamFactoryImplJob* alternative_job = | |
| 159 new TestHttpStreamFactoryImplJob( | |
| 160 job_controller(), HttpStreamFactoryImpl::ALTERNATIVE, | |
| 161 job_controller_peer_->session(), request_info, DEFAULT_PRIORITY, | |
| 162 SSLConfig(), SSLConfig(), server, original_url, alternative_service, | |
| 163 nullptr); | |
| 164 job_controller_peer_->SetAlternativeJob(alternative_job); | |
| 165 | |
| 166 // We have |main_job| with unknown status when |alternative_job| is failed | |
| 167 // thus should not bind Job or notify Request of |alternative_job|'s status. | |
| 168 // But should notify |main_job| to mark |alternative_job| failed. | |
| 169 EXPECT_CALL(request_delegate_, OnStreamFailed(_, _, _)).Times(0); | |
| 170 EXPECT_CALL(*main_job, MarkOtherJobComplete(_)).Times(1); | |
| 171 job_controller_peer_->OnStreamFailed(alternative_job, ERR_FAILED, SSLConfig(), | |
| 172 SSL_FAILURE_NONE); | |
| 173 EXPECT_TRUE(!job_controller_peer_->job_bound()); | |
| 174 EXPECT_TRUE(!job_controller_peer_->bound_job()); | |
| 175 EXPECT_TRUE(!job_controller_peer_->alternative_job()); | |
| 176 EXPECT_TRUE(job_controller_peer_->main_job()); | |
| 177 | |
| 178 // The failure of second Job should be reported to Request as there's no more | |
| 179 // pending Job to server the Request. | |
| 180 EXPECT_CALL(request_delegate_, OnStreamFailed(_, _, _)).Times(1); | |
| 181 job_controller_peer_->OnStreamFailed(main_job, ERR_FAILED, SSLConfig(), | |
| 182 SSL_FAILURE_NONE); | |
|
Ryan Hamilton
2016/06/01 18:43:07
nice!
| |
| 183 } | |
| 184 | |
| 185 TEST_P(HttpStreamFactoryImplJobControllerTest, | |
| 186 SecondJobFailsAfterFirstJobSucceeds) { | |
| 187 HttpRequestInfo request_info; | |
| 188 request_info.method = "GET"; | |
| 189 request_info.url = GURL("http://www.google.com"); | |
| 190 job_controller_peer_->CreateRequest(request_info); | |
| 191 | |
| 192 HostPortPair server = HostPortPair::FromURL(request_info.url); | |
| 193 GURL original_url = | |
| 194 job_controller_peer_->ApplyHostMappingRules(request_info.url, &server); | |
| 195 | |
| 196 TestHttpStreamFactoryImplJob* main_job = new TestHttpStreamFactoryImplJob( | |
| 197 job_controller(), HttpStreamFactoryImpl::MAIN, | |
| 198 job_controller_peer_->session(), request_info, DEFAULT_PRIORITY, | |
| 199 SSLConfig(), SSLConfig(), server, original_url, nullptr); | |
| 200 job_controller_peer_->SetMainJob(main_job); | |
| 201 | |
| 202 AlternativeService alternative_service(net::NPN_HTTP_2, server); | |
| 203 TestHttpStreamFactoryImplJob* alternative_job = | |
| 204 new TestHttpStreamFactoryImplJob( | |
| 205 job_controller(), HttpStreamFactoryImpl::ALTERNATIVE, | |
| 206 job_controller_peer_->session(), request_info, DEFAULT_PRIORITY, | |
| 207 SSLConfig(), SSLConfig(), server, original_url, alternative_service, | |
| 208 nullptr); | |
| 209 job_controller_peer_->SetAlternativeJob(alternative_job); | |
| 210 | |
| 211 // Main job succeeds and gets bound to Request and it should report status | |
| 212 // to Request. The alternative job will mark the main job complete and gets | |
| 213 // orphaned. | |
| 214 HttpStream* http_stream = | |
| 215 new HttpBasicStream(new ClientSocketHandle(), false); | |
| 216 main_job->SetStream(http_stream); | |
| 217 | |
| 218 EXPECT_CALL(request_delegate_, OnStreamReady(_, _, _)).Times(1); | |
| 219 EXPECT_CALL(*alternative_job, MarkOtherJobComplete(_)).Times(1); | |
| 220 job_controller_peer_->OnStreamReady(main_job, SSLConfig(), ProxyInfo()); | |
| 221 EXPECT_TRUE(job_controller_peer_->job_bound()); | |
| 222 EXPECT_EQ(job_controller_peer_->bound_job(), main_job); | |
| 223 | |
| 224 // Reset the request as it's been successfully served. | |
| 225 job_controller_peer_->CancelRequest(); | |
| 226 EXPECT_TRUE(job_controller_peer_->job_bound()); | |
| 227 EXPECT_EQ(job_controller_peer_->bound_job(), nullptr); | |
| 228 | |
| 229 // Though bound_job_ is cleared, but JobController knows a job has ever been | |
| 230 // bound. JobController shouldn't report the status of second job as request | |
| 231 // is gone served. | |
| 232 job_controller_peer_->OnStreamFailed(alternative_job, ERR_FAILED, SSLConfig(), | |
| 233 SSL_FAILURE_NONE); | |
| 234 EXPECT_TRUE(job_controller_peer_->IsJobControllerDeleted()); | |
| 235 delete http_stream; | |
| 236 } | |
| 237 | |
| 238 TEST_P(HttpStreamFactoryImplJobControllerTest, | |
| 239 SecondJobSucceedsAfterFirstJobFailed) { | |
| 240 HttpRequestInfo request_info; | |
| 241 request_info.method = "GET"; | |
| 242 request_info.url = GURL("http://www.google.com"); | |
| 243 job_controller_peer_->CreateRequest(request_info); | |
| 244 | |
| 245 HostPortPair server = HostPortPair::FromURL(request_info.url); | |
| 246 GURL original_url = | |
| 247 job_controller_peer_->ApplyHostMappingRules(request_info.url, &server); | |
| 248 | |
| 249 TestHttpStreamFactoryImplJob* main_job = new TestHttpStreamFactoryImplJob( | |
| 250 job_controller(), HttpStreamFactoryImpl::MAIN, | |
| 251 job_controller_peer_->session(), request_info, DEFAULT_PRIORITY, | |
| 252 SSLConfig(), SSLConfig(), server, original_url, nullptr); | |
| 253 job_controller_peer_->SetMainJob(main_job); | |
| 254 | |
| 255 AlternativeService alternative_service(net::NPN_HTTP_2, server); | |
| 256 TestHttpStreamFactoryImplJob* alternative_job = | |
| 257 new TestHttpStreamFactoryImplJob( | |
| 258 job_controller(), HttpStreamFactoryImpl::ALTERNATIVE, | |
| 259 job_controller_peer_->session(), request_info, DEFAULT_PRIORITY, | |
| 260 SSLConfig(), SSLConfig(), server, original_url, alternative_service, | |
| 261 nullptr); | |
| 262 job_controller_peer_->SetAlternativeJob(alternative_job); | |
| 263 | |
| 264 // |main_job| fails but should not get bound and report status to Request. | |
| 265 // The alternative job will mark the main job complete and gets orphaned. | |
| 266 EXPECT_CALL(request_delegate_, OnStreamFailed(_, _, _)).Times(0); | |
| 267 EXPECT_CALL(*alternative_job, MarkOtherJobComplete(_)).Times(1); | |
| 268 | |
| 269 job_controller_peer_->OnStreamFailed(main_job, ERR_FAILED, SSLConfig(), | |
| 270 SSL_FAILURE_NONE); | |
| 271 EXPECT_FALSE(job_controller_peer_->job_bound()); | |
| 272 EXPECT_EQ(job_controller_peer_->bound_job(), nullptr); | |
| 273 | |
| 274 // |alternative_job| succeeds and should report status to Request. | |
| 275 HttpStream* http_stream = | |
| 276 new HttpBasicStream(new ClientSocketHandle(), false); | |
| 277 alternative_job->SetStream(http_stream); | |
| 278 | |
| 279 EXPECT_CALL(request_delegate_, OnStreamReady(_, _, _)).Times(1); | |
| 280 job_controller_peer_->OnStreamReady(alternative_job, SSLConfig(), | |
| 281 ProxyInfo()); | |
| 282 EXPECT_EQ(job_controller_peer_->bound_job(), alternative_job); | |
| 283 | |
| 284 delete http_stream; | |
| 285 } | |
| 286 | |
| 287 TEST_P(HttpStreamFactoryImplJobControllerTest, NotifyFactoryOfCompletion) { | |
| 288 HttpRequestInfo request_info; | |
| 289 request_info.method = "GET"; | |
| 290 request_info.url = GURL("http://www.google.com"); | |
| 291 HostPortPair server = HostPortPair::FromURL(request_info.url); | |
| 292 GURL original_url = | |
| 293 job_controller_peer_->ApplyHostMappingRules(request_info.url, &server); | |
| 294 | |
| 295 TestHttpStreamFactoryImplJob* main_job = new TestHttpStreamFactoryImplJob( | |
| 296 job_controller(), HttpStreamFactoryImpl::MAIN, | |
| 297 job_controller_peer_->session(), request_info, DEFAULT_PRIORITY, | |
| 298 SSLConfig(), SSLConfig(), server, original_url, nullptr); | |
| 299 job_controller_peer_->SetMainJob(main_job); | |
| 300 | |
| 301 // HttpStreamFactoryImpl shouldn't be notified to delete the JobController | |
| 302 // when there's still Job left. | |
| 303 job_controller_peer_->MaybeNotifyFactoryOfCompletion(); | |
| 304 EXPECT_FALSE(job_controller_peer_->IsJobControllerDeleted()); | |
| 305 | |
| 306 // HttpStreamFactoryImpl should be notified to delete the JobController | |
| 307 // when there's no Job as well as Request left. | |
| 308 job_controller_peer_->ClearMainJob(); | |
| 309 job_controller_peer_->MaybeNotifyFactoryOfCompletion(); | |
| 310 EXPECT_TRUE(job_controller_peer_->IsJobControllerDeleted()); | |
| 311 } | |
| 312 | |
|
Zhongyi Shi
2016/06/02 20:49:08
This test is removed as MaybeNotifyFactoryOfComple
| |
| 313 } // namespace net | |
| OLD | NEW |