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/common/message_pump_mojo.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 #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h"
22 class TestURLRequestJob
;
24 TestURLRequestJob
* g_current_job
= nullptr;
27 void PassA(A
* destination
, A value
) {
28 *destination
= value
.Pass();
31 class TestURLRequestJob
: public net::URLRequestJob
{
33 enum Status
{ CREATED
, STARTED
, READING
, COMPLETED
};
35 TestURLRequestJob(net::URLRequest
* request
,
36 net::NetworkDelegate
* network_delegate
)
37 : net::URLRequestJob(request
, network_delegate
),
40 CHECK(!g_current_job
);
44 Status
status() { return status_
; }
46 int buf_size() { return buf_size_
; }
48 void Start() override
{ status_
= STARTED
; }
50 bool ReadRawData(net::IOBuffer
* buf
, int buf_size
, int* bytes_read
) override
{
53 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING
, 0));
57 void NotifyHeadersComplete() { net::URLRequestJob::NotifyHeadersComplete(); }
59 void NotifyReadComplete(int bytes_read
) {
62 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED
, 0));
63 net::URLRequestJob::NotifyReadComplete(0);
64 } else if (bytes_read
== 0) {
66 NotifyDone(net::URLRequestStatus());
67 net::URLRequestJob::NotifyReadComplete(bytes_read
);
70 SetStatus(net::URLRequestStatus());
71 net::URLRequestJob::NotifyReadComplete(bytes_read
);
76 ~TestURLRequestJob() override
{
77 CHECK(g_current_job
== this);
78 g_current_job
= nullptr;
85 class TestProtocolHandler
: public net::URLRequestJobFactory::ProtocolHandler
{
87 net::URLRequestJob
* MaybeCreateJob(
88 net::URLRequest
* request
,
89 net::NetworkDelegate
* network_delegate
) const override
{
90 return new TestURLRequestJob(request
, network_delegate
);
94 ~TestProtocolHandler() override
{}
97 class UrlLoaderImplTest
: public test::ApplicationTestBase
{
99 UrlLoaderImplTest() : message_loop_(common::MessagePumpMojo::Create()) {}
102 bool ShouldCreateDefaultRunLoop() override
{
106 void SetUp() override
{
107 ApplicationTestBase::SetUp();
109 scoped_ptr
<net::TestURLRequestContext
> url_request_context(
110 new net::TestURLRequestContext(true));
111 ASSERT_TRUE(url_request_job_factory_
.SetProtocolHandler(
112 "http", new TestProtocolHandler()));
113 url_request_context
->set_job_factory(&url_request_job_factory_
);
114 url_request_context
->Init();
115 network_context_
.reset(new NetworkContext(url_request_context
.Pass()));
117 new URLLoaderImpl(network_context_
.get(),
118 GetProxy(&url_loader_proxy_
),
119 make_scoped_ptr
<mojo::AppRefCount
>(nullptr));
120 EXPECT_TRUE(IsUrlLoaderValid());
123 bool IsUrlLoaderValid() {
124 return network_context_
->GetURLLoaderCountForTesting() > 0u;
127 base::MessageLoop message_loop_
;
128 net::TestJobInterceptor
* job_interceptor_
;
129 net::URLRequestJobFactoryImpl url_request_job_factory_
;
130 scoped_ptr
<NetworkContext
> network_context_
;
131 URLLoaderPtr url_loader_proxy_
;
134 TEST_F(UrlLoaderImplTest
, ClosedBeforeAnyCall
) {
135 url_loader_proxy_
.reset();
136 base::RunLoop().RunUntilIdle();
138 EXPECT_FALSE(IsUrlLoaderValid());
141 TEST_F(UrlLoaderImplTest
, ClosedWhileWaitingOnTheNetwork
) {
142 URLRequestPtr
request(URLRequest::New());
143 request
->url
= "http://example.com";
145 URLResponsePtr response
;
146 url_loader_proxy_
->Start(request
.Pass(),
147 base::Bind(&PassA
<URLResponsePtr
>, &response
));
148 base::RunLoop().RunUntilIdle();
150 EXPECT_TRUE(IsUrlLoaderValid());
151 EXPECT_FALSE(response
);
152 ASSERT_TRUE(g_current_job
);
154 g_current_job
->NotifyHeadersComplete();
155 base::RunLoop().RunUntilIdle();
157 EXPECT_TRUE(IsUrlLoaderValid());
158 EXPECT_TRUE(response
);
159 EXPECT_EQ(TestURLRequestJob::READING
, g_current_job
->status());
161 url_loader_proxy_
.reset();
162 base::RunLoop().RunUntilIdle();
164 EXPECT_TRUE(IsUrlLoaderValid());
167 base::RunLoop().RunUntilIdle();
169 EXPECT_FALSE(IsUrlLoaderValid());
172 TEST_F(UrlLoaderImplTest
, ClosedWhileWaitingOnThePipeToBeWriteable
) {
173 URLRequestPtr
request(URLRequest::New());
174 request
->url
= "http://example.com";
176 URLResponsePtr response
;
177 url_loader_proxy_
->Start(request
.Pass(),
178 base::Bind(&PassA
<URLResponsePtr
>, &response
));
179 base::RunLoop().RunUntilIdle();
181 EXPECT_TRUE(IsUrlLoaderValid());
182 EXPECT_FALSE(response
);
183 ASSERT_TRUE(g_current_job
);
185 g_current_job
->NotifyHeadersComplete();
186 base::RunLoop().RunUntilIdle();
188 EXPECT_TRUE(IsUrlLoaderValid());
189 EXPECT_TRUE(response
);
190 EXPECT_EQ(TestURLRequestJob::READING
, g_current_job
->status());
192 while (g_current_job
->status() == TestURLRequestJob::READING
) {
193 g_current_job
->NotifyReadComplete(g_current_job
->buf_size());
194 base::RunLoop().RunUntilIdle();
197 EXPECT_EQ(TestURLRequestJob::STARTED
, g_current_job
->status());
199 url_loader_proxy_
.reset();
200 base::RunLoop().RunUntilIdle();
202 EXPECT_TRUE(IsUrlLoaderValid());
205 base::RunLoop().RunUntilIdle();
207 EXPECT_FALSE(IsUrlLoaderValid());
210 TEST_F(UrlLoaderImplTest
, RequestCompleted
) {
211 URLRequestPtr
request(URLRequest::New());
212 request
->url
= "http://example.com";
214 URLResponsePtr response
;
215 url_loader_proxy_
->Start(request
.Pass(),
216 base::Bind(&PassA
<URLResponsePtr
>, &response
));
217 base::RunLoop().RunUntilIdle();
219 EXPECT_TRUE(IsUrlLoaderValid());
220 EXPECT_FALSE(response
);
221 ASSERT_TRUE(g_current_job
);
223 g_current_job
->NotifyHeadersComplete();
224 base::RunLoop().RunUntilIdle();
226 EXPECT_TRUE(IsUrlLoaderValid());
227 EXPECT_TRUE(response
);
228 EXPECT_EQ(TestURLRequestJob::READING
, g_current_job
->status());
230 url_loader_proxy_
.reset();
231 base::RunLoop().RunUntilIdle();
233 EXPECT_TRUE(IsUrlLoaderValid());
235 g_current_job
->NotifyReadComplete(0);
236 base::RunLoop().RunUntilIdle();
238 EXPECT_FALSE(IsUrlLoaderValid());
241 TEST_F(UrlLoaderImplTest
, RequestFailed
) {
242 URLRequestPtr
request(URLRequest::New());
243 request
->url
= "http://example.com";
245 URLResponsePtr response
;
246 url_loader_proxy_
->Start(request
.Pass(),
247 base::Bind(&PassA
<URLResponsePtr
>, &response
));
248 base::RunLoop().RunUntilIdle();
250 EXPECT_TRUE(IsUrlLoaderValid());
251 EXPECT_FALSE(response
);
252 ASSERT_TRUE(g_current_job
);
254 g_current_job
->NotifyHeadersComplete();
255 base::RunLoop().RunUntilIdle();
257 EXPECT_TRUE(IsUrlLoaderValid());
258 EXPECT_TRUE(response
);
259 EXPECT_EQ(TestURLRequestJob::READING
, g_current_job
->status());
261 url_loader_proxy_
.reset();
262 base::RunLoop().RunUntilIdle();
264 EXPECT_TRUE(IsUrlLoaderValid());
266 g_current_job
->NotifyReadComplete(-1);
267 base::RunLoop().RunUntilIdle();
269 EXPECT_FALSE(IsUrlLoaderValid());