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.
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/application/public/cpp/application_test_base.h"
11 #include "mojo/message_pump/message_pump_mojo.h"
12 #include "mojo/services/network/network_context.h"
13 #include "mojo/services/network/url_loader_impl.h"
14 #include "net/base/net_errors.h"
15 #include "net/url_request/url_request_job.h"
16 #include "net/url_request/url_request_job_factory_impl.h"
17 #include "net/url_request/url_request_status.h"
18 #include "net/url_request/url_request_test_util.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h"
24 class TestURLRequestJob
;
26 TestURLRequestJob
* g_current_job
= nullptr;
29 void PassA(A
* destination
, A value
) {
30 *destination
= value
.Pass();
33 class TestURLRequestJob
: public net::URLRequestJob
{
35 enum Status
{ CREATED
, STARTED
, READING
, COMPLETED
};
37 TestURLRequestJob(net::URLRequest
* request
,
38 net::NetworkDelegate
* network_delegate
)
39 : net::URLRequestJob(request
, network_delegate
),
42 CHECK(!g_current_job
);
46 Status
status() { return status_
; }
48 int buf_size() { return buf_size_
; }
50 void Start() override
{ status_
= STARTED
; }
52 bool ReadRawData(net::IOBuffer
* buf
, int buf_size
, int* bytes_read
) override
{
55 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING
, 0));
59 void NotifyHeadersComplete() { net::URLRequestJob::NotifyHeadersComplete(); }
61 void NotifyReadComplete(int bytes_read
) {
64 NotifyDone(net::URLRequestStatus(
65 net::URLRequestStatus::FromError(net::ERR_FAILED
)));
66 net::URLRequestJob::NotifyReadComplete(0);
67 } else if (bytes_read
== 0) {
69 NotifyDone(net::URLRequestStatus());
70 net::URLRequestJob::NotifyReadComplete(bytes_read
);
73 SetStatus(net::URLRequestStatus());
74 net::URLRequestJob::NotifyReadComplete(bytes_read
);
79 ~TestURLRequestJob() override
{
80 CHECK(g_current_job
== this);
81 g_current_job
= nullptr;
88 class TestProtocolHandler
: public net::URLRequestJobFactory::ProtocolHandler
{
90 net::URLRequestJob
* MaybeCreateJob(
91 net::URLRequest
* request
,
92 net::NetworkDelegate
* network_delegate
) const override
{
93 return new TestURLRequestJob(request
, network_delegate
);
97 ~TestProtocolHandler() override
{}
100 class UrlLoaderImplTest
: public test::ApplicationTestBase
{
102 UrlLoaderImplTest() : message_loop_(common::MessagePumpMojo::Create()) {}
105 bool ShouldCreateDefaultRunLoop() override
{
109 void SetUp() override
{
110 ApplicationTestBase::SetUp();
112 scoped_ptr
<net::TestURLRequestContext
> url_request_context(
113 new net::TestURLRequestContext(true));
114 ASSERT_TRUE(url_request_job_factory_
.SetProtocolHandler(
115 "http", new TestProtocolHandler()));
116 url_request_context
->set_job_factory(&url_request_job_factory_
);
117 url_request_context
->Init();
118 network_context_
.reset(new NetworkContext(url_request_context
.Pass()));
120 new URLLoaderImpl(network_context_
.get(),
121 GetProxy(&url_loader_proxy_
),
122 make_scoped_ptr
<mojo::AppRefCount
>(nullptr));
123 EXPECT_TRUE(IsUrlLoaderValid());
126 bool IsUrlLoaderValid() {
127 return network_context_
->GetURLLoaderCountForTesting() > 0u;
130 base::MessageLoop message_loop_
;
131 net::TestJobInterceptor
* job_interceptor_
;
132 net::URLRequestJobFactoryImpl url_request_job_factory_
;
133 scoped_ptr
<NetworkContext
> network_context_
;
134 URLLoaderPtr url_loader_proxy_
;
137 TEST_F(UrlLoaderImplTest
, ClosedBeforeAnyCall
) {
138 url_loader_proxy_
.reset();
139 base::RunLoop().RunUntilIdle();
141 EXPECT_FALSE(IsUrlLoaderValid());
144 TEST_F(UrlLoaderImplTest
, ClosedWhileWaitingOnTheNetwork
) {
145 URLRequestPtr
request(URLRequest::New());
146 request
->url
= "http://example.com";
148 URLResponsePtr response
;
149 url_loader_proxy_
->Start(request
.Pass(),
150 base::Bind(&PassA
<URLResponsePtr
>, &response
));
151 base::RunLoop().RunUntilIdle();
153 EXPECT_TRUE(IsUrlLoaderValid());
154 EXPECT_FALSE(response
);
155 ASSERT_TRUE(g_current_job
);
157 g_current_job
->NotifyHeadersComplete();
158 base::RunLoop().RunUntilIdle();
160 EXPECT_TRUE(IsUrlLoaderValid());
161 EXPECT_TRUE(response
);
162 EXPECT_EQ(TestURLRequestJob::READING
, g_current_job
->status());
164 url_loader_proxy_
.reset();
165 base::RunLoop().RunUntilIdle();
167 EXPECT_TRUE(IsUrlLoaderValid());
170 base::RunLoop().RunUntilIdle();
172 EXPECT_FALSE(IsUrlLoaderValid());
175 TEST_F(UrlLoaderImplTest
, ClosedWhileWaitingOnThePipeToBeWriteable
) {
176 URLRequestPtr
request(URLRequest::New());
177 request
->url
= "http://example.com";
179 URLResponsePtr response
;
180 url_loader_proxy_
->Start(request
.Pass(),
181 base::Bind(&PassA
<URLResponsePtr
>, &response
));
182 base::RunLoop().RunUntilIdle();
184 EXPECT_TRUE(IsUrlLoaderValid());
185 EXPECT_FALSE(response
);
186 ASSERT_TRUE(g_current_job
);
188 g_current_job
->NotifyHeadersComplete();
189 base::RunLoop().RunUntilIdle();
191 EXPECT_TRUE(IsUrlLoaderValid());
192 EXPECT_TRUE(response
);
193 EXPECT_EQ(TestURLRequestJob::READING
, g_current_job
->status());
195 while (g_current_job
->status() == TestURLRequestJob::READING
) {
196 g_current_job
->NotifyReadComplete(g_current_job
->buf_size());
197 base::RunLoop().RunUntilIdle();
200 EXPECT_EQ(TestURLRequestJob::STARTED
, g_current_job
->status());
202 url_loader_proxy_
.reset();
203 base::RunLoop().RunUntilIdle();
205 EXPECT_TRUE(IsUrlLoaderValid());
208 base::RunLoop().RunUntilIdle();
210 EXPECT_FALSE(IsUrlLoaderValid());
213 TEST_F(UrlLoaderImplTest
, RequestCompleted
) {
214 URLRequestPtr
request(URLRequest::New());
215 request
->url
= "http://example.com";
217 URLResponsePtr response
;
218 url_loader_proxy_
->Start(request
.Pass(),
219 base::Bind(&PassA
<URLResponsePtr
>, &response
));
220 base::RunLoop().RunUntilIdle();
222 EXPECT_TRUE(IsUrlLoaderValid());
223 EXPECT_FALSE(response
);
224 ASSERT_TRUE(g_current_job
);
226 g_current_job
->NotifyHeadersComplete();
227 base::RunLoop().RunUntilIdle();
229 EXPECT_TRUE(IsUrlLoaderValid());
230 EXPECT_TRUE(response
);
231 EXPECT_EQ(TestURLRequestJob::READING
, g_current_job
->status());
233 url_loader_proxy_
.reset();
234 base::RunLoop().RunUntilIdle();
236 EXPECT_TRUE(IsUrlLoaderValid());
238 g_current_job
->NotifyReadComplete(0);
239 base::RunLoop().RunUntilIdle();
241 EXPECT_FALSE(IsUrlLoaderValid());
244 TEST_F(UrlLoaderImplTest
, RequestFailed
) {
245 URLRequestPtr
request(URLRequest::New());
246 request
->url
= "http://example.com";
248 URLResponsePtr response
;
249 url_loader_proxy_
->Start(request
.Pass(),
250 base::Bind(&PassA
<URLResponsePtr
>, &response
));
251 base::RunLoop().RunUntilIdle();
253 EXPECT_TRUE(IsUrlLoaderValid());
254 EXPECT_FALSE(response
);
255 ASSERT_TRUE(g_current_job
);
257 g_current_job
->NotifyHeadersComplete();
258 base::RunLoop().RunUntilIdle();
260 EXPECT_TRUE(IsUrlLoaderValid());
261 EXPECT_TRUE(response
);
262 EXPECT_EQ(TestURLRequestJob::READING
, g_current_job
->status());
264 url_loader_proxy_
.reset();
265 base::RunLoop().RunUntilIdle();
267 EXPECT_TRUE(IsUrlLoaderValid());
269 g_current_job
->NotifyReadComplete(-1);
270 base::RunLoop().RunUntilIdle();
272 EXPECT_FALSE(IsUrlLoaderValid());