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

Side by Side Diff: chrome/browser/net/resolve_proxy_msg_helper_unittest.cc

Issue 14142: Start using the proxy resolve IPC for plugins.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 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 | Annotate | Revision Log
« no previous file with comments | « chrome/browser/net/resolve_proxy_msg_helper.cc ('k') | chrome/browser/plugin_process_host.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2009 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 "chrome/browser/net/resolve_proxy_msg_helper.h"
6
7 #include "base/waitable_event.h"
8 #include "net/base/net_errors.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10
11 // This ProxyConfigService always returns "http://pac" as the PAC url to use.
12 class MockProxyConfigService: public net::ProxyConfigService {
13 public:
14 virtual int GetProxyConfig(net::ProxyConfig* results) {
15 results->pac_url = GURL("http://pac");
16 return net::OK;
17 }
18 };
19
20 // This PAC resolver always returns the hostname of the query URL as the
21 // proxy to use. The Block() method will make GetProxyForURL() hang until
22 // Unblock() is called.
23 class MockProxyResolver : public net::ProxyResolver {
24 public:
25 explicit MockProxyResolver() : event_(false, false), is_blocked_(false) {
26 }
27
28 virtual int GetProxyForURL(const GURL& query_url,
29 const GURL& /*pac_url*/,
30 net::ProxyInfo* results) {
31 if (is_blocked_)
32 event_.Wait();
33 results->UseNamedProxy(query_url.host());
34 return net::OK;
35 }
36
37 void Block() {
38 is_blocked_ = true;
39 event_.Reset();
40 }
41
42 void Unblock() {
43 is_blocked_ = false;
44 event_.Signal();
45 }
46
47 private:
48 base::WaitableEvent event_;
49 bool is_blocked_;
50 };
51
52 // This struct holds the values that were passed to
53 // Delegate::OnResolveProxyCompleted(). The caller should use WaitUntilDone()
54 // to block until the result has been populated.
55 struct ResultFuture {
56 public:
57 ResultFuture()
58 : reply_msg(NULL),
59 error_code(0),
60 started_(false, false),
61 completed_(false, false) {
62 }
63
64 // Wait until the request has completed. In other words we have invoked:
65 // ResolveProxyMsgHelper::Delegate::OnResolveProxyCompleted.
66 void WaitUntilDone() {
67 completed_.Wait();
68 }
69
70 // Wait until the request has been sent to ResolveProxyMsgHelper.
71 void WaitUntilStarted() {
72 started_.Wait();
73 }
74
75 bool TimedWaitUntilDone(const base::TimeDelta& max_time) {
76 return completed_.TimedWait(max_time);
77 }
78
79 // These fields are only valid after returning from WaitUntilDone().
80 IPC::Message* reply_msg;
81 int error_code;
82 std::string proxy_list;
83
84 private:
85 friend class AsyncRequestRunner;
86 base::WaitableEvent started_;
87 base::WaitableEvent completed_;
88 };
89
90 // This class lives on the io thread. It starts async requests using the
91 // class under test (ResolveProxyMsgHelper), and signals the result future on
92 // completion.
93 class AsyncRequestRunner : public ResolveProxyMsgHelper::Delegate {
94 public:
95 AsyncRequestRunner(net::ProxyService* proxy_service) {
96 resolve_proxy_msg_helper_.reset(
97 new ResolveProxyMsgHelper(this, proxy_service));
98 }
99
100 void Start(ResultFuture* future, const GURL& url, IPC::Message* reply_msg) {
101 futures_.push_back(future);
102 resolve_proxy_msg_helper_->Start(url, reply_msg);
103
104 // Notify of request start.
105 future->started_.Signal();
106 }
107
108 virtual void OnResolveProxyCompleted(IPC::Message* reply_msg,
109 int error_code,
110 const std::string& proxy_list) {
111 // Update the result future for this request (top of queue), and signal it.
112 ResultFuture* future = futures_.front();
113 futures_.pop_front();
114
115 future->reply_msg = reply_msg;
116 future->error_code = error_code;
117 future->proxy_list = proxy_list;
118
119 // Notify of request completion.
120 future->completed_.Signal();
121 }
122
123 private:
124 std::deque<ResultFuture*> futures_;
125 scoped_ptr<ResolveProxyMsgHelper> resolve_proxy_msg_helper_;
126 };
127
128 // Helper class to start async requests on an io thread, and return a
129 // result future. The caller then uses ResultFuture::WaitUntilDone() to
130 // get at the results. It "bridges" the originating thread with the helper
131 // io thread.
132 class RunnerBridge {
133 public:
134 RunnerBridge() : io_thread_("io_thread"), done_(true, false) {
135 // Start an io thread where we will run the async requests.
136 base::Thread::Options options;
137 options.message_loop_type = MessageLoop::TYPE_IO;
138 io_thread_.StartWithOptions(options);
139
140 // Construct the state that lives on io thread.
141 io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
142 this, &RunnerBridge::DoConstruct));
143 done_.Wait();
144 }
145
146 // Start an async request on the io thread.
147 ResultFuture* Start(const GURL& url, IPC::Message* reply_msg) {
148 ResultFuture* future = new ResultFuture();
149
150 io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
151 async_runner_, &AsyncRequestRunner::Start, future, url, reply_msg));
152
153 return future;
154 }
155
156 void DestroyAsyncRunner() {
157 io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
158 this, &RunnerBridge::DoDestroyAsyncRunner));
159 done_.Wait();
160 }
161
162 ~RunnerBridge() {
163 io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
164 this, &RunnerBridge::DoDestroy));
165 done_.Wait();
166 }
167
168 MockProxyResolver* proxy_resolver() {
169 return proxy_resolver_;
170 }
171
172 // Called from io thread.
173 void DoConstruct() {
174 proxy_resolver_ = new MockProxyResolver();
175 proxy_service_ = new net::ProxyService(new MockProxyConfigService(),
176 proxy_resolver_);
177 async_runner_ = new AsyncRequestRunner(proxy_service_);
178 done_.Signal();
179 }
180
181 // Called from io thread.
182 void DoDestroy() {
183 delete async_runner_;
184 delete proxy_service_;
185 done_.Signal();
186 }
187
188 // Called from io thread.
189 void DoDestroyAsyncRunner() {
190 delete async_runner_;
191 async_runner_ = NULL;
192 done_.Signal();
193 }
194
195 private:
196 base::Thread io_thread_;
197 base::WaitableEvent done_;
198
199 net::ProxyService* proxy_service_;
200 MockProxyResolver* proxy_resolver_; // Owned by proxy_service_.
201
202 AsyncRequestRunner* async_runner_;
203 };
204
205 // Avoid the need to have an AddRef / Release
206 template<>
207 void RunnableMethodTraits<RunnerBridge>::RetainCallee(RunnerBridge*) {}
208 template<>
209 void RunnableMethodTraits<RunnerBridge>::ReleaseCallee(RunnerBridge*) {}
210
211 template<>
212 void RunnableMethodTraits<AsyncRequestRunner>::RetainCallee(AsyncRequestRunner*) {}
213 template<>
214 void RunnableMethodTraits<AsyncRequestRunner>::ReleaseCallee(AsyncRequestRunner* ) {}
215
216
217 // Issue three sequential requests -- each should succeed.
218 TEST(ResolveProxyMsgHelperTest, Sequential) {
219 RunnerBridge runner;
220
221 GURL url1("http://www.google1.com/");
222 GURL url2("http://www.google2.com/");
223 GURL url3("http://www.google3.com/");
224
225 scoped_ptr<IPC::Message> msg1(new IPC::Message());
226 scoped_ptr<IPC::Message> msg2(new IPC::Message());
227 scoped_ptr<IPC::Message> msg3(new IPC::Message());
228
229 // Execute each request sequentially (so there are never 2 requests
230 // outstanding at the same time).
231
232 scoped_ptr<ResultFuture> result1(runner.Start(url1, msg1.get()));
233 result1->WaitUntilDone();
234
235 scoped_ptr<ResultFuture> result2(runner.Start(url2, msg2.get()));
236 result2->WaitUntilDone();
237
238 scoped_ptr<ResultFuture> result3(runner.Start(url3, msg3.get()));
239 result3->WaitUntilDone();
240
241 // Check that each request gave the expected result.
242
243 EXPECT_EQ(msg1.get(), result1->reply_msg);
244 EXPECT_EQ(net::OK, result1->error_code);
245 EXPECT_EQ("PROXY www.google1.com", result1->proxy_list);
246
247 EXPECT_EQ(msg2.get(), result2->reply_msg);
248 EXPECT_EQ(net::OK, result2->error_code);
249 EXPECT_EQ("PROXY www.google2.com", result2->proxy_list);
250
251 EXPECT_EQ(msg3.get(), result3->reply_msg);
252 EXPECT_EQ(net::OK, result3->error_code);
253 EXPECT_EQ("PROXY www.google3.com", result3->proxy_list);
254 }
255
256 // Issue a request while one is already in progress -- should be queued.
257 TEST(ResolveProxyMsgHelperTest, QueueRequests) {
258 RunnerBridge runner;
259
260 GURL url1("http://www.google1.com/");
261 GURL url2("http://www.google2.com/");
262 GURL url3("http://www.google3.com/");
263
264 scoped_ptr<IPC::Message> msg1(new IPC::Message());
265 scoped_ptr<IPC::Message> msg2(new IPC::Message());
266 scoped_ptr<IPC::Message> msg3(new IPC::Message());
267
268 // Make the proxy resolver hang on the next request.
269 runner.proxy_resolver()->Block();
270
271 // Start three requests. Since the proxy resolver is hung, the second two
272 // will be pending.
273
274 scoped_ptr<ResultFuture> result1(runner.Start(url1, msg1.get()));
275 scoped_ptr<ResultFuture> result2(runner.Start(url2, msg2.get()));
276 scoped_ptr<ResultFuture> result3(runner.Start(url3, msg3.get()));
277
278 // Wait for the final request to have been scheduled. Otherwise we may rush
279 // to calling Unblock() without actually having blocked anything.
280 result3->WaitUntilStarted();
281
282 // Unblock the proxy service so requests 1-3 can complete.
283 runner.proxy_resolver()->Unblock();
284
285 // Wait for all the requests to finish (they run in FIFO order).
286 result3->WaitUntilDone();
287
288 // Check that each call invoked the callback with the right parameters.
289
290 EXPECT_EQ(msg1.get(), result1->reply_msg);
291 EXPECT_EQ(net::OK, result1->error_code);
292 EXPECT_EQ("PROXY www.google1.com", result1->proxy_list);
293
294 EXPECT_EQ(msg2.get(), result2->reply_msg);
295 EXPECT_EQ(net::OK, result2->error_code);
296 EXPECT_EQ("PROXY www.google2.com", result2->proxy_list);
297
298 EXPECT_EQ(msg3.get(), result3->reply_msg);
299 EXPECT_EQ(net::OK, result3->error_code);
300 EXPECT_EQ("PROXY www.google3.com", result3->proxy_list);
301 }
302
303 // Delete the helper while a request is in progress, and others are pending.
304 TEST(ResolveProxyMsgHelperTest, CancelPendingRequests) {
305 RunnerBridge runner;
306
307 GURL url1("http://www.google1.com/");
308 GURL url2("http://www.google2.com/");
309 GURL url3("http://www.google3.com/");
310
311 // NOTE: these are not scoped ptr, since they will be deleted by the
312 // request's cancellation.
313 IPC::Message* msg1 = new IPC::Message();
314 IPC::Message* msg2 = new IPC::Message();
315 IPC::Message* msg3 = new IPC::Message();
316
317 // Make the next request block.
318 runner.proxy_resolver()->Block();
319
320 // Start three requests; since the first one blocked, the other two should
321 // be pending.
322
323 scoped_ptr<ResultFuture> result1(runner.Start(url1, msg1));
324 scoped_ptr<ResultFuture> result2(runner.Start(url2, msg2));
325 scoped_ptr<ResultFuture> result3(runner.Start(url3, msg3));
326
327 result3->WaitUntilStarted();
328
329 // Delete the underlying ResolveProxyMsgHelper -- this should cancel all
330 // the requests which are outstanding.
331 runner.DestroyAsyncRunner();
332
333 // Unblocking the proxy resolver means the three requests can complete --
334 // however they should not try to notify the delegate since we have already
335 // deleted the helper.
336 runner.proxy_resolver()->Unblock();
337
338 // Check that none of the requests were sent to the delegate.
339 EXPECT_FALSE(
340 result1->TimedWaitUntilDone(base::TimeDelta::FromMilliseconds(2)));
341 EXPECT_FALSE(
342 result2->TimedWaitUntilDone(base::TimeDelta::FromMilliseconds(2)));
343 EXPECT_FALSE(
344 result3->TimedWaitUntilDone(base::TimeDelta::FromMilliseconds(2)));
345
346 // It should also be the case that msg1, msg2, msg3 were deleted by the
347 // cancellation. (Else will show up as a leak in Purify).
348 }
349
OLDNEW
« no previous file with comments | « chrome/browser/net/resolve_proxy_msg_helper.cc ('k') | chrome/browser/plugin_process_host.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698