Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(20)

Side by Side Diff: net/proxy/proxy_resolver_mojo_unittest.cc

Issue 917863005: Implementation of ProxyResolver that uses a Mojo service. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@sam-v8-pac-utility-proxy
Patch Set: Address review comments. Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/proxy/proxy_resolver_mojo.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include "net/proxy/proxy_resolver_mojo.h"
6
7 #include <list>
8 #include <map>
9 #include <string>
10
11 #include "base/bind.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/run_loop.h"
14 #include "base/stl_util.h"
15 #include "mojo/common/common_type_converters.h"
16 #include "net/base/net_log.h"
17 #include "net/base/test_completion_callback.h"
18 #include "net/dns/mock_host_resolver.h"
19 #include "net/proxy/mojo_proxy_resolver_factory.h"
20 #include "net/proxy/mojo_type_converters.h"
21 #include "net/proxy/proxy_info.h"
22 #include "net/proxy/proxy_resolver_script_data.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 #include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h"
25 #include "third_party/mojo/src/mojo/public/cpp/bindings/error_handler.h"
26 #include "url/gurl.h"
27
28 namespace net {
29
30 namespace {
31
32 static const char kScriptData[] = "FooBarBaz";
33
34 struct SetPacScriptAction {
35 public:
36 enum Action {
37 COMPLETE,
38 DROP,
39 };
40
41 static SetPacScriptAction ReturnResult(int error) {
42 SetPacScriptAction result;
43 result.error = error;
44 return result;
45 }
46
47 static SetPacScriptAction DropRequest() {
48 SetPacScriptAction result;
49 result.action = DROP;
50 return result;
51 }
52
53 Action action = COMPLETE;
54 int error = OK;
55 };
56
57 class MockMojoProxyResolver : public interfaces::ProxyResolver {
58 public:
59 explicit MockMojoProxyResolver(
60 mojo::InterfaceRequest<interfaces::ProxyResolver> req)
61 : pac_script_calls_(0), binding_(this, req.Pass()) {}
62 ~MockMojoProxyResolver() override {
63 STLDeleteContainerPairSecondPointers(proxy_results_.begin(),
64 proxy_results_.end());
65 };
66
67 void AddPacScriptAction(SetPacScriptAction action);
68 // Returned script data is UTF8.
69 std::string GetPacScriptData() { return pac_script_data_; }
70 int GetPacScriptCalls() { return pac_script_calls_; }
71
72 void AddProxyResult(const GURL& url,
73 int error,
74 mojo::Array<interfaces::ProxyServerPtr> proxy_servers);
75 void CloseRequestClient(const GURL& url);
76
77 void Disconnect() { binding_.Close(); }
78
79 void WaitForSetPacScript();
80
81 private:
82 struct ProxyResults {
83 explicit ProxyResults(bool close)
84 : close(close), error(OK), proxy_servers() {}
85 ProxyResults(int err, mojo::Array<interfaces::ProxyServerPtr>& s)
86 : close(false), error(err), proxy_servers(s.Pass()) {}
87
88 bool close;
89 int error;
90 mojo::Array<interfaces::ProxyServerPtr> proxy_servers;
91 };
92
93 // Overridden from interfaces::ProxyResolver:
94 void SetPacScript(const mojo::String& data,
95 const mojo::Callback<void(int32_t)>& callback) override;
96 void GetProxyForUrl(
97 const mojo::String& url,
98 interfaces::ProxyResolverRequestClientPtr client) override;
99
100 std::string pac_script_data_;
101 std::list<SetPacScriptAction> pac_script_actions_;
102 int pac_script_calls_;
103 base::Closure pac_script_quit_closure_;
104
105 std::map<GURL, ProxyResults*> proxy_results_;
106
107 mojo::Binding<interfaces::ProxyResolver> binding_;
108 };
109
110 void MockMojoProxyResolver::AddProxyResult(
111 const GURL& url,
112 int error,
113 mojo::Array<interfaces::ProxyServerPtr> proxy_servers) {
114 proxy_results_[url] = new ProxyResults(error, proxy_servers);
115 }
116
117 void MockMojoProxyResolver::CloseRequestClient(const GURL& url) {
118 proxy_results_[url] = new ProxyResults(true);
119 }
120
121 void MockMojoProxyResolver::AddPacScriptAction(SetPacScriptAction action) {
122 pac_script_actions_.push_back(action);
123 }
124
125 void MockMojoProxyResolver::SetPacScript(
126 const mojo::String& data,
127 const mojo::Callback<void(int32_t)>& callback) {
128 pac_script_data_ = data.To<std::string>();
129 pac_script_calls_++;
130
131 DCHECK(!pac_script_actions_.empty());
132 SetPacScriptAction action = pac_script_actions_.front();
133 pac_script_actions_.pop_front();
134
135 switch (action.action) {
136 case SetPacScriptAction::COMPLETE:
137 callback.Run(action.error);
138 break;
139 case SetPacScriptAction::DROP:
140 binding_.Close();
141 break;
142 }
143
144 if (!pac_script_quit_closure_.is_null())
145 pac_script_quit_closure_.Run();
146 pac_script_quit_closure_.Reset();
147 }
148
149 void MockMojoProxyResolver::WaitForSetPacScript() {
150 if (pac_script_calls_)
151 return;
152
153 base::RunLoop run_loop;
154 pac_script_quit_closure_ = run_loop.QuitClosure();
155 run_loop.Run();
156 }
157
158 void MockMojoProxyResolver::GetProxyForUrl(
159 const mojo::String& url,
160 interfaces::ProxyResolverRequestClientPtr client) {
161 ProxyResults* result = proxy_results_[url.To<GURL>()];
162 ASSERT_NE(nullptr, result);
163 if (result->close) {
164 client.reset();
165 } else {
166 client->ReportResult(result->error, result->proxy_servers.Clone());
167 }
168 }
169
170 class TestMojoProxyResolverFactory : public MojoProxyResolverFactory {
171 public:
172 TestMojoProxyResolverFactory();
173 ~TestMojoProxyResolverFactory();
174
175 // Overridden from MojoProxyResolverFactory:
176 void Create(mojo::InterfaceRequest<interfaces::ProxyResolver> req,
177 interfaces::HostResolverPtr host_resolver) override;
178
179 MockMojoProxyResolver* GetMockResolver() {
Sam McNally 2015/02/17 06:23:09 MockMojoProxyResolver& mock_resolver()
Anand Mistry (off Chromium) 2015/02/18 06:48:52 Done.
180 return mock_proxy_resolver_.get();
181 }
182
183 void AddFuturePacScriptAction(int creation, SetPacScriptAction action);
184
185 int NumCreateCalls() const { return num_create_calls_; }
Sam McNally 2015/02/17 06:23:09 num_create_calls()
Anand Mistry (off Chromium) 2015/02/18 06:48:52 Done.
186 void WaitForCreateCalls(int num);
187
188 private:
189 int num_create_calls_;
190 base::Closure run_loop_quit_closure_;
191 std::map<int, std::list<SetPacScriptAction>> pac_script_actions_;
192
193 scoped_ptr<MockMojoProxyResolver> mock_proxy_resolver_;
194 };
195
196 TestMojoProxyResolverFactory::TestMojoProxyResolverFactory()
197 : num_create_calls_(0) {
198 }
199
200 TestMojoProxyResolverFactory::~TestMojoProxyResolverFactory() {
201 }
202
203 void TestMojoProxyResolverFactory::Create(
204 mojo::InterfaceRequest<interfaces::ProxyResolver> req,
205 interfaces::HostResolverPtr host_resolver) {
206 mock_proxy_resolver_.reset(new MockMojoProxyResolver(req.Pass()));
207
208 for (const auto& action : pac_script_actions_[num_create_calls_])
209 mock_proxy_resolver_->AddPacScriptAction(action);
210 num_create_calls_++;
211
212 if (!run_loop_quit_closure_.is_null())
213 run_loop_quit_closure_.Run();
214 run_loop_quit_closure_.Reset();
215 }
216
217 void TestMojoProxyResolverFactory::AddFuturePacScriptAction(
218 int creation,
219 SetPacScriptAction action) {
220 pac_script_actions_[creation].push_back(action);
221 }
222
223 void TestMojoProxyResolverFactory::WaitForCreateCalls(int num) {
224 while (num_create_calls_ < num) {
225 base::RunLoop run_loop;
226 run_loop_quit_closure_ = run_loop.QuitClosure();
227 run_loop.Run();
228 }
229 }
230
231 class Request {
232 public:
233 Request(ProxyResolverMojo* resolver, const GURL& url);
234
235 int Resolve();
236 void Cancel();
237 int WaitForResult();
238
239 int error() const { return error_; }
240 const ProxyInfo& results() const { return results_; }
241
242 private:
243 // Completion callback for ProxyResolverMojo::Resolve.
244 void OnResolveDone(int error);
245
246 ProxyResolverMojo* resolver_;
247 const GURL url_;
248 ProxyInfo results_;
249 ProxyResolver::RequestHandle handle_;
250 int error_;
251
252 base::RunLoop run_loop_;
Sam McNally 2015/02/17 06:23:09 The comment for RunLoop says it should be created
Anand Mistry (off Chromium) 2015/02/18 06:48:52 Done.
253 };
254
255 Request::Request(ProxyResolverMojo* resolver, const GURL& url)
256 : resolver_(resolver), url_(url), error_(0) {
257 }
258
259 int Request::Resolve() {
260 BoundNetLog net_log;
261 error_ = resolver_->GetProxyForURL(
262 url_, &results_,
263 base::Bind(&Request::OnResolveDone, base::Unretained(this)), &handle_,
264 net_log);
265 return error_;
266 }
267
268 void Request::Cancel() {
269 resolver_->CancelRequest(handle_);
270 }
271
272 void Request::OnResolveDone(int error) {
273 error_ = error;
274 run_loop_.Quit();
275 }
276
277 int Request::WaitForResult() {
278 run_loop_.Run();
279 return error_;
280 }
281
282 } // namespace
283
284 class ProxyResolverMojoTest : public testing::Test {
285 protected:
286 void SetUp() override {
287 mock_host_resolver_.rules()->AddRule("example.com", "1.2.3.4");
288
289 proxy_resolver_mojo_.reset(new ProxyResolverMojo(
290 &mojo_proxy_resolver_factory_, &mock_host_resolver_));
291 }
292
293 scoped_ptr<Request> MakeRequest(const GURL& url) {
294 return scoped_ptr<Request>(new Request(proxy_resolver_mojo_.get(), url));
Sam McNally 2015/02/17 06:23:09 make_scoped_ptr
Anand Mistry (off Chromium) 2015/02/18 06:48:52 Done.
295 }
296
297 mojo::Array<interfaces::ProxyServerPtr> ProxyServersFromPacString(
298 const std::string& pac_string) {
299 ProxyInfo proxy_info;
300 proxy_info.UsePacString(pac_string);
301
302 return mojo::Array<interfaces::ProxyServerPtr>::From(
303 proxy_info.proxy_list().GetAll());
304 }
305
306 MockHostResolver mock_host_resolver_;
307 TestMojoProxyResolverFactory mojo_proxy_resolver_factory_;
308 scoped_ptr<ProxyResolverMojo> proxy_resolver_mojo_;
309 };
310
311 TEST_F(ProxyResolverMojoTest, SetPacScript) {
312 TestCompletionCallback callback;
313 scoped_refptr<ProxyResolverScriptData> pac_script(
314 ProxyResolverScriptData::FromUTF8(kScriptData));
315 mojo_proxy_resolver_factory_.GetMockResolver()->AddPacScriptAction(
316 SetPacScriptAction::ReturnResult(OK));
317 EXPECT_EQ(OK, callback.GetResult(proxy_resolver_mojo_->SetPacScript(
318 pac_script, callback.callback())));
319 EXPECT_EQ(kScriptData,
320 mojo_proxy_resolver_factory_.GetMockResolver()->GetPacScriptData());
321 }
322
323 TEST_F(ProxyResolverMojoTest, SetPacScript_Empty) {
324 TestCompletionCallback callback;
325 scoped_refptr<ProxyResolverScriptData> pac_script(
326 ProxyResolverScriptData::FromUTF8(""));
327 EXPECT_EQ(ERR_PAC_SCRIPT_FAILED,
328 callback.GetResult(proxy_resolver_mojo_->SetPacScript(
329 pac_script, callback.callback())));
330 }
331
332 TEST_F(ProxyResolverMojoTest, SetPacScript_Url) {
333 TestCompletionCallback callback;
334 scoped_refptr<ProxyResolverScriptData> pac_script(
335 ProxyResolverScriptData::FromURL(GURL("http://www.example.com")));
336 EXPECT_EQ(ERR_PAC_SCRIPT_FAILED,
337 callback.GetResult(proxy_resolver_mojo_->SetPacScript(
338 pac_script, callback.callback())));
339 }
340
341 TEST_F(ProxyResolverMojoTest, SetPacScript_Failed) {
342 TestCompletionCallback callback;
343 scoped_refptr<ProxyResolverScriptData> pac_script(
344 ProxyResolverScriptData::FromUTF8(kScriptData));
345 mojo_proxy_resolver_factory_.GetMockResolver()->AddPacScriptAction(
346 SetPacScriptAction::ReturnResult(ERR_PAC_STATUS_NOT_OK));
347 EXPECT_EQ(ERR_PAC_STATUS_NOT_OK,
348 callback.GetResult(proxy_resolver_mojo_->SetPacScript(
349 pac_script, callback.callback())));
350 }
351
352 TEST_F(ProxyResolverMojoTest, SetPacScript_Disconnected) {
353 scoped_refptr<ProxyResolverScriptData> pac_script(
354 ProxyResolverScriptData::FromUTF8(kScriptData));
355 TestCompletionCallback callback;
356 EXPECT_EQ(ERR_IO_PENDING, proxy_resolver_mojo_->SetPacScript(
357 pac_script, callback.callback()));
358 mojo_proxy_resolver_factory_.GetMockResolver()->Disconnect();
359 EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, callback.GetResult(ERR_IO_PENDING));
360
361 // The service should have been recreated transparently.
362 mojo_proxy_resolver_factory_.WaitForCreateCalls(2);
363 }
364
365 TEST_F(ProxyResolverMojoTest, SetPacScript_SuccessThenDisconnect) {
366 scoped_refptr<ProxyResolverScriptData> pac_script(
367 ProxyResolverScriptData::FromUTF8(kScriptData));
368 mojo_proxy_resolver_factory_.GetMockResolver()->AddPacScriptAction(
369 SetPacScriptAction::ReturnResult(OK));
370 mojo_proxy_resolver_factory_.GetMockResolver()->AddPacScriptAction(
371 SetPacScriptAction::DropRequest());
372 mojo_proxy_resolver_factory_.AddFuturePacScriptAction(
373 1, SetPacScriptAction::ReturnResult(OK));
374 {
375 TestCompletionCallback callback;
376 EXPECT_EQ(OK, callback.GetResult(proxy_resolver_mojo_->SetPacScript(
377 pac_script, callback.callback())));
378 EXPECT_EQ(
379 kScriptData,
380 mojo_proxy_resolver_factory_.GetMockResolver()->GetPacScriptData());
381 }
382
383 {
384 TestCompletionCallback callback;
385 EXPECT_EQ(ERR_IO_PENDING, proxy_resolver_mojo_->SetPacScript(
386 pac_script, callback.callback()));
Sam McNally 2015/02/17 06:23:09 This should use a different pac script.
Anand Mistry (off Chromium) 2015/02/18 06:48:52 Done.
387 EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, callback.GetResult(ERR_IO_PENDING));
388 }
389
390 // The service should have been recreated transparently.
391 mojo_proxy_resolver_factory_.WaitForCreateCalls(2);
392
393 // Wait for SetPacScript() to be run.
394 mojo_proxy_resolver_factory_.GetMockResolver()->WaitForSetPacScript();
395 EXPECT_EQ(
396 1, mojo_proxy_resolver_factory_.GetMockResolver()->GetPacScriptCalls());
397 EXPECT_EQ(kScriptData,
398 mojo_proxy_resolver_factory_.GetMockResolver()->GetPacScriptData());
399 }
400
401 TEST_F(ProxyResolverMojoTest, SetPacScript_Cancel) {
402 scoped_refptr<ProxyResolverScriptData> pac_script(
403 ProxyResolverScriptData::FromUTF8(kScriptData));
404 TestCompletionCallback callback;
405 mojo_proxy_resolver_factory_.GetMockResolver()->AddPacScriptAction(
406 SetPacScriptAction::ReturnResult(OK));
407 EXPECT_EQ(ERR_IO_PENDING, proxy_resolver_mojo_->SetPacScript(
408 pac_script, callback.callback()));
409 proxy_resolver_mojo_->CancelSetPacScript();
410 }
411
412 TEST_F(ProxyResolverMojoTest, SetPacScript_CancelAndSetAgain) {
413 scoped_refptr<ProxyResolverScriptData> pac_script(
414 ProxyResolverScriptData::FromUTF8(kScriptData));
415 mojo_proxy_resolver_factory_.GetMockResolver()->AddPacScriptAction(
416 SetPacScriptAction::ReturnResult(ERR_FAILED));
417 mojo_proxy_resolver_factory_.GetMockResolver()->AddPacScriptAction(
418 SetPacScriptAction::ReturnResult(ERR_UNEXPECTED));
419 TestCompletionCallback callback1;
420 EXPECT_EQ(ERR_IO_PENDING, proxy_resolver_mojo_->SetPacScript(
421 pac_script, callback1.callback()));
422 proxy_resolver_mojo_->CancelSetPacScript();
423
424 TestCompletionCallback callback2;
425 EXPECT_EQ(ERR_IO_PENDING, proxy_resolver_mojo_->SetPacScript(
426 pac_script, callback2.callback()));
427 EXPECT_EQ(ERR_UNEXPECTED, callback2.GetResult(ERR_IO_PENDING));
428 EXPECT_EQ(
429 2, mojo_proxy_resolver_factory_.GetMockResolver()->GetPacScriptCalls());
430 }
431
432 TEST_F(ProxyResolverMojoTest, GetProxyForURL) {
433 scoped_ptr<Request> request(MakeRequest(GURL("http://www.example.com")));
434 mojo_proxy_resolver_factory_.GetMockResolver()->AddProxyResult(
435 GURL("http://www.example.com"), OK, ProxyServersFromPacString("DIRECT"));
436 EXPECT_EQ(ERR_IO_PENDING, request->Resolve());
437 EXPECT_EQ(OK, request->WaitForResult());
438
439 EXPECT_EQ("DIRECT", request->results().ToPacString());
440 }
441
442 TEST_F(ProxyResolverMojoTest, GetProxyForURL_MultipleResults) {
443 static const char kPacString[] =
444 "PROXY foo1:80;DIRECT;SOCKS foo2:1234;"
445 "SOCKS5 foo3:1080;HTTPS foo4:443;QUIC foo6:8888";
446 scoped_ptr<Request> request(MakeRequest(GURL("http://www.example.com")));
447 mojo_proxy_resolver_factory_.GetMockResolver()->AddProxyResult(
448 GURL("http://www.example.com"), OK,
449 ProxyServersFromPacString(kPacString));
450 EXPECT_EQ(ERR_IO_PENDING, request->Resolve());
451 EXPECT_EQ(OK, request->WaitForResult());
452
453 EXPECT_EQ(kPacString, request->results().ToPacString());
454 }
455
456 TEST_F(ProxyResolverMojoTest, GetProxyForURL_Error) {
457 scoped_ptr<Request> request(MakeRequest(GURL("http://www.example.com")));
458 mojo_proxy_resolver_factory_.GetMockResolver()->AddProxyResult(
459 GURL("http://www.example.com"), ERR_UNEXPECTED,
460 mojo::Array<interfaces::ProxyServerPtr>());
461 EXPECT_EQ(ERR_IO_PENDING, request->Resolve());
462 EXPECT_EQ(ERR_UNEXPECTED, request->WaitForResult());
463
464 EXPECT_TRUE(request->results().is_empty());
465 }
466
467 TEST_F(ProxyResolverMojoTest, GetProxyForURL_Cancel) {
468 scoped_ptr<Request> request(MakeRequest(GURL("http://www.example.com")));
469 mojo_proxy_resolver_factory_.GetMockResolver()->AddProxyResult(
470 GURL("http://www.example.com"), OK, ProxyServersFromPacString("DIRECT"));
471 EXPECT_EQ(ERR_IO_PENDING, request->Resolve());
472 request->Cancel();
473 }
474
475 TEST_F(ProxyResolverMojoTest, GetProxyForURL_MultipleRequests) {
476 mojo_proxy_resolver_factory_.GetMockResolver()->AddProxyResult(
477 GURL("http://www.example.com"), OK, ProxyServersFromPacString("DIRECT"));
478 mojo_proxy_resolver_factory_.GetMockResolver()->AddProxyResult(
479 GURL("https://www.chromium.org"), OK,
480 ProxyServersFromPacString("HTTPS foo:443"));
481
482 scoped_ptr<Request> request1(MakeRequest(GURL("http://www.example.com")));
483 EXPECT_EQ(ERR_IO_PENDING, request1->Resolve());
484 scoped_ptr<Request> request2(MakeRequest(GURL("https://www.chromium.org")));
485 EXPECT_EQ(ERR_IO_PENDING, request2->Resolve());
486
487 EXPECT_EQ(OK, request1->WaitForResult());
488 EXPECT_EQ(OK, request2->WaitForResult());
489
490 EXPECT_EQ("DIRECT", request1->results().ToPacString());
491 EXPECT_EQ("HTTPS foo:443", request2->results().ToPacString());
492 }
493
494 TEST_F(ProxyResolverMojoTest, GetProxyForURL_Disconnect) {
495 {
496 scoped_ptr<Request> request(MakeRequest(GURL("http://www.example.com")));
497 mojo_proxy_resolver_factory_.GetMockResolver()->AddProxyResult(
498 GURL("http://www.example.com"), OK,
499 ProxyServersFromPacString("DIRECT"));
500 EXPECT_EQ(ERR_IO_PENDING, request->Resolve());
501 mojo_proxy_resolver_factory_.GetMockResolver()->Disconnect();
502 EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, request->WaitForResult());
503 EXPECT_TRUE(request->results().is_empty());
504 }
505
506 // The service should have been recreated transparently.
507 mojo_proxy_resolver_factory_.WaitForCreateCalls(2);
508
509 {
510 scoped_ptr<Request> request(MakeRequest(GURL("http://www.example.com")));
511 mojo_proxy_resolver_factory_.GetMockResolver()->AddProxyResult(
512 GURL("http://www.example.com"), OK,
513 ProxyServersFromPacString("DIRECT"));
514 EXPECT_EQ(ERR_IO_PENDING, request->Resolve());
515 EXPECT_EQ(OK, request->WaitForResult());
516 EXPECT_EQ("DIRECT", request->results().ToPacString());
517 }
518 }
519
520 TEST_F(ProxyResolverMojoTest, GetProxyForURL_ClientClosed) {
521 scoped_ptr<Request> request(MakeRequest(GURL("http://www.example.com")));
522 mojo_proxy_resolver_factory_.GetMockResolver()->CloseRequestClient(
523 GURL("http://www.example.com"));
524 EXPECT_EQ(ERR_IO_PENDING, request->Resolve());
525 EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, request->WaitForResult());
526
527 EXPECT_TRUE(request->results().is_empty());
528 }
529
530 } // namespace net
OLDNEW
« no previous file with comments | « net/proxy/proxy_resolver_mojo.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698