OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 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 "base/bind.h" |
| 6 #include "base/lazy_instance.h" |
| 7 #include "base/memory/weak_ptr.h" |
| 8 #include "base/message_loop/message_loop.h" |
| 9 #include "base/run_loop.h" |
| 10 #include "mojo/common/message_pump_mojo.h" |
| 11 #include "mojo/public/cpp/application/application_test_base.h" |
| 12 #include "mojo/services/network/network_context.h" |
| 13 #include "mojo/services/network/url_loader_impl.h" |
| 14 #include "net/url_request/url_request_job.h" |
| 15 #include "net/url_request/url_request_job_factory_impl.h" |
| 16 #include "net/url_request/url_request_test_util.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" |
| 18 |
| 19 namespace mojo { |
| 20 namespace { |
| 21 |
| 22 class TestURLRequestJob; |
| 23 |
| 24 TestURLRequestJob* g_current_job = nullptr; |
| 25 |
| 26 template <class A> |
| 27 void PassA(A* destination, A value) { |
| 28 *destination = value.Pass(); |
| 29 } |
| 30 |
| 31 // Extends URLLoaderImpl to allow to get a weak pointer and check if it has been |
| 32 // correctly deleted. |
| 33 class TestedURLLoaderImpl : public URLLoaderImpl, |
| 34 public base::SupportsWeakPtr<TestedURLLoaderImpl> { |
| 35 public: |
| 36 TestedURLLoaderImpl(NetworkContext* context, |
| 37 InterfaceRequest<URLLoader> request) |
| 38 : URLLoaderImpl(context, request.Pass()) {} |
| 39 }; |
| 40 |
| 41 class TestURLRequestJob : public net::URLRequestJob { |
| 42 public: |
| 43 enum Status { CREATED, STARTED, READING, COMPLETED }; |
| 44 |
| 45 TestURLRequestJob(net::URLRequest* request, |
| 46 net::NetworkDelegate* network_delegate) |
| 47 : net::URLRequestJob(request, network_delegate), |
| 48 status_(CREATED), |
| 49 buf_size_(0) { |
| 50 CHECK(!g_current_job); |
| 51 g_current_job = this; |
| 52 } |
| 53 |
| 54 Status status() { return status_; } |
| 55 |
| 56 int buf_size() { return buf_size_; } |
| 57 |
| 58 void Start() override { status_ = STARTED; } |
| 59 |
| 60 bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override { |
| 61 status_ = READING; |
| 62 buf_size_ = buf_size; |
| 63 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); |
| 64 return false; |
| 65 } |
| 66 |
| 67 void NotifyHeadersComplete() { net::URLRequestJob::NotifyHeadersComplete(); } |
| 68 |
| 69 void NotifyReadComplete(int bytes_read) { |
| 70 if (bytes_read < 0) { |
| 71 status_ = COMPLETED; |
| 72 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, 0)); |
| 73 net::URLRequestJob::NotifyReadComplete(0); |
| 74 } else if (bytes_read == 0) { |
| 75 status_ = COMPLETED; |
| 76 NotifyDone(net::URLRequestStatus()); |
| 77 net::URLRequestJob::NotifyReadComplete(bytes_read); |
| 78 } else { |
| 79 status_ = STARTED; |
| 80 SetStatus(net::URLRequestStatus()); |
| 81 net::URLRequestJob::NotifyReadComplete(bytes_read); |
| 82 } |
| 83 } |
| 84 |
| 85 private: |
| 86 ~TestURLRequestJob() override { |
| 87 CHECK(g_current_job == this); |
| 88 g_current_job = nullptr; |
| 89 } |
| 90 |
| 91 Status status_; |
| 92 int buf_size_; |
| 93 }; |
| 94 |
| 95 class TestProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler { |
| 96 public: |
| 97 net::URLRequestJob* MaybeCreateJob( |
| 98 net::URLRequest* request, |
| 99 net::NetworkDelegate* network_delegate) const override { |
| 100 return new TestURLRequestJob(request, network_delegate); |
| 101 } |
| 102 |
| 103 private: |
| 104 ~TestProtocolHandler() override {} |
| 105 }; |
| 106 |
| 107 class UrlLoaderImplTest : public test::ApplicationTestBase { |
| 108 public: |
| 109 UrlLoaderImplTest() : message_loop_(common::MessagePumpMojo::Create()) {} |
| 110 |
| 111 protected: |
| 112 bool ShouldCreateDefaultRunLoop() override { |
| 113 return false; |
| 114 } |
| 115 |
| 116 void SetUp() { |
| 117 ApplicationTestBase::SetUp(); |
| 118 |
| 119 scoped_ptr<net::TestURLRequestContext> url_request_context( |
| 120 new net::TestURLRequestContext(true)); |
| 121 ASSERT_TRUE(url_request_job_factory_.SetProtocolHandler( |
| 122 "http", new TestProtocolHandler())); |
| 123 url_request_context->set_job_factory(&url_request_job_factory_); |
| 124 url_request_context->Init(); |
| 125 network_context_.reset(new NetworkContext(url_request_context.Pass())); |
| 126 MessagePipe pipe; |
| 127 url_loader_proxy_ = MakeProxy<URLLoader>(pipe.handle0.Pass()); |
| 128 url_loader_ = |
| 129 (new TestedURLLoaderImpl(network_context_.get(), |
| 130 MakeRequest<URLLoader>(pipe.handle1.Pass()))) |
| 131 ->AsWeakPtr(); |
| 132 EXPECT_TRUE(url_loader_); |
| 133 } |
| 134 |
| 135 base::MessageLoop message_loop_; |
| 136 net::TestJobInterceptor* job_interceptor_; |
| 137 net::URLRequestJobFactoryImpl url_request_job_factory_; |
| 138 scoped_ptr<NetworkContext> network_context_; |
| 139 URLLoaderPtr url_loader_proxy_; |
| 140 base::WeakPtr<TestedURLLoaderImpl> url_loader_; |
| 141 }; |
| 142 |
| 143 TEST_F(UrlLoaderImplTest, ClosedBeforeAnyCall) { |
| 144 url_loader_proxy_.reset(); |
| 145 base::RunLoop().RunUntilIdle(); |
| 146 |
| 147 EXPECT_FALSE(url_loader_); |
| 148 } |
| 149 |
| 150 TEST_F(UrlLoaderImplTest, ClosedWhileWaitingOnTheNetwork) { |
| 151 URLRequestPtr request(URLRequest::New()); |
| 152 request->url = "http://example.com"; |
| 153 |
| 154 URLResponsePtr response; |
| 155 url_loader_proxy_->Start(request.Pass(), |
| 156 base::Bind(&PassA<URLResponsePtr>, &response)); |
| 157 base::RunLoop().RunUntilIdle(); |
| 158 |
| 159 EXPECT_TRUE(url_loader_); |
| 160 EXPECT_FALSE(response); |
| 161 ASSERT_TRUE(g_current_job); |
| 162 |
| 163 g_current_job->NotifyHeadersComplete(); |
| 164 base::RunLoop().RunUntilIdle(); |
| 165 |
| 166 EXPECT_TRUE(url_loader_); |
| 167 EXPECT_TRUE(response); |
| 168 EXPECT_EQ(TestURLRequestJob::READING, g_current_job->status()); |
| 169 |
| 170 url_loader_proxy_.reset(); |
| 171 base::RunLoop().RunUntilIdle(); |
| 172 |
| 173 EXPECT_TRUE(url_loader_); |
| 174 |
| 175 response.reset(); |
| 176 base::RunLoop().RunUntilIdle(); |
| 177 |
| 178 EXPECT_FALSE(url_loader_); |
| 179 } |
| 180 |
| 181 TEST_F(UrlLoaderImplTest, ClosedWhileWaitingOnThePipeToBeWriteable) { |
| 182 URLRequestPtr request(URLRequest::New()); |
| 183 request->url = "http://example.com"; |
| 184 |
| 185 URLResponsePtr response; |
| 186 url_loader_proxy_->Start(request.Pass(), |
| 187 base::Bind(&PassA<URLResponsePtr>, &response)); |
| 188 base::RunLoop().RunUntilIdle(); |
| 189 |
| 190 EXPECT_TRUE(url_loader_); |
| 191 EXPECT_FALSE(response); |
| 192 ASSERT_TRUE(g_current_job); |
| 193 |
| 194 g_current_job->NotifyHeadersComplete(); |
| 195 base::RunLoop().RunUntilIdle(); |
| 196 |
| 197 EXPECT_TRUE(url_loader_); |
| 198 EXPECT_TRUE(response); |
| 199 EXPECT_EQ(TestURLRequestJob::READING, g_current_job->status()); |
| 200 |
| 201 while (g_current_job->status() == TestURLRequestJob::READING) { |
| 202 g_current_job->NotifyReadComplete(g_current_job->buf_size()); |
| 203 base::RunLoop().RunUntilIdle(); |
| 204 } |
| 205 |
| 206 EXPECT_EQ(TestURLRequestJob::STARTED, g_current_job->status()); |
| 207 |
| 208 url_loader_proxy_.reset(); |
| 209 base::RunLoop().RunUntilIdle(); |
| 210 |
| 211 EXPECT_TRUE(url_loader_); |
| 212 |
| 213 response.reset(); |
| 214 base::RunLoop().RunUntilIdle(); |
| 215 |
| 216 EXPECT_FALSE(url_loader_); |
| 217 } |
| 218 |
| 219 TEST_F(UrlLoaderImplTest, RequestCompleted) { |
| 220 URLRequestPtr request(URLRequest::New()); |
| 221 request->url = "http://example.com"; |
| 222 |
| 223 URLResponsePtr response; |
| 224 url_loader_proxy_->Start(request.Pass(), |
| 225 base::Bind(&PassA<URLResponsePtr>, &response)); |
| 226 base::RunLoop().RunUntilIdle(); |
| 227 |
| 228 EXPECT_TRUE(url_loader_); |
| 229 EXPECT_FALSE(response); |
| 230 ASSERT_TRUE(g_current_job); |
| 231 |
| 232 g_current_job->NotifyHeadersComplete(); |
| 233 base::RunLoop().RunUntilIdle(); |
| 234 |
| 235 EXPECT_TRUE(url_loader_); |
| 236 EXPECT_TRUE(response); |
| 237 EXPECT_EQ(TestURLRequestJob::READING, g_current_job->status()); |
| 238 |
| 239 url_loader_proxy_.reset(); |
| 240 base::RunLoop().RunUntilIdle(); |
| 241 |
| 242 EXPECT_TRUE(url_loader_); |
| 243 |
| 244 g_current_job->NotifyReadComplete(0); |
| 245 base::RunLoop().RunUntilIdle(); |
| 246 |
| 247 EXPECT_FALSE(url_loader_); |
| 248 } |
| 249 |
| 250 TEST_F(UrlLoaderImplTest, RequestFailed) { |
| 251 URLRequestPtr request(URLRequest::New()); |
| 252 request->url = "http://example.com"; |
| 253 |
| 254 URLResponsePtr response; |
| 255 url_loader_proxy_->Start(request.Pass(), |
| 256 base::Bind(&PassA<URLResponsePtr>, &response)); |
| 257 base::RunLoop().RunUntilIdle(); |
| 258 |
| 259 EXPECT_TRUE(url_loader_); |
| 260 EXPECT_FALSE(response); |
| 261 ASSERT_TRUE(g_current_job); |
| 262 |
| 263 g_current_job->NotifyHeadersComplete(); |
| 264 base::RunLoop().RunUntilIdle(); |
| 265 |
| 266 EXPECT_TRUE(url_loader_); |
| 267 EXPECT_TRUE(response); |
| 268 EXPECT_EQ(TestURLRequestJob::READING, g_current_job->status()); |
| 269 |
| 270 url_loader_proxy_.reset(); |
| 271 base::RunLoop().RunUntilIdle(); |
| 272 |
| 273 EXPECT_TRUE(url_loader_); |
| 274 |
| 275 g_current_job->NotifyReadComplete(-1); |
| 276 base::RunLoop().RunUntilIdle(); |
| 277 |
| 278 EXPECT_FALSE(url_loader_); |
| 279 } |
| 280 |
| 281 } // namespace mojo |
| 282 } // namespace |
OLD | NEW |