[Cronet] Delay StartNetLog and StopNetLog until native request context is initialized
[chromium-blink-merge.git] / net / proxy / mojo_proxy_resolver_impl_unittest.cc
blob8f2f4ab29538ba35bc2ee754c9b3e9d3524a6411
1 // Copyright 2015 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.
5 #include "net/proxy/mojo_proxy_resolver_impl.h"
7 #include <string>
8 #include <vector>
10 #include "base/run_loop.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "net/base/net_errors.h"
13 #include "net/proxy/mock_proxy_resolver.h"
14 #include "net/proxy/mojo_proxy_type_converters.h"
15 #include "net/proxy/proxy_info.h"
16 #include "net/proxy/proxy_server.h"
17 #include "net/test/event_waiter.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h"
20 #include "third_party/mojo/src/mojo/public/cpp/bindings/error_handler.h"
22 namespace net {
23 namespace {
25 class TestRequestClient : public interfaces::ProxyResolverRequestClient,
26 public mojo::ErrorHandler {
27 public:
28 enum Event {
29 RESULT_RECEIVED,
30 LOAD_STATE_CHANGED,
31 CONNECTION_ERROR,
34 explicit TestRequestClient(
35 mojo::InterfaceRequest<interfaces::ProxyResolverRequestClient> request);
37 void WaitForResult();
39 Error error() { return error_; }
40 const mojo::Array<interfaces::ProxyServerPtr>& results() { return results_; }
41 LoadState load_state() { return load_state_; }
42 EventWaiter<Event>& event_waiter() { return event_waiter_; }
44 private:
45 // interfaces::ProxyResolverRequestClient override.
46 void ReportResult(int32_t error,
47 mojo::Array<interfaces::ProxyServerPtr> results) override;
48 void LoadStateChanged(int32_t load_state) override;
50 // mojo::ErrorHandler override.
51 void OnConnectionError() override;
53 bool done_ = false;
54 Error error_ = ERR_FAILED;
55 LoadState load_state_ = LOAD_STATE_IDLE;
56 mojo::Array<interfaces::ProxyServerPtr> results_;
58 mojo::Binding<interfaces::ProxyResolverRequestClient> binding_;
60 EventWaiter<Event> event_waiter_;
63 TestRequestClient::TestRequestClient(
64 mojo::InterfaceRequest<interfaces::ProxyResolverRequestClient> request)
65 : binding_(this, request.Pass()) {
66 binding_.set_error_handler(this);
69 void TestRequestClient::WaitForResult() {
70 if (done_)
71 return;
73 event_waiter_.WaitForEvent(RESULT_RECEIVED);
74 ASSERT_TRUE(done_);
77 void TestRequestClient::ReportResult(
78 int32_t error,
79 mojo::Array<interfaces::ProxyServerPtr> results) {
80 event_waiter_.NotifyEvent(RESULT_RECEIVED);
81 ASSERT_FALSE(done_);
82 error_ = static_cast<Error>(error);
83 results_ = results.Pass();
84 done_ = true;
87 void TestRequestClient::LoadStateChanged(int32_t load_state) {
88 event_waiter_.NotifyEvent(LOAD_STATE_CHANGED);
89 load_state_ = static_cast<LoadState>(load_state);
92 void TestRequestClient::OnConnectionError() {
93 event_waiter_.NotifyEvent(CONNECTION_ERROR);
96 class SetPacScriptClient {
97 public:
98 base::Callback<void(int32_t)> CreateCallback();
99 Error error() { return error_; }
101 private:
102 void ReportResult(int32_t error);
104 Error error_ = ERR_FAILED;
107 base::Callback<void(int32_t)> SetPacScriptClient::CreateCallback() {
108 return base::Bind(&SetPacScriptClient::ReportResult, base::Unretained(this));
111 void SetPacScriptClient::ReportResult(int32_t error) {
112 error_ = static_cast<Error>(error);
115 class CallbackMockProxyResolver : public MockAsyncProxyResolverExpectsBytes {
116 public:
117 CallbackMockProxyResolver() {}
118 ~CallbackMockProxyResolver() override;
120 // MockAsyncProxyResolverExpectsBytes overrides.
121 int GetProxyForURL(const GURL& url,
122 ProxyInfo* results,
123 const net::CompletionCallback& callback,
124 RequestHandle* request_handle,
125 const BoundNetLog& net_log) override;
126 void CancelRequest(RequestHandle request_handle) override;
127 int SetPacScript(const scoped_refptr<ProxyResolverScriptData>& script_data,
128 const net::CompletionCallback& callback) override;
130 // Wait until the mock resolver has received a CancelRequest call.
131 void WaitForCancel();
133 // Queues a proxy result to be returned synchronously.
134 void ReturnProxySynchronously(const ProxyInfo& result);
136 // Queues a SetPacScript to be completed synchronously.
137 void CompleteSetPacScriptSynchronously();
139 private:
140 base::Closure cancel_callback_;
141 scoped_ptr<ProxyInfo> sync_result_;
142 bool set_pac_script_sync_ = false;
145 CallbackMockProxyResolver::~CallbackMockProxyResolver() {
146 EXPECT_TRUE(pending_requests().empty());
149 int CallbackMockProxyResolver::GetProxyForURL(
150 const GURL& url,
151 ProxyInfo* results,
152 const net::CompletionCallback& callback,
153 RequestHandle* request_handle,
154 const BoundNetLog& net_log) {
155 if (sync_result_) {
156 *results = *sync_result_;
157 sync_result_.reset();
158 return OK;
160 return MockAsyncProxyResolverExpectsBytes::GetProxyForURL(
161 url, results, callback, request_handle, net_log);
164 void CallbackMockProxyResolver::CancelRequest(RequestHandle request_handle) {
165 MockAsyncProxyResolverExpectsBytes::CancelRequest(request_handle);
166 if (!cancel_callback_.is_null()) {
167 cancel_callback_.Run();
168 cancel_callback_.Reset();
172 int CallbackMockProxyResolver::SetPacScript(
173 const scoped_refptr<ProxyResolverScriptData>& script_data,
174 const net::CompletionCallback& callback) {
175 if (set_pac_script_sync_) {
176 set_pac_script_sync_ = false;
177 return OK;
179 return MockAsyncProxyResolverExpectsBytes::SetPacScript(script_data,
180 callback);
183 void CallbackMockProxyResolver::WaitForCancel() {
184 while (cancelled_requests().empty()) {
185 base::RunLoop run_loop;
186 cancel_callback_ = run_loop.QuitClosure();
187 run_loop.Run();
191 void CallbackMockProxyResolver::ReturnProxySynchronously(
192 const ProxyInfo& result) {
193 sync_result_.reset(new ProxyInfo(result));
196 void CallbackMockProxyResolver::CompleteSetPacScriptSynchronously() {
197 set_pac_script_sync_ = true;
200 void Fail(int32_t error) {
201 FAIL() << "Unexpected callback with error: " << error;
204 } // namespace
206 class MojoProxyResolverImplTest : public testing::Test {
207 protected:
208 void SetUp() override {
209 scoped_ptr<CallbackMockProxyResolver> mock_resolver(
210 new CallbackMockProxyResolver);
211 mock_proxy_resolver_ = mock_resolver.get();
212 resolver_impl_.reset(new MojoProxyResolverImpl(mock_resolver.Pass()));
213 resolver_ = resolver_impl_.get();
216 CallbackMockProxyResolver* mock_proxy_resolver_;
218 scoped_ptr<MojoProxyResolverImpl> resolver_impl_;
219 interfaces::ProxyResolver* resolver_;
222 TEST_F(MojoProxyResolverImplTest, GetProxyForUrl) {
223 interfaces::ProxyResolverRequestClientPtr client_ptr;
224 TestRequestClient client(mojo::GetProxy(&client_ptr));
226 resolver_->GetProxyForUrl("http://example.com", client_ptr.Pass());
227 ASSERT_EQ(1u, mock_proxy_resolver_->pending_requests().size());
228 scoped_refptr<MockAsyncProxyResolverBase::Request> request =
229 mock_proxy_resolver_->pending_requests()[0];
230 EXPECT_EQ(GURL("http://example.com"), request->url());
232 resolver_impl_->LoadStateChanged(request.get(),
233 LOAD_STATE_RESOLVING_HOST_IN_PROXY_SCRIPT);
234 client.event_waiter().WaitForEvent(TestRequestClient::LOAD_STATE_CHANGED);
235 EXPECT_EQ(LOAD_STATE_RESOLVING_HOST_IN_PROXY_SCRIPT, client.load_state());
237 request->results()->UsePacString(
238 "PROXY proxy.example.com:1; "
239 "SOCKS4 socks4.example.com:2; "
240 "SOCKS5 socks5.example.com:3; "
241 "HTTPS https.example.com:4; "
242 "QUIC quic.example.com:65000; "
243 "DIRECT");
244 request->CompleteNow(OK);
245 client.WaitForResult();
247 EXPECT_EQ(net::OK, client.error());
248 std::vector<net::ProxyServer> servers =
249 client.results().To<std::vector<net::ProxyServer>>();
250 ASSERT_EQ(6u, servers.size());
251 EXPECT_EQ(ProxyServer::SCHEME_HTTP, servers[0].scheme());
252 EXPECT_EQ("proxy.example.com", servers[0].host_port_pair().host());
253 EXPECT_EQ(1, servers[0].host_port_pair().port());
255 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, servers[1].scheme());
256 EXPECT_EQ("socks4.example.com", servers[1].host_port_pair().host());
257 EXPECT_EQ(2, servers[1].host_port_pair().port());
259 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, servers[2].scheme());
260 EXPECT_EQ("socks5.example.com", servers[2].host_port_pair().host());
261 EXPECT_EQ(3, servers[2].host_port_pair().port());
263 EXPECT_EQ(ProxyServer::SCHEME_HTTPS, servers[3].scheme());
264 EXPECT_EQ("https.example.com", servers[3].host_port_pair().host());
265 EXPECT_EQ(4, servers[3].host_port_pair().port());
267 EXPECT_EQ(ProxyServer::SCHEME_QUIC, servers[4].scheme());
268 EXPECT_EQ("quic.example.com", servers[4].host_port_pair().host());
269 EXPECT_EQ(65000, servers[4].host_port_pair().port());
271 EXPECT_EQ(ProxyServer::SCHEME_DIRECT, servers[5].scheme());
274 TEST_F(MojoProxyResolverImplTest, GetProxyForUrlSynchronous) {
275 interfaces::ProxyResolverRequestClientPtr client_ptr;
276 TestRequestClient client(mojo::GetProxy(&client_ptr));
278 ProxyInfo result;
279 result.UsePacString("DIRECT");
280 mock_proxy_resolver_->ReturnProxySynchronously(result);
281 resolver_->GetProxyForUrl("http://example.com", client_ptr.Pass());
282 ASSERT_EQ(0u, mock_proxy_resolver_->pending_requests().size());
283 client.WaitForResult();
285 EXPECT_EQ(net::OK, client.error());
286 std::vector<net::ProxyServer> proxy_servers =
287 client.results().To<std::vector<net::ProxyServer>>();
288 ASSERT_EQ(1u, proxy_servers.size());
289 net::ProxyServer& server = proxy_servers[0];
290 EXPECT_TRUE(server.is_direct());
293 TEST_F(MojoProxyResolverImplTest, GetProxyForUrlFailure) {
294 interfaces::ProxyResolverRequestClientPtr client_ptr;
295 TestRequestClient client(mojo::GetProxy(&client_ptr));
297 resolver_->GetProxyForUrl("http://example.com", client_ptr.Pass());
298 ASSERT_EQ(1u, mock_proxy_resolver_->pending_requests().size());
299 scoped_refptr<MockAsyncProxyResolverBase::Request> request =
300 mock_proxy_resolver_->pending_requests()[0];
301 EXPECT_EQ(GURL("http://example.com"), request->url());
302 request->CompleteNow(ERR_FAILED);
303 client.WaitForResult();
305 EXPECT_EQ(ERR_FAILED, client.error());
306 std::vector<net::ProxyServer> proxy_servers =
307 client.results().To<std::vector<net::ProxyServer>>();
308 EXPECT_TRUE(proxy_servers.empty());
311 TEST_F(MojoProxyResolverImplTest, GetProxyForUrlMultiple) {
312 interfaces::ProxyResolverRequestClientPtr client_ptr1;
313 TestRequestClient client1(mojo::GetProxy(&client_ptr1));
314 interfaces::ProxyResolverRequestClientPtr client_ptr2;
315 TestRequestClient client2(mojo::GetProxy(&client_ptr2));
317 resolver_->GetProxyForUrl("http://example.com", client_ptr1.Pass());
318 resolver_->GetProxyForUrl("https://example.com", client_ptr2.Pass());
319 ASSERT_EQ(2u, mock_proxy_resolver_->pending_requests().size());
320 scoped_refptr<MockAsyncProxyResolverBase::Request> request1 =
321 mock_proxy_resolver_->pending_requests()[0];
322 EXPECT_EQ(GURL("http://example.com"), request1->url());
323 scoped_refptr<MockAsyncProxyResolverBase::Request> request2 =
324 mock_proxy_resolver_->pending_requests()[1];
325 EXPECT_EQ(GURL("https://example.com"), request2->url());
326 request1->results()->UsePacString("HTTPS proxy.example.com:12345");
327 request1->CompleteNow(OK);
328 request2->results()->UsePacString("SOCKS5 another-proxy.example.com:6789");
329 request2->CompleteNow(OK);
330 client1.WaitForResult();
331 client2.WaitForResult();
333 EXPECT_EQ(net::OK, client1.error());
334 std::vector<net::ProxyServer> proxy_servers1 =
335 client1.results().To<std::vector<net::ProxyServer>>();
336 ASSERT_EQ(1u, proxy_servers1.size());
337 net::ProxyServer& server1 = proxy_servers1[0];
338 EXPECT_EQ(ProxyServer::SCHEME_HTTPS, server1.scheme());
339 EXPECT_EQ("proxy.example.com", server1.host_port_pair().host());
340 EXPECT_EQ(12345, server1.host_port_pair().port());
342 EXPECT_EQ(net::OK, client2.error());
343 std::vector<net::ProxyServer> proxy_servers2 =
344 client2.results().To<std::vector<net::ProxyServer>>();
345 ASSERT_EQ(1u, proxy_servers1.size());
346 net::ProxyServer& server2 = proxy_servers2[0];
347 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, server2.scheme());
348 EXPECT_EQ("another-proxy.example.com", server2.host_port_pair().host());
349 EXPECT_EQ(6789, server2.host_port_pair().port());
352 TEST_F(MojoProxyResolverImplTest, SetPacScript) {
353 SetPacScriptClient client;
355 resolver_->SetPacScript("pac script", client.CreateCallback());
356 MockAsyncProxyResolverBase::SetPacScriptRequest* request =
357 mock_proxy_resolver_->pending_set_pac_script_request();
358 ASSERT_TRUE(request);
359 EXPECT_EQ("pac script", base::UTF16ToUTF8(request->script_data()->utf16()));
360 request->CompleteNow(OK);
361 EXPECT_EQ(OK, client.error());
364 TEST_F(MojoProxyResolverImplTest, SetPacScriptSynchronous) {
365 SetPacScriptClient client;
367 mock_proxy_resolver_->CompleteSetPacScriptSynchronously();
368 resolver_->SetPacScript("pac script", client.CreateCallback());
369 EXPECT_FALSE(mock_proxy_resolver_->pending_set_pac_script_request());
370 EXPECT_EQ(OK, client.error());
373 TEST_F(MojoProxyResolverImplTest, SetPacScriptMultiple) {
374 SetPacScriptClient client1;
375 SetPacScriptClient client2;
377 resolver_->SetPacScript("pac script", client1.CreateCallback());
378 resolver_->SetPacScript("a different pac script", client2.CreateCallback());
379 MockAsyncProxyResolverBase::SetPacScriptRequest* request =
380 mock_proxy_resolver_->pending_set_pac_script_request();
381 ASSERT_TRUE(request);
382 EXPECT_EQ("pac script", base::UTF16ToUTF8(request->script_data()->utf16()));
383 request->CompleteNow(OK);
384 EXPECT_EQ(OK, client1.error());
386 request = mock_proxy_resolver_->pending_set_pac_script_request();
387 ASSERT_TRUE(request);
388 EXPECT_EQ("a different pac script",
389 base::UTF16ToUTF8(request->script_data()->utf16()));
390 request->CompleteNow(ERR_PAC_SCRIPT_FAILED);
391 EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, client2.error());
394 TEST_F(MojoProxyResolverImplTest, DestroyClient) {
395 interfaces::ProxyResolverRequestClientPtr client_ptr;
396 scoped_ptr<TestRequestClient> client(
397 new TestRequestClient(mojo::GetProxy(&client_ptr)));
399 resolver_->GetProxyForUrl("http://example.com", client_ptr.Pass());
400 ASSERT_EQ(1u, mock_proxy_resolver_->pending_requests().size());
401 scoped_refptr<MockAsyncProxyResolverBase::Request> request =
402 mock_proxy_resolver_->pending_requests()[0];
403 EXPECT_EQ(GURL("http://example.com"), request->url());
404 request->results()->UsePacString("PROXY proxy.example.com:8080");
405 client.reset();
406 mock_proxy_resolver_->WaitForCancel();
409 TEST_F(MojoProxyResolverImplTest, DestroyService) {
410 interfaces::ProxyResolverRequestClientPtr client_ptr;
411 TestRequestClient client(mojo::GetProxy(&client_ptr));
413 resolver_->GetProxyForUrl("http://example.com", client_ptr.Pass());
414 resolver_->SetPacScript("pac script", base::Bind(&Fail));
415 ASSERT_EQ(1u, mock_proxy_resolver_->pending_requests().size());
416 scoped_refptr<MockAsyncProxyResolverBase::Request> request =
417 mock_proxy_resolver_->pending_requests()[0];
418 resolver_impl_.reset();
419 client.event_waiter().WaitForEvent(TestRequestClient::CONNECTION_ERROR);
422 } // namespace net