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

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

Issue 42596: Fix a race in proxy_service_unittest.cc that was causing flakiness on purify b... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Address wtc's second batch of comments Created 11 years, 9 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 | « no previous file | 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
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/compiler_specific.h" 5 #include "base/compiler_specific.h"
6 #include "googleurl/src/gurl.h" 6 #include "googleurl/src/gurl.h"
7 #include "net/base/net_errors.h" 7 #include "net/base/net_errors.h"
8 #include "net/proxy/proxy_config_service.h" 8 #include "net/proxy/proxy_config_service.h"
9 #include "net/proxy/proxy_resolver.h" 9 #include "net/proxy/proxy_resolver.h"
10 #include "net/proxy/proxy_script_fetcher.h" 10 #include "net/proxy/proxy_script_fetcher.h"
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 net::ProxyInfo info; 51 net::ProxyInfo info;
52 52
53 // info is only returned if query_url in GetProxyForURL matches this: 53 // info is only returned if query_url in GetProxyForURL matches this:
54 std::string info_predicate_query_host; 54 std::string info_predicate_query_host;
55 55
56 // If true, then GetProxyForURL will fail, which simulates failure to 56 // If true, then GetProxyForURL will fail, which simulates failure to
57 // download or execute the PAC file. 57 // download or execute the PAC file.
58 bool fail_get_proxy_for_url; 58 bool fail_get_proxy_for_url;
59 }; 59 };
60 60
61 class SyncProxyService {
62 public:
63 SyncProxyService(net::ProxyConfigService* config_service,
64 net::ProxyResolver* resolver)
65 : io_thread_("IO_Thread"),
66 service_(config_service, resolver) {
67 base::Thread::Options options;
68 options.message_loop_type = MessageLoop::TYPE_IO;
69 io_thread_.StartWithOptions(options);
70 sync_proxy_service_ = new net::SyncProxyServiceHelper(
71 io_thread_.message_loop(), &service_);
72 }
73
74 int ResolveProxy(const GURL& url, net::ProxyInfo* proxy_info) {
75 return sync_proxy_service_->ResolveProxy(url, proxy_info);
76 }
77
78 int ReconsiderProxyAfterError(const GURL& url, net::ProxyInfo* proxy_info) {
79 return sync_proxy_service_->ReconsiderProxyAfterError(url, proxy_info);
80 }
81
82 private:
83 base::Thread io_thread_;
84 net::ProxyService service_;
85 scoped_refptr<net::SyncProxyServiceHelper> sync_proxy_service_;
86 };
87
88 // ResultFuture is a handle to get at the result from 61 // ResultFuture is a handle to get at the result from
89 // ProxyService::ResolveProxyForURL() that ran on another thread. 62 // ProxyService::ResolveProxyForURL() that ran on another thread.
90 class ResultFuture : public base::RefCountedThreadSafe<ResultFuture> { 63 class ResultFuture : public base::RefCountedThreadSafe<ResultFuture> {
91 public: 64 public:
92 // |service| is the ProxyService to issue requests on, and |io_message_loop| 65 // |service| is the ProxyService to issue requests on, and |io_message_loop|
93 // is the message loop where ProxyService lives. 66 // is the message loop where ProxyService lives.
94 ResultFuture(MessageLoop* io_message_loop, 67 ResultFuture(MessageLoop* io_message_loop,
95 net::ProxyService* service) 68 net::ProxyService* service)
96 : io_message_loop_(io_message_loop), 69 : io_message_loop_(io_message_loop),
97 service_(service), 70 service_(service),
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 // Wait until the ProxyService completes this request. 109 // Wait until the ProxyService completes this request.
137 void WaitUntilCompleted() { 110 void WaitUntilCompleted() {
138 DCHECK(MessageLoop::current() != io_message_loop_); 111 DCHECK(MessageLoop::current() != io_message_loop_);
139 completion_.Wait(); 112 completion_.Wait();
140 DCHECK(did_complete_); 113 DCHECK(did_complete_);
141 } 114 }
142 115
143 private: 116 private:
144 friend class ProxyServiceWithFutures; 117 friend class ProxyServiceWithFutures;
145 118
146 // Start the request. Return once ProxyService::GetProxyForURL() returns. 119 typedef int (net::ProxyService::*RequestMethod)(const GURL&, net::ProxyInfo*,
120 net::CompletionCallback*, net::ProxyService::PacRequest**);
121
147 void StartResolve(const GURL& url) { 122 void StartResolve(const GURL& url) {
123 StartRequest(url, &net::ProxyService::ResolveProxy);
124 }
125
126 // |proxy_info| is the *previous* result (that we are reconsidering).
127 void StartReconsider(const GURL& url, const net::ProxyInfo& proxy_info) {
128 proxy_info_ = proxy_info;
129 StartRequest(url, &net::ProxyService::ReconsiderProxyAfterError);
130 }
131
132 // Start the request. Return once ProxyService::GetProxyForURL() or
133 // ProxyService::ReconsiderProxyAfterError() returns.
134 void StartRequest(const GURL& url, RequestMethod method) {
148 DCHECK(MessageLoop::current() != io_message_loop_); 135 DCHECK(MessageLoop::current() != io_message_loop_);
149 io_message_loop_->PostTask(FROM_HERE, NewRunnableMethod( 136 io_message_loop_->PostTask(FROM_HERE, NewRunnableMethod(
150 this, &ResultFuture::DoStartResolve, url)); 137 this, &ResultFuture::DoStartRequest, url, method));
151 started_.Wait(); 138 started_.Wait();
152 } 139 }
153 140
154 // Called on |io_message_loop_|. 141 // Called on |io_message_loop_|.
155 void DoStartResolve(const GURL& url) { 142 void DoStartRequest(const GURL& url, RequestMethod method) {
156 DCHECK(MessageLoop::current() == io_message_loop_); 143 DCHECK(MessageLoop::current() == io_message_loop_);
157 int rv = service_->ResolveProxy(url, &proxy_info_, &callback_, &request_); 144 int rv = (service_->*method)(url, &proxy_info_, &callback_, &request_);
158 if (rv != net::ERR_IO_PENDING) { 145 if (rv != net::ERR_IO_PENDING) {
159 // Completed synchronously. 146 // Completed synchronously.
160 OnCompletion(rv); 147 OnCompletion(rv);
161 } 148 }
162 started_.Signal(); 149 started_.Signal();
163 } 150 }
164 151
165 // Called on |io_message_loop_|. 152 // Called on |io_message_loop_|.
166 void DoCancel() { 153 void DoCancel() {
167 DCHECK(MessageLoop::current() == io_message_loop_); 154 DCHECK(MessageLoop::current() == io_message_loop_);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 int result_code_; 186 int result_code_;
200 net::ProxyInfo proxy_info_; 187 net::ProxyInfo proxy_info_;
201 }; 188 };
202 189
203 // Wraps a ProxyService running on its own IO thread. 190 // Wraps a ProxyService running on its own IO thread.
204 class ProxyServiceWithFutures { 191 class ProxyServiceWithFutures {
205 public: 192 public:
206 ProxyServiceWithFutures(net::ProxyConfigService* config_service, 193 ProxyServiceWithFutures(net::ProxyConfigService* config_service,
207 net::ProxyResolver* resolver) 194 net::ProxyResolver* resolver)
208 : io_thread_("IO_Thread"), 195 : io_thread_("IO_Thread"),
209 service_(config_service, resolver) { 196 io_thread_state_(new IOThreadState) {
210 base::Thread::Options options; 197 base::Thread::Options options;
211 options.message_loop_type = MessageLoop::TYPE_IO; 198 options.message_loop_type = MessageLoop::TYPE_IO;
212 io_thread_.StartWithOptions(options); 199 io_thread_.StartWithOptions(options);
200
201 // Initialize state that lives on |io_thread_|.
202 io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
203 io_thread_state_.get(), &IOThreadState::DoInit,
204 config_service, resolver));
205 io_thread_state_->event.Wait();
206 }
207
208 ~ProxyServiceWithFutures() {
209 // Destroy state that lives on |io_thread_|.
210 io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
211 io_thread_state_.get(), &IOThreadState::DoDestroy));
212 io_thread_state_->event.Wait();
213 } 213 }
214 214
215 // Start the request on |io_thread_|, and return a handle that can be 215 // Start the request on |io_thread_|, and return a handle that can be
216 // used to access the results. The caller is responsible for freeing 216 // used to access the results. The caller is responsible for freeing
217 // the ResultFuture. 217 // the ResultFuture.
218 void ResolveProxy(scoped_refptr<ResultFuture>* result, const GURL& url) { 218 void ResolveProxy(scoped_refptr<ResultFuture>* result, const GURL& url) {
219 (*result) = new ResultFuture(io_thread_.message_loop(), &service_); 219 *result = new ResultFuture(io_thread_.message_loop(),
220 io_thread_state_->service);
220 (*result)->StartResolve(url); 221 (*result)->StartResolve(url);
221 } 222 }
222 223
224 // Same as above, but for "ReconsiderProxyAfterError()".
225 void ReconsiderProxyAfterError(scoped_refptr<ResultFuture>* result,
226 const GURL& url,
227 const net::ProxyInfo& proxy_info) {
228 *result = new ResultFuture(io_thread_.message_loop(),
229 io_thread_state_->service);
230 (*result)->StartReconsider(url, proxy_info);
231 }
232
223 void SetProxyScriptFetcher(net::ProxyScriptFetcher* proxy_script_fetcher) { 233 void SetProxyScriptFetcher(net::ProxyScriptFetcher* proxy_script_fetcher) {
224 service_.SetProxyScriptFetcher(proxy_script_fetcher); 234 io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
235 io_thread_state_.get(), &IOThreadState::DoSetProxyScriptFetcher,
236 proxy_script_fetcher));
237 io_thread_state_->event.Wait();
225 } 238 }
226 239
227 private: 240 private:
241 // Class that encapsulates the state living on IO thread. It needs to be
242 // ref-counted for posting tasks.
243 class IOThreadState : public base::RefCounted<IOThreadState> {
244 public:
245 IOThreadState() : event(false, false), service(NULL) {}
246
247 void DoInit(net::ProxyConfigService* config_service,
248 net::ProxyResolver* resolver) {
249 service = new net::ProxyService(config_service, resolver);
250 event.Signal();
251 }
252
253 void DoDestroy() {
254 delete service;
255 service = NULL;
256 event.Signal();
257 }
258
259 void DoSetProxyScriptFetcher(
260 net::ProxyScriptFetcher* proxy_script_fetcher) {
261 service->SetProxyScriptFetcher(proxy_script_fetcher);
262 event.Signal();
263 }
264
265 base::WaitableEvent event;
266 net::ProxyService* service;
267 };
268
228 base::Thread io_thread_; 269 base::Thread io_thread_;
229 net::ProxyService service_; 270 scoped_refptr<IOThreadState> io_thread_state_; // Lives on |io_thread_|.
271 };
272
273 // Wrapper around ProxyServiceWithFutures to do one request at a time.
274 class SyncProxyService {
275 public:
276 SyncProxyService(net::ProxyConfigService* config_service,
277 net::ProxyResolver* resolver)
278 : service_(config_service, resolver) {
279 }
280
281 int ResolveProxy(const GURL& url, net::ProxyInfo* proxy_info) {
282 scoped_refptr<ResultFuture> result;
283 service_.ResolveProxy(&result, url);
284 *proxy_info = result->GetProxyInfo();
285 return result->GetResultCode();
286 }
287
288 int ReconsiderProxyAfterError(const GURL& url, net::ProxyInfo* proxy_info) {
289 scoped_refptr<ResultFuture> result;
290 service_.ReconsiderProxyAfterError(&result, url, *proxy_info);
291 *proxy_info = result->GetProxyInfo();
292 return result->GetResultCode();
293 }
294
295 private:
296 ProxyServiceWithFutures service_;
230 }; 297 };
231 298
232 // A ProxyResolver which can be set to block upon reaching GetProxyForURL. 299 // A ProxyResolver which can be set to block upon reaching GetProxyForURL.
233 class BlockableProxyResolver : public net::ProxyResolver { 300 class BlockableProxyResolver : public net::ProxyResolver {
234 public: 301 public:
235 BlockableProxyResolver() : net::ProxyResolver(true), 302 BlockableProxyResolver() : net::ProxyResolver(true),
236 should_block_(false), 303 should_block_(false),
237 unblocked_(true, true), 304 unblocked_(true, true),
238 blocked_(true, false) { 305 blocked_(true, false) {
239 } 306 }
(...skipping 676 matching lines...) Expand 10 before | Expand all | Expand 10 after
916 result3->WaitUntilCompleted(); 983 result3->WaitUntilCompleted();
917 984
918 EXPECT_FALSE(result1->IsCompleted()); // Cancelled. 985 EXPECT_FALSE(result1->IsCompleted()); // Cancelled.
919 EXPECT_FALSE(result2->IsCompleted()); // Cancelled. 986 EXPECT_FALSE(result2->IsCompleted()); // Cancelled.
920 987
921 EXPECT_TRUE(result3->IsCompleted()); 988 EXPECT_TRUE(result3->IsCompleted());
922 EXPECT_EQ(net::OK, result3->GetResultCode()); 989 EXPECT_EQ(net::OK, result3->GetResultCode());
923 EXPECT_EQ("pac-v1.request3:80", 990 EXPECT_EQ("pac-v1.request3:80",
924 result3->GetProxyInfo().proxy_server().ToURI()); 991 result3->GetProxyInfo().proxy_server().ToURI());
925 } 992 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698