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

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

Issue 149525: Remove the concept of threading from ProxyService, and move it into the Proxy... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Add missing header for mac Created 11 years, 4 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 | « net/proxy/single_threaded_proxy_resolver.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')
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 "base/waitable_event.h"
6 #include "googleurl/src/gurl.h"
7 #include "net/base/net_errors.h"
8 #include "net/base/test_completion_callback.h"
9 #include "net/proxy/proxy_info.h"
10 #include "net/proxy/single_threaded_proxy_resolver.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12
13 namespace net {
14 namespace {
15
16 // A synchronous mock ProxyResolver implementation, which can be used in
17 // conjunction with SingleThreadedProxyResolver.
18 // - returns a single-item proxy list with the query's host.
19 class MockProxyResolver : public ProxyResolver {
20 public:
21 MockProxyResolver()
22 : ProxyResolver(true /*expects_pac_bytes*/),
23 wrong_loop_(MessageLoop::current()),
24 request_count_(0),
25 resolve_latency_ms_(0) {}
26
27 // ProxyResolver implementation:
28 virtual int GetProxyForURL(const GURL& query_url,
29 ProxyInfo* results,
30 CompletionCallback* callback,
31 RequestHandle* request) {
32 if (resolve_latency_ms_)
33 PlatformThread::Sleep(resolve_latency_ms_);
34
35 CheckIsOnWorkerThread();
36
37 EXPECT_EQ(NULL, callback);
38 EXPECT_EQ(NULL, request);
39
40 results->UseNamedProxy(query_url.host());
41
42 // Return a success code which represents the request's order.
43 return request_count_++;
44 }
45
46 virtual void CancelRequest(RequestHandle request) {
47 NOTREACHED();
48 }
49
50 virtual void SetPacScriptByDataInternal(const std::string& bytes) {
51 CheckIsOnWorkerThread();
52 last_pac_bytes_ = bytes;
53 }
54
55 const std::string& last_pac_bytes() const { return last_pac_bytes_; }
56
57 void SetResolveLatency(int latency_ms) {
58 resolve_latency_ms_ = latency_ms;
59 }
60
61 private:
62 void CheckIsOnWorkerThread() {
63 // We should be running on the worker thread -- while we don't know the
64 // message loop of SingleThreadedProxyResolver's worker thread, we do
65 // know that it is going to be distinct from the loop running the
66 // test, so at least make sure it isn't the main loop.
67 EXPECT_NE(MessageLoop::current(), wrong_loop_);
68 }
69
70 MessageLoop* wrong_loop_;
71 int request_count_;
72 std::string last_pac_bytes_;
73 int resolve_latency_ms_;
74 };
75
76
77 // A mock synchronous ProxyResolver which can be set to block upon reaching
78 // GetProxyForURL().
79 class BlockableProxyResolver : public MockProxyResolver {
80 public:
81 BlockableProxyResolver()
82 : should_block_(false),
83 unblocked_(true, true),
84 blocked_(true, false) {
85 }
86
87 void Block() {
88 should_block_ = true;
89 unblocked_.Reset();
90 }
91
92 void Unblock() {
93 should_block_ = false;
94 blocked_.Reset();
95 unblocked_.Signal();
96 }
97
98 void WaitUntilBlocked() {
99 blocked_.Wait();
100 }
101
102 virtual int GetProxyForURL(const GURL& query_url,
103 ProxyInfo* results,
104 CompletionCallback* callback,
105 RequestHandle* request) {
106 if (should_block_) {
107 blocked_.Signal();
108 unblocked_.Wait();
109 }
110
111 return MockProxyResolver::GetProxyForURL(
112 query_url, results, callback, request);
113 }
114
115 private:
116 bool should_block_;
117 base::WaitableEvent unblocked_;
118 base::WaitableEvent blocked_;
119 };
120
121 TEST(SingleThreadedProxyResolverTest, Basic) {
122 MockProxyResolver* mock = new MockProxyResolver;
123 scoped_ptr<SingleThreadedProxyResolver> resolver(
124 new SingleThreadedProxyResolver(mock));
125
126 int rv;
127
128 EXPECT_TRUE(resolver->expects_pac_bytes());
129
130 // Call SetPacScriptByData() -- we will make sure it reaches the sync resolver
131 // later on.
132 resolver->SetPacScriptByData("pac script bytes");
133
134 // Start request 0.
135 TestCompletionCallback callback0;
136 ProxyInfo results0;
137 rv = resolver->GetProxyForURL(
138 GURL("http://request0"), &results0, &callback0, NULL);
139 EXPECT_EQ(ERR_IO_PENDING, rv);
140
141 // Wait for request 0 to finish.
142 rv = callback0.WaitForResult();
143 EXPECT_EQ(0, rv);
144 EXPECT_EQ("PROXY request0:80", results0.ToPacString());
145
146 // Verify that the data from SetPacScriptByData() reached the resolver.
147 // (Since we waited for the first request to complete, we are guaranteed
148 // that the earlier post completed).
149 EXPECT_EQ("pac script bytes", mock->last_pac_bytes());
150
151 // Start 3 more requests (request1 to request3).
152
153 TestCompletionCallback callback1;
154 ProxyInfo results1;
155 rv = resolver->GetProxyForURL(
156 GURL("http://request1"), &results1, &callback1, NULL);
157 EXPECT_EQ(ERR_IO_PENDING, rv);
158
159 TestCompletionCallback callback2;
160 ProxyInfo results2;
161 rv = resolver->GetProxyForURL(
162 GURL("http://request2"), &results2, &callback2, NULL);
163 EXPECT_EQ(ERR_IO_PENDING, rv);
164
165 TestCompletionCallback callback3;
166 ProxyInfo results3;
167 rv = resolver->GetProxyForURL(
168 GURL("http://request3"), &results3, &callback3, NULL);
169 EXPECT_EQ(ERR_IO_PENDING, rv);
170
171 // Wait for the requests to finish (they must finish in the order they were
172 // started, which is what we check for from their magic return value)
173
174 rv = callback1.WaitForResult();
175 EXPECT_EQ(1, rv);
176 EXPECT_EQ("PROXY request1:80", results1.ToPacString());
177
178 rv = callback2.WaitForResult();
179 EXPECT_EQ(2, rv);
180 EXPECT_EQ("PROXY request2:80", results2.ToPacString());
181
182 rv = callback3.WaitForResult();
183 EXPECT_EQ(3, rv);
184 EXPECT_EQ("PROXY request3:80", results3.ToPacString());
185 }
186
187 // Cancel a request which is in progress, and then cancel a request which
188 // is pending.
189 TEST(SingleThreadedProxyResolverTest, CancelRequest) {
190 BlockableProxyResolver* mock = new BlockableProxyResolver;
191 scoped_ptr<SingleThreadedProxyResolver> resolver(
192 new SingleThreadedProxyResolver(mock));
193
194 int rv;
195
196 // Block the proxy resolver, so no request can complete.
197 mock->Block();
198
199 // Start request 0.
200 ProxyResolver::RequestHandle request0;
201 TestCompletionCallback callback0;
202 ProxyInfo results0;
203 rv = resolver->GetProxyForURL(
204 GURL("http://request0"), &results0, &callback0, &request0);
205 EXPECT_EQ(ERR_IO_PENDING, rv);
206
207 // Wait until requests 0 reaches the worker thread.
208 mock->WaitUntilBlocked();
209
210 // Start 3 more requests (request1 : request3).
211
212 TestCompletionCallback callback1;
213 ProxyInfo results1;
214 rv = resolver->GetProxyForURL(
215 GURL("http://request1"), &results1, &callback1, NULL);
216 EXPECT_EQ(ERR_IO_PENDING, rv);
217
218 ProxyResolver::RequestHandle request2;
219 TestCompletionCallback callback2;
220 ProxyInfo results2;
221 rv = resolver->GetProxyForURL(
222 GURL("http://request2"), &results2, &callback2, &request2);
223 EXPECT_EQ(ERR_IO_PENDING, rv);
224
225 TestCompletionCallback callback3;
226 ProxyInfo results3;
227 rv = resolver->GetProxyForURL(
228 GURL("http://request3"), &results3, &callback3, NULL);
229 EXPECT_EQ(ERR_IO_PENDING, rv);
230
231 // Cancel request0 (inprogress) and request2 (pending).
232 resolver->CancelRequest(request0);
233 resolver->CancelRequest(request2);
234
235 // Unblock the worker thread so the requests can continue running.
236 mock->Unblock();
237
238 // Wait for requests 1 and 3 to finish.
239
240 rv = callback1.WaitForResult();
241 EXPECT_EQ(1, rv);
242 EXPECT_EQ("PROXY request1:80", results1.ToPacString());
243
244 rv = callback3.WaitForResult();
245 // Note that since request2 was cancelled before reaching the resolver,
246 // the request count is 2 and not 3 here.
247 EXPECT_EQ(2, rv);
248 EXPECT_EQ("PROXY request3:80", results3.ToPacString());
249
250 // Requests 0 and 2 which were cancelled, hence their completion callbacks
251 // were never summoned.
252 EXPECT_FALSE(callback0.have_result());
253 EXPECT_FALSE(callback2.have_result());
254 }
255
256 // Test that deleting SingleThreadedProxyResolver while requests are
257 // outstanding cancels them (and doesn't leak anything).
258 TEST(SingleThreadedProxyResolverTest, CancelRequestByDeleting) {
259 BlockableProxyResolver* mock = new BlockableProxyResolver;
260 scoped_ptr<SingleThreadedProxyResolver> resolver(
261 new SingleThreadedProxyResolver(mock));
262
263 int rv;
264
265 // Block the proxy resolver, so no request can complete.
266 mock->Block();
267
268 // Start 3 requests.
269
270 TestCompletionCallback callback0;
271 ProxyInfo results0;
272 rv = resolver->GetProxyForURL(
273 GURL("http://request0"), &results0, &callback0, NULL);
274 EXPECT_EQ(ERR_IO_PENDING, rv);
275
276 TestCompletionCallback callback1;
277 ProxyInfo results1;
278 rv = resolver->GetProxyForURL(
279 GURL("http://request1"), &results1, &callback1, NULL);
280 EXPECT_EQ(ERR_IO_PENDING, rv);
281
282 TestCompletionCallback callback2;
283 ProxyInfo results2;
284 rv = resolver->GetProxyForURL(
285 GURL("http://request2"), &results2, &callback2, NULL);
286 EXPECT_EQ(ERR_IO_PENDING, rv);
287
288 // Wait until request 0 reaches the worker thread.
289 mock->WaitUntilBlocked();
290
291 // Add some latency, to improve the chance that when
292 // SingleThreadedProxyResolver is deleted below we are still running inside
293 // of the worker thread. The test will pass regardless, so this race doesn't
294 // cause flakiness. However the destruction during execution is a more
295 // interesting case to test.
296 mock->SetResolveLatency(100);
297
298 // Unblock the worker thread and delete the underlying
299 // SingleThreadedProxyResolver immediately.
300 mock->Unblock();
301 resolver.reset();
302
303 // Give any posted tasks a chance to run (in case there is badness).
304 MessageLoop::current()->RunAllPending();
305
306 // Check that none of the outstanding requests were completed.
307 EXPECT_FALSE(callback0.have_result());
308 EXPECT_FALSE(callback1.have_result());
309 EXPECT_FALSE(callback2.have_result());
310 }
311
312 } // namespace
313 } // namespace net
OLDNEW
« no previous file with comments | « net/proxy/single_threaded_proxy_resolver.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698